Creating resources
You can write resource types and providers in the Puppet language. The following example shows you how to create resources in Puppet using the low-level types and provider method.
Puppet’s property support has a helper method called
ensurable
that handles modeling creation and destruction; it
creates an ensure
property and adds absent
and
present
values for it, which require three methods on the provider,
create
, destroy
, and exists?
.
The following example is a resource called file
. The
resource contains the type name (file
), a documentation string, a
parameter for the name of the file, and used the ensurable method to say that the file
is both createable and destroyable.
Puppet::Type.newtype(:file) do
@doc = "Manage a file (the simple version)."
ensurable
newparam(:name) do
desc "The full path to the file."
end
end
The following example is a provider. The provider contains the docs, the provider name,
and the three methods that the ensure
property requires. Note that it
uses a desc
instead of @doc =
to specify the
documentation. It also uses Ruby’s built-in file
abilities to create an empty file, remove the file, or test whether the file exists.
Puppet::Type.type(:file).provide(:posix) do
desc "Normal Unix-like POSIX support for file management."
def create
File.open(@resource[:name], "w") { |f| f.puts "" } # Create an empty file
end
def destroy
File.unlink(@resource[:name])
end
def exists?
File.exists?(@resource[:name])
end
end
newproperty(:mode) do
desc "Manage the file's mode."
defaultto "640"
end
Note that the default value is specified, and it is a string instead of an integer (file
modes are in octal). You can pass a lambda to defaultto
instead of a
value, if you don’t have a simple value.
To understand modes, add the following code to the provider:
def create
File.open(@resource[:name], "w") { |f| f.puts "" } # Create an empty file
# Make sure the mode is correct
should_mode = @resource.should(:mode)
unless self.mode == should_mode
self.mode = should_mode
end
end
# Return the mode as an octal string, not as an integer.
def mode
if File.exists?(@resource[:name])
"%o" % (File.stat(@resource[:name]).mode & 007777)
else
:absent
end
end
# Set the file mode, converting from a string to an integer.
def mode=(value)
File.chmod(Integer("0" + value), @resource[:name])
end
The getter method returns the value, but does not attempt to modify the resource itself. When the setter gets passed, the value it is supposed to set — it does not attempt to figure out the appropriate value to use.
Note that the ensure
property, when created by the
ensurable
method, behaves differently because it uses methods for
creation and destruction of the file, compared to normal properties that use getter and
setter methods. When you create a resource, Puppet
expects the create
method to make any other necessary changes. This is
because resources are already configured when created, so Puppet does not need to test them manually.
The absent
and present
values are defined by looking in
the property.rb
file:
newvalue(:present) do
if @resource.provider and @resource.provider.respond_to?(:create)
@resource.provider.create
else
@resource.create
end
nil # return nil so the event is autogenerated
end
newvalue(:absent) do
if @resource.provider and @resource.provider.respond_to?(:destroy)
@resource.provider.destroy
else
@resource.destroy
end
nil # return nil so the event is autogenerated
end