On Jun 30, 6:15 am, Martijn Grendelman <mart...@iphion.nl> wrote:
> Hi,
>
> 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.


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

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

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.


John

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