On Thu, Nov 6, 2014 at 1:36 PM, Henrik Lindberg <
henrik.lindb...@cloudsmith.com> wrote:

> 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
>

I think this design is sufficiently complex that nearly no one would be
able to use it.


> 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.


Of the two, I prefer this approach.

However, I think it's worth looking at a third approach:

Right now, the 'resources' type isn't actually special.  It uses hacks to
do its work, rather than being part of the system and treated specially.

I think we should build it, or at least its functionality, more into the
core, so that we don't have to use those hacks, and we don't have to ask
the users to do things like the above.

For instance, you could modify the system to allow attributes to Resources
that match the specified type.  This would break the current parameter
checking, but it wouldn't be too hard to do this, and it could make a lot
of sense.  With this, you'd want to be able to extend types to give
affordances to the Resources type, so you could control this from there.

E.g., rather than teaching Resources about special kinds of users, you
teach User about what a system_user is, and then you give Resources the
ability to select against that status.

A fourth option would be to combine the best of Resources and exported
resources:  Build a querying system akin to exported resources, but against
the current system, rather than against the catalog.  Or really, take the
exact same querying we already have, but provide the ability to control
where it's searching against, and what to do with the results.

This is my preferred solution.  It makes querying more powerful, and
separates the concept of querying from the source of the data.

I really do think this kind of functionality should be supported at the
framework level, and more hacks like Resources aren't the best long term
solution.


-- 
http://puppetlabs.com/ | http://about.me/lak | @puppetmasterd

-- 
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/CAGMZ2bzj5%3DKYfH2D5jLEu4Xrn1Bb%2BsFvOgH8pqH4O%2Bb8-hcGFg%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to