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.