Develop types and providers with the Resource API
The recommended method to create custom types and providers is to use the Resource API, which is built on top of Puppet core. It is easier, faster, and safer than the old types and providers method.
Writing the type and provider
Write a type to describe the resource and define its metadata, and a provider to gather information about the resource and implement changes.
Writing the type
name
and ensure
attributes. You
can modify their description and the name's type to match your resource. Add more attributes
as you need. # lib/puppet/type/yum.rb
require 'puppet/resource_api'
Puppet::ResourceApi.register_type(
name: 'yum',
docs: <<-EOS,
This type provides Puppet with the capabilities to manage ...
EOS
attributes: {
ensure: {
type: 'Enum[present, absent]',
desc: 'Whether this apt key should be present or absent on the target system.',
default: 'present',
},
name: {
type: 'String',
desc: 'The name of the resource you want to manage.',
behaviour: :namevar,
},
},
)
-
type
: the Puppet 4 data type allowed in this attribute. You can use all data types matchingScalar
andData
. -
desc
: a string describing this attribute. This is used in creating the automated API docs with puppet-strings. -
default
: a default value used by the runtime environment; when the caller does not specify a value for this attribute. -
behaviour
/behavior
: how the attribute behaves. Available values include:-
namevar
: marks an attribute as part of the primary key or identity of the resource. A given set ofnamevar
values must distinctively identify an instance. -
init_only
: this attribute can only be set during the creation of the resource. Its value is reported going forward, but trying to change it later leads to an error. For example, the base image for a VM or the UID of a user. -
read_only
: values for this attribute are returned byget()
, butset()
is not able to change them. Values for this should never be specified in a manifest. For example, the checksum of a file, or the MAC address of a network interface. -
parameter
: values for this attributes are not returned byget()
. You can use this attribute to influence how the provider behaves. For example, you can influence themanagehome
attribute when creating a user.
-
Writing the provider
pdk new
provider
command, PDK generates a provider file
like this generated yum.rb
file
require 'puppet/resource_api/simple_provider'
# Implementation for the yum type using the Resource API.
class Puppet::Provider::Yum::Yum < Puppet::ResourceApi::SimpleProvider
def get(_context)
[
{
name: 'foo',
ensure: 'present',
},
{
name: 'bar',
ensure: 'present',
},
]
end
def create(context, name, should)
context.notice("Creating '#{name}' with #{should.inspect}")
end
def update(context, name, should)
context.notice("Updating '#{name}' with #{should.inspect}")
end
def delete(context, name)
context.notice("Deleting '#{name}'")
end
end
The optional initialize
method can be used to set
up state that is available throughout the execution of the catalog. This is most often used
for establishing a connection when talking to a service, such as when you are managing a
database.
get(context)
method returns a list of hashes
describing the resources that are on the target system. The basic example would return an
empty list. For example, these resources could be returned from this:
[
{
name: 'a',
ensure: 'present',
},
{
name: 'b',
ensure: 'present',
},
]
The create
, update
,
and delete
methods are called by the SimpleProvider
base class to change the system as requested
by the catalog. The name
argument is the name of
the resource that is being processed. should
contains the attribute hash — in the same format as get
returns — with the values in the catalog.
-
For small sized blocks of code, put the code in the provider.
-
For medium sized blocks of code, put the code into a separate file in
lib/puppet_x/$forgeuser/$modulename.rb
.puppet_x
is optional, but it helps keep the file name unique and reduces the risk of a file overwriting code from an unknown dependency. -
For large sized blocks of code, put the code in a separate gem.
Unit testing
The generated unit tests in spec/unit/puppet/provider/<PROVIDER_NAME>_spec.rb
are evaluated when
you run pdk test unit
.