Hi,
I am bringing up this topic because of a recent discussion and PR for the ticket https://tickets.puppetlabs.com/browse/PUP-1486

Here is a recap.

The Resources resource is used to "manage unmanaged" resources of a particular given type - e.g. to purge users, groups etc. that are not otherwise managed.

The issues are that "managing the unmanaged" may require additional attributes that are specific to the type that is referenced. The base type only has the attributes "unless_system_user" and "unless_uid" (se https://docs.puppetlabs.com/references/latest/type.html#resources for the documentation).

At times it is suggested that the Resources type should have additional attributes that are specific only to one type. This solution has the obvious problem that over time, the Resource type would then have a very large number of attributes for different types and the temptation will be great to borrow attributes and apply similar semantics. Over time this solution will become unmanageable.

Another solution was proposed in PR-3269 (https://github.com/puppetlabs/puppet/pull/3269) which we closed for various reasons.

The approach in the PR was to add a "newresourcesparam" to Puppet::Type
allowing this to define additional parameters to the Resources type.
An obvious problem with this approach is the need to load all types in order to check the validity of attributes of a Resources instance.

Instead, I would like to see something where the concerns are separated (to avoid the problem of "the base class knows about all the things"). One good pattern is "the strategy pattern" / "adapter pattern" which is used internally in the future parser. (You can read about this here: http://puppet-on-the-edge.blogspot.se/2014/02/puppet-internals-adapter-pattern.html). TL;DR - an adapter is responsible for "sticking a label" on someone else without that someone having to be concerned about its existence, protocol etc.

How can we achieve something similar in a simple way in Puppet?

One very simple approach is to add the basic ability to handle such "adapters", or "extra data" if you like, in the Resources type. We cannot use the actual adapter pattern since when it comes to resources, they are serialized and processed in ways that would drop such adapters (since those are really a runtime concept).

Proposal:

* Add the attribute options (with the type Array[Resource])
* Add the ability in a resource type to specify a list of type names that it allows instances of as options (typically one)
* Add the ability in type to get the options.

Here is a simulation of the above using just user defined types - a type "base" specifies that it takes an "option" that must be a reference to a "Base_option":

    define base_options($p1, $p2) {
    }

    define base(Resource[base_option] $option = undef) {
    }

    base { 'the_base':
      extraref => Base_options[the_options]
    }

    base_options { the_options:
      p1 => 'extra 1',
      p2 => 'extra 2'
    }

This way, everything ends up in the catalog. The same using Resources would look like this:

    resources { base:
      options => [Base_options[the_options]]
    }

How the rest of the protocol between Resources and the types that support options should work is left to be designed, but basically; the Resources implementation should present the options to the type either for just asking if a particular resource should be purged or not (as it does now but done as a delegation to the particular type).

I think this design is:

* type safe - it is possible to statically check the combination of the managed type, the options it supports, and the type of the entries in options. * The optional type can be a user defined type - all that is needed are the parameter values specified by the user.
* A user defined type can be name-spaced

Alternative - using the type system in Puppet 4.0

Another alternative is to simply use the new type system in Puppet 4.0.
A type that supports options to Resources returns a Struct type that describes the options. (A Struct is a detailed type specification of a hash). (Read more about the Struct type here: http://puppet-on-the-edge.blogspot.se/2014/02/adding-struct-and-tuple-to-puppet-type.html)

In the catalog a Struct type is simply encoded as a String, and it is easily converted back to an instance of the type which can be used for type checking the options received from the Resources type.

Thoughts?
- henrik

--

Visit my Blog "Puppet on the Edge"
http://puppet-on-the-edge.blogspot.se/

--
You received this message because you are subscribed to the Google Groups "Puppet 
Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to puppet-dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/puppet-dev/m3ems4%24qu3%241%40ger.gmane.org.
For more options, visit https://groups.google.com/d/optout.

Reply via email to