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 [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/puppet-users?hl=en.