Skip to content

Instantly share code, notes, and snippets.

@abrader
Last active June 21, 2017 17:54
Show Gist options
  • Select an option

  • Save abrader/afa87a5c35b3f32c43de99a10c564689 to your computer and use it in GitHub Desktop.

Select an option

Save abrader/afa87a5c35b3f32c43de99a10c564689 to your computer and use it in GitHub Desktop.
Properties

Properties

Here’s where we define how the resource really works. In most cases, it’s the properties that interact with your resource’s providers. If you define a property named owner, then when you are retrieving the state of your resource, then the owner property will call the owner method on the provider. In turn, when you are setting the state (because the resource is out of sync), then the owner property will call the owner= method to set the state on disk.

There’s one common exception to this: The ensure property is special because it’s used to create and destroy resources. You can set this property up on your resource type just by calling the ensurable method in your type definition:

    Puppet::Type.newtype(:database) do
      ensurable
      ...
    end

This property uses three methods on the provider: create, destroy, and exists?. The last method, somewhat obviously, is a boolean to determine if the resource current exists. If a resource’s ensure property is out of sync, then no other properties will be checked or modified.

You can modify how ensure behaves, such as by adding other valid values and determining what methods get called as a result; see existing types like package for examples.

The rest of the properties are defined a lot like you define the types, with the newproperty method, which should be called on the type:

    Puppet::Type.newtype(:database) do
      ensurable
      newproperty(:owner) do
        desc "The owner of the database."
        ...
      end
    end

Note the call to desc; this sets the documentation string for this property, and for Puppet types that get distributed with Puppet, it is extracted as part of the Type reference.

When Puppet was first developed, there would normally be a lot of code in this property definition. Now, however, you normally only define valid values or set up validation and munging. If you specify valid values, then Puppet will only accept those values, and it will automatically handle accepting either strings or symbols. In most cases, you only define allowed values for ensure, but it works for other properties, too:

    newproperty(:enable) do
      newvalue(:true)
      newvalue(:false)
    end

You can attach code to the value definitions (this code would be called instead of the property= method), but it’s normally unnecessary.

For most properties, though, it is sufficient to set up validation:

    newproperty(:owner) do
      validate do |value|
        unless value =~ /^\w+/
          raise ArgumentError, "%s is not a valid user name" % value
        end
      end
    end

Note that the order in which you define your properties can be important: Puppet keeps track of the definition order, and it always checks and fixes properties in the order they are defined.

Customizing Behaviour

By default, if a property is assigned multiple values in an array:

It is considered in sync if any of those values matches the current value. If none of those values match, the first one will be used when syncing the property. If, instead, the property should only be in sync if all values match the current value (e.g., a list of times in a cron job), you can declare this:

    newproperty(:minute, :array_matching => :all) do # :array_matching defaults to :first
      ...
    end

You can also customize how information about your property gets logged. You can create an is_to_s method to change how the current values are described, should_to_s to change how the desired values are logged, and change_to_s to change the overall log message for changes. See current types for examples.

Handling Property Values

Handling values set on properties is currently somewhat confusing, and will hopefully be fixed in the future. When a resource is created with a list of desired values, those values are stored in each property in its @should instance variable. You can retrieve those values directly by calling should on your resource (although note that when :array_matching is set to :first you get the first value in the array, otherwise you get the whole array):

    myval = should(:color)

When you’re not sure (or don’t care) whether you’re dealing with a property or parameter, it’s best to use value:

    myvalue = value(:color)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment