Hi,

I am bringing back a topic that I started a month ago. Summer holidays
prevented me from following up on it back then, but they didn't make the
problem go away, unfortunately ;-)

>> Having installed Puppet 2.7.1 on my testserver yesterday, I am now bugged
>> by log messages, that tell me not to use dynamic variable lookups:
>>
>> Jun 29 13:31:09 os1 puppet-master[31910]: Dynamic lookup of
>> $ssh_permitrootlogin at /etc/puppet/templates/etc/ssh/sshd_config.erb:28
>> is deprecated.  Support will be removed in Puppet 2.8.  Use a
>> fully-qualified variable name (e.g., $classname::variable) or
>> parameterized classes.
>>
>> Now, I have been reading up on variable scoping and trying to figure out
>> how to rewrite my manifests to embrace best practices, but I am confused
>> on how to proceed, and I can't really find any working examples, so I turn
>> here for help.
>>
>> My current setup is something like this:
>>
>> node basenode {
>>     $somevar      = "defaultvalue"
>>     $someothervar = "anotherdefault"
>>
>> }
> 
> 
> [...]
> 
> 
>> In any class or module I use $somevar and $someothervar as I please, and I
>> understand that this a) is not a recommended practice and b) will stop
>> working in Puppet 2.8.
>>
>> So, what should I do?
> 
> 
> It's not actually clear to me whether "top level" includes inside node
> declarations, but IMHO it should.  If it does, and if you do not rely
> on defining different values for $somevar or $someothervar inside your
> classes (see below), then you should be able to solve your problem by
> changing all appearance of $somevar and $someothervar to $::somevar
> and $::someothervar (i.e. use their fully-qualified names as the
> warning suggests).  It should be pretty easy to test whether that
> works for you.

In classes that have been defined in the top scope (imported in site.pp),
I can use the fully qualified names ($::somevar). That results in the
correct value, and it doesn't generate any warnings about dynamic scoping.

However, inside modules, this doesn't work. I get empty values when I try
that. For example:

In nodes.pp:

node basenode {
    $syslocation = "Server room"
}

node testserver inherits basenode {
    $syslocation = "Martijn's office"
}

In modules/snmp/manifests/init.pp:

    notify { "System location: $syslocation": }
    notify { "System location qualified: $::syslocation": }

results in:

notice: System location qualified:
notice: /Stage[main]/Snmp/Notify[System location qualified: ]/message:
defined 'message' as 'System location qualified: '

notice: System location: Martijn's office
notice: /Stage[main]/Snmp/Notify[System location: Martijn's
office]/message: defined 'message' as 'System location: Martijn's office'

The 'dynamic' name works (but gives a warning), the  fully-qualified name
doesn't work. The use of curly braces ${::syslocation} doesn't make any
difference.

>> Switching to parameterized classes sounds nice, but that would mean that
>> the 'generic' class would have to get /every/ variable I use as a
>> parameter and pass it on to subsequent classes where needed. That sounds
>> incredibly clumsy to me.
> 
> 
> As regulars here will know, I am not a big fan of parameterized
> classes.  Puppetlabs likes them, and pushes them, but I think they are
> rarely the best tool for the job.  Perhaps the thing that they are
> most appropriate for, however, is avoiding dynamic scoping.  More on
> that below.
> 
> You are right that for your manifest design, solving the problem via
> class parameterization would require your Class["generic"] to be
> parameterized with all the variables it uses directly plus all those
> needed by the classes it includes.  I think this is one reason that
> Puppetlabs' style guide now recommends avoiding classes including
> other classes.  Once your manifests become complex enough that that is
> painful, they suggest using an external node classifier.  If you don't
> buy in to parameterized classes, however, then that advice does not
> stand up so well.
> 
> 
>> Inhttp://docs.puppetlabs.com/guides/scope_and_puppet.htmlI read:
>>
>>   "If you re using dynamic scope to share resource defaults, there s no
>> way around it: you ll have to repeat yourself in each file that the
>> defaults apply to."
>>
>> Is this what's biting me here? Well, this sounds like something I can live
>> with, after all: it's not the default values I care about, it's the
>> overriding values.
> 
> 
> Forgive me for being didactic:
> 
> In Puppet < 2.8.0, variables declared outside any class can be
> overridden by declarations of the same variable name within classes.
> Within a class that does so and any class it includes, recursively,
> the variable's unqualified name resolves to the class's definition,
> not the top-level one.  Except that this nests, so that if an included
> class also defines a variable having the same simple name, then it and
> its included classes see *its* definition.  This is called "dynamic
> scoping".
> 
> Dynamic scoping presents at least two problems:
> 
> 1) When a class refers to externally defined variables by their simple
> names, it is hard to know what definition of the variable you're going
> to get.  That's not such a big deal, though, and it could even be
> considered an advantage -- the external variables a class uses can be
> considered de facto parameters for it.
> 
> 2) Classes can be included multiple times, by more than one path, and
> there is no guarantee that the values they see for unqualified
> external variable names will be the same at each inclusion.  This can
> result in unintended behavior, but the problem is not so much that
> dynamic scoping is inherently bad, but rather that it facilitates poor
> manifest design.
> 
> Parameterized classes address problem (1) by formalizing class
> parameterization, and they address problem (2) by making it illegal to
> include a parameterized class more than once (even with the same
> parameters).  One of my main objections to parameterized classes is
> that the latter is too far-reaching and constraining.
> 
> 
>> Further, it states:
>>
>>   "If you need to apply resource defaults more broadly, you can still set
>> them at top scope in your primary site manifest. If you need the resource
>> defaults in a class to change depending on where the class is being
>> declared, you need parameterized classes."
>>
>> And we're back at parameterized classes. And what does 'top scope' mean
>> exactly? I assume that would be in 'site.pp', outside any class or node
>> definition?
> 
> 
> Outside any class or node definition and inside site.pp or any
> manifest 'import'ed by it is certainly top-level.  Surely someone else
> around here knows offhand whether anywhere else, such as inside node
> definitions, is also top-level.  Or you can test: the fully-qualified
> name of a top-level variable $somevar is $::somevar.
> 
> 
>> To make a long question short: what is the recommended way to override
>> values for certain nodes or groups of nodes (by inheritance)? And I'd
>> /really/ prefer to do that without having to pass on each and every value
>> as a parameter to the next included class...
> 
> 
> Things to consider:
> 
> 1) I personally recommend avoiding deep node inheritance hierarchies.
> In fact, I recommend no more than two levels to your node inheritance
> tree.  This may or may not help with your present problem.

We have three levels: a basenode in which we set defaults, a level for
'internal' and 'external' servers, since that is the biggest distinction
in our server park, and every node definition inherits either 'internal'
or 'external'.

> 2) As I mentioned above, you may be able to just change to fully-
> qualified variable names.  That would be quick and relatively
> painless.

Yes. But it doesn't work ;-)

> 3) There is another built-in alternative to dynamically-scoped
> variables: the extlookup() function.  Using extlookup() to retrieve
> data for your resources can allow you to minimize the number of
> parameters you need to pass, or even to avoid class parameterization
> altogether.  I think this is a great way to go, but Puppetlabs's style
> guide disfavors it.

The big question here is: would that be future-proof??

Best regards,
Martijn Grendelman

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Users" group.
To post to this group, send email to puppet-users@googlegroups.com.
To unsubscribe from this group, send email to 
puppet-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/puppet-users?hl=en.

Reply via email to