On 2014-07-07 20:54, John Bollinger wrote:


On Monday, July 7, 2014 9:39:06 AM UTC-5, henrik lindberg wrote:

    On 2014-07-07 15:43, John Bollinger wrote:
    [...]  Consider:
     >
     > class mymodule {
     >    File { group => 'example' }
     > }
     >
     > class mymodule::example {
     >    file { '/tmp/example': owner => 'root', ensure => 'file' }
     > }
     >
     > include 'mymodule::example'
     > include 'mymodule'
     >
     > File { mode => '0400' }
     >
     >
     > What should File['/tmp/example']['group'] be?  And
     > File['/tmp/example']['mode']?

    The evaluation will evaluate both classes before the default
    expression..
    The resources are thus created before the default is added. If we do go
    for eager defaults, then the two resources would not get an default
    values.



Ok, that's what I expected, but take a closer look at the classes.
Class[mymodule] declares a resource default for the File resource, and
Class[mymodule::example] declares a file instance, but the later is
'include'd before the former.  I am supposing that with eager defaults,
the File instance in Class[mymodule::example] will not see the resource
default this way, but that it would see it if the order of the 'include'
statements were reversed (following the same resolution rules as for
variables).

That reversing the order in which the classes are evaluated could change
which defaults are applied -- if indeed that's the case -- would be an
unhappy consequence.

Yes, if the default applied per named scope and be visibile in inner named scopes, then the application of defaults would need to be lazy, or you would go crazy over the order of how classes where included.

Since the implementation is to only look in the scope the resource creation takes place in, (then in an inherited scope, i.e. class inherit) and then in the global scope) it would not matter if you changed the order of the two includes.

Puppet's strictness for named scopes is very weak as they can be introduced anywhere, and in any arbitrary order, and they can be reopened and appended to. So, while it would be very useful to be able to declare defaults for a named scope and its subscopes, it leads to more problems than what it solves IMO.

     > If part of the objective is to avoid
     > binding defaults late without (re)opening the door to issues around
     > evaluation order uncertainty, then you can rely only on the local
     > lexical scope for defaults.  And yes, variable references do
    suffer from
     > that issue already.
     >
     >     I agree
     >     that this pretty much renders defaults useless as they have
    to be
     >     global
     >     or repeated per class / define. It is only useful if a define
    or class
     >     creates many resources.
     >
     >     If defaults followed lexical scope / (namespaces). Then the
    defaults
     >     would apply to the namespace it is defined in, and all inner
     >     namespaces..
     >     That would make them more useful while also safe to use. They
    would not
     >     apply to something that is included.
     >
     >
     >
     > It's not clear to me how that last alternative differs from the
    previous
     > one, nor whether it fares any better on the evaluation-order front
     > relative to my example above.

    If we do defaults per named scope and not do late binding, care has
    to be taken to introduce entities in the right order (to get them
    evaluated in the wanted order - you want to evaluate nested named
    elements after outer elements. This is probably just as confusing to
    puppet users as the current way.



I'm still not catching the distinction between that and resolving
defaults "how variables are resolved".  Probably I'm just being dense,
but perhaps I don't know how variables are resolved as well as I think I do.

Variable references are resolve like this:
* local scope (in the closure where the variable reference is)
* named scope (the named scope the variable, or closure is in)
* inherited scope - if a class inherits another, it looks in its named scope
* top / node scope

and, if a variable is qualified, it is always anchored in top scope, thus a reference to x::y is always resolved as if it had been written ::x::y.

Defaults now (future parser 3.7) follow the same rules except there is no distinction between local scope (inside a lambda) and inside a named scope. Coming back to your example, a default inside a::b, does not apply to things in a::b::c, nor a::b::d, etc.

In any case, though, it looks like you concur with me that there are
evaluation-order consequences attending these approaches.


Yes, and in different ways. The eager approach would mean that a default
setting on a line after a resource is created (even in the same body) would not apply to that resource, only resources created after that line (i.e. a "normal imperative logic style").

What I like about the Schmitt style (with my variation) is that it allows an explicit use of name spaced defaults, but you are responsible for both a) including the class that defines those defaults, and b) stating that you want those values as the default for your created resource(s).

- 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/lpf3v7%24kvs%241%40ger.gmane.org.
For more options, visit https://groups.google.com/d/optout.

Reply via email to