On Thursday, July 5, 2012 5:34:13 AM UTC-5, fpee wrote:
>
> Hello puppet masters, I am cleaning up some puppet modules, using 
> puppet-lint. The warning I am getting is: 
>
> top-scope variable being used without an explicit namespace 
>
> I can turn this particular check off, but in doing my research I'm 
> finding all sorts of messages saying to avoid using +=


Good advice.
 

> , to avoid using 
> variables in the node scope,


Good advice, but sometimes difficult to apply.
 

> and to switch to a parameterized class 
> whenever possible.


Bad, *bad* advice.  PuppetLabs did a pretty good job of promoting 
parametrized classes when it first introduced them, but the design was 
deeply flawed.  The idea clashes with Puppet's model of classes as 
singletons, and the worst of the flaws spring from that mismatch.  Only if 
you're using an ENC should you even consider class parametrization (a 
manifest set designed with an ENC in mind can in principle overcome the 
worst problems attending class parametrization), but think twice even then.

Puppet 3 does better by tying class parameters to hiera, allowing class 
parameters to serve as a structured shortcut to external data, and 
providing a means to wean all the poor folks that invested development time 
in parametrized classes.  Even if you're aiming for Puppet 3, however, your 
effort would be better spent on externalizing data for access via hiera 
than on parametrizing your classes.

 

> Okay, I'm game. 
>
> So, to understand what I'm doing, I'm setting up a yum repository and 
> limiting the includepkgs line to the very minimum amount of packages for 
> reasons of security / policy / insanity / etc. 
>
> Here is the current implementation of this (which works fine). 
>
> node standard { 
>    $epel_includepkgs += 'puppet augeas-libs facter ruby-augeas ruby-shadow 
> ' 
>    class { 'repo_epel': stage => 'pre' } 
>    #other stuff 
> } 
>

The worst thing about run stages in Puppet 2 is that you can only use them 
via the parametrized class syntax, which brings the worst problems of 
parametrized classes even to non-parametrized classes.  Of course, run 
stages are purely syntactic sugar anyway.
 

> node 'my.node1' inherits standard { 
>    include denyhosts 
> } 
>
> node 'my.node2' inherits standard { 
>    include denyhosts 
>    include gitlabhq 
> } 
>
> class repo_epel { 
>    yumrepo { 'epel': 
>      enabled         => 1, 
>      descr           => 'Extra Packages for Enterprise Linux 6 - 
> \$basearch', 
>      mirrorlist      => 
> 'https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=\$basearch', 
>      failovermethod  => priority, 
>      gpgcheck        => 1, 
>      gpgkey          => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6', 
>      require         => File['/etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6'], 
>      includepkgs     => $epel_includepkgs, 
>    } 
>    # other stuff 
> } 
>
> class denyhosts { 
>    $epel_includepkgs += 'denyhosts ' 
>    # other stuff 
> } 
>
> class gitlabhq { 
>    $epel_includepkgs += 'libyaml gitolite git-all rvm ' 
>    # other stuff 
> } 
>
> my.node1, and my.node2 will have different (and correct) includepkgs 
> doing it this way (I have like .. 30+ modules for epel and more of other 
> repos to give you an idea) 
>


If that's so then you are relying on a Puppet bug, or perhaps you have 
oversimplified your example.  The language guide specifically states that 
the += operator affects the observed value of the affected variable only in 
the scope where the plussignment is performed.  You definitely should not 
see the modified value in classes that are not declared in the scope of the 
plussignment.

 

> To get rid of the error I tried making the variable $::epel_includepkgs, 
> but that generates the error: 
> err: Could not parse for environment production: Cannot assign to 
> variables in other #namespaces


Right, because plussignment doesn't change the values of existing 
variables.  It merely shadows those values with supplemented ones, and only 
within the scope where the plussignment appears.  Dynamic scoping allows 
classes and resources to see that local value when their declarations 
appear in the same scope or a deeper-nested one, but that's a problem 
because classes can be included more than once, from different scopes.  If 
those scopes provide different values for the same, needed variable then 
which one does such a class use?  For all intents and purposes, it's 
unpredictable.
 

> So what is the 'proper' puppet way to accomplish this? 
>

Puppet DSL does not provide a mechanism for constructing values 
incrementally.  Even what you're currently doing probably doesn't work 
quite the way you think it does.  There are ways to approach it if you can 
assume strict nesting of all the scopes that are expected to contribute 
values, but that's not your case.

One messy, but valid way to do this might be to manage the inclusion of 
packages in a repo's includepkgs via instances of a defined type that 
relies on an exec.  Each instance of that type would ensure that or more 
included packages were listed for the specified repo, and they could all be 
declared independently, wherever the package itself is declared.  Then 
don't manage the 'includepkgs' property of the Yumrepo resource so that you 
don't have clashes.

Alternatively, you could probably write a couple of custom functions to 
manage a named, updatable data cubbyhole to use the way you are currently 
using plussignment.  That would silence the warnings, but you would still 
have to deal with the issue of ensuring that all the needed values had been 
appended before the result was read out.  I think you could work out 
something in that regard via class inheritance.

Or you could switch to Ruby DSL, at least in strategic places.  That would 
give you more freedom, but you would still need to handle the problem of 
accumulating all the needed values before reading them out.


John

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Users" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/puppet-users/-/J2DtcXbtDFMJ.
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