[Puppet Users] Re: Two parameterized classes calling both a thirth class (results in already defined)

jcbollinger
2011-09-22T13:14:30Z

On Sep 21, 3:06 pm, rvlinden <rene.vanderlinde...@gmail.com>
wrote:
> Hi all,
>
> I have three parameterized classes, named mq, mq_gsk and apache.
> The mq class always calls the mq_gsk class, but the apache class
> should only call the mq_gsk class when the mq class is not used in a
> hosts'' node definition
>
> Here is my configuration
>
> class mq (
>   $gsk_version = undef ) {
>
>   require mq::params
>
>   <  ..... >
>
>   class { ''mq_gsk'':
>     gsk_version => "${mq::params::package_gsk_version}",
>   }
>
> }
>
> class mq_gsk (
>   $gsk_version = undef ) {
>
>   require mq_gsk::params
>
>   package { $mq_gsk::params::gsk_packages:
>     ensure  => "${mq_gsk::params::package_gsk_version}",
>   }
>
> }
>
> When a node needs to be configured as an MQ server, the mq class will
> be included and mq and the mq gsk software will be installed. However
> some servers only need to have an Apache server installed, but apache
> uses an additional plugin which requires the mq gsk software also.
>
> If I configure a host with either MQ or Apache all is well, but as
> soon as both classes are included in a node, I get a duplicate /
> already defined error (as expected)
>
> ERROR:
> Could not retrieve catalog from remote server: Error 400 on SERVER:
> Duplicate definition: Class[Mq_gsk] is already defined in file /etc/
> puppet/modules/apache/manifests/init.pp at line 104; cannot redefine
> at /etc/puppet/modules/mq/manifests/init.pp:62 on node
> nodex.domainy.com
>
> Within my apache class, I tried to use "if defined()", but this
does
> not seem to work at all
>
> Here is one of my many attempts
>
>  if defined(Package["mq_gsk"]) {
>    notice ( "${apache::params::module_name}, mq module defined, mq_gsk
> already included" )
>  } else {
>    notice ( "${apache::params::module_name}, mq module not defined,
> check websphere module defined" )
>    if
defined(Package["${apache::params::package_name_module_was}"]) {
>      notice ( "${apache::params::module_name}, websphere module
> defined, mq_gsk included" )
>      class { ''mq_gsk'':
>        gsk_version => undef,
>      }
>    }
>  }
>
> I also tried other things which I read on Puppet Users, like
>
> if defined("mq_gsk") {
> if defined("mg_gsk::gsk_version") {
>
> but nothings seems to work. It always says that the mq module is
> defined (while the mq class is not included in the host definition) or
> it says not included (while the mq class is included in the node)
>
> I wonder I ''defined'' is to way forward, of if there is a
better way to
> solve the ''already defined'' issue.
>
> I''m using puppet 2.7.3 on CentOS/RHEL 5.7

The easiest solution from where you are now might be to remove the
parameterization from class mg_gsk.  An unparameterized class may be
included any number of times on the same node with no problem.  If the
class needs to be fed external data then do so via extlookup, hiera,
or a fully-qualified class- or top-level variable.

I am certain that this sort of problem is one of the reasons that the
Puppetlabs''s current style recommendations say that classes should not
include other classes.  That''s a very inconvenient constraint,
however, even if you are using an ENC.  In fact, it introduces a
strong coupling between class design and ENC implementation (and/or
node declarations) that isn''t helpful to anyone.

In general, you have a manifest design problem if your manifests ever
have to ask whether a class has been assigned to a node.  Doubly so if
the purpose is to determine whether to assign that class at that
point.


John