In regard to: [Puppet Users] package handling in puppet?, lamour said (at...:

I'm starting to feel like, maybe, I have a fundamentally flawed concept of
how puppet is intended to be used.  (new to puppet.  setting up initial
puppet environment.  blah blah)

so, I've got most of the pieces worked out, but I've hit a major roadblock
with the way packages are handled in puppet.  (according to my limited
understanding of puppet, that is)  The problem starts with the fact that
including the following in two different classes:

  package { 'perl': ensure => installed }

There are several ways to deal with this.

I know perl is probably a general example of the problem, but at least
in that case, it's fairly rare that you need to specify the interpreter
directly.  If you're making good use of packages, what you probably
instead want is something like

  package { 'perl-Net-SMTP-SSL':
    ensure  => installed,
    require => Yumrepo['your-local-repo-name-or-maybe-epel'],
  }

In other words, specify your "package { whatever: }" so that it asks
for the "highest level" requirement, and just let the packaging system
pull in the dependencies.  A properly packaged perl module should
automatically cause perl to be installed.

Let's say you have an unpackaged script (hint: consider packaging it!)
that relies on just the core perl modules and doesn't have any external
module dependency that you can key on, so keying on some higher level
dependency isn't going to work.

Now you're back to the cases you were considering.

For the first case:

causes this error:

  "Duplicate definition: Package[perl] is already defined"

This is pretty unfortunate, but we can try to work around it by doing this:

  package { 'test-perl': ensure => installed, alias => 'perl' }

*Definitely* do not do this.  There might be other places where this
kind of chicanery is appropriate, but it's not a good idea here.

One pretty kludgey way around it is to wrap each package definition in a
class and then just "include" the classes where I want the packages
defined.

That's the way we do it for packages where we've run into this issue, but
remember again that you generally don't need to do this for every package,
you just need to do it for cases where you can identify a package that
must be installed *but* isn't going to be pulled in automatically by your
package management system via a dependency from some *other* package
you're requiring.

 I mean, I can write a perl script to generate a class for each
package that is in my packaging system and just do it this way, but it just
feels like I'm cheating, and I have no idea what kind of overhead that
would put on puppet.

I wouldn't recommend that.  Generate only the classes that you need, and
consider subclasses too.  For example, we do have a few cases where
non-packaged scripts written by e.g. a dba require something like perl's
Foo::Bar module.  We have a class for perl and subsclasses for stuff like
perl::foo::bar.  We only need to

        include perl::foo::bar

and that has the

  package { 'perl-Foo-Bar':
    ensure => installed,
  }

*and* the actual OS package has the proper dependency to get pulled
in if needed.

Another, less gross, way to do it is to do something like this:

      if !defined(Package['perl']) {
         package { 'perl':
            ensure => installed,
         }
      }

I would instead do something more like

  file { 'your-unpackaged-perl-script-here.pl':
    ensure  => file,
    owner   => 'whomever',
    group   => 'ditto',
    mode    => '0whatever-whatever-whatever',
    require => Package['perl'],
    source  => 'puppet:///module_name/script-source-here.pl',
  }

This is kinda what I expected "ensure => installed" to mean.  The big
problem with this method is that it's so verbose that to do this for every
package I want to include would make it somewhat difficult to see which
packages I was including in a class if I had more than a few.

So do

  class your_class {

    include your_class::packages

    # other stuff here.

  }

and split your packages into the your_class::packages class.

We also stumbled across the Singleton puppet module, which does almost kind
of exactly what we want, except it has a dependency on hiera. We haven't
really decided whether to use hiera or not.  Efforts to rip the hiera
dependencies out of Singleton and also getting it to run even with hiera
installed have both failed.  I'll probably keep looking into modifying the
ruby code to behave in some useful manner for us, but for now, I'm running
out of good options.

Don't rip out hiera, it will be part of puppet 3.x.  I'm not familiar with
the Singleton module, but I wouldn't think you would need to resort to
external modules for something that's pretty fundamental to the problem
domain.

Another option that some have used in this situation is virtual resources
for packages, e.g.

  class all_packages {

    @package { 'perl': }
    @package { 'perl-Foo-Bar': }

  }

and

  class your_class {

    realize(Package['perl-Foo-Bar'])

  }

That might be worth considering.  We're not doing it that way, but
perhaps we should be.

So...what am I doing wrong?  Does the puppet philosophy not really allow
for maintaining package lists in classes?

It does, but in my experience it should be done in a minimal fashion.
Specify the highest level dependency, and let the OS package management
system pull in the prereqs, rather than trying to repeat all of the same
relationships in your puppet classes.

Tim
--
Tim Mooney                                             tim.moo...@ndsu.edu
Enterprise Computing & Infrastructure                  701-231-1076 (Voice)
Room 242-J6, IACC Building                             701-231-8541 (Fax)
North Dakota State University, Fargo, ND 58105-5164

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