Puppet Duplicate declaration error

jbosspuppet

i'm running in an Error: Duplicate declaration with my puppet project. I want to deploy jboss instances, and part of them are some special config files.

As soon as i create a 2nd instance, which should contain the same special config files as the first instance, i get the mentioned error.

I create an instance like this:

jbossas::instance { 'node01':
         ...
         propfiles => [ "kupo.properties", "web.properties" ],
}

in jboss::instance is this code:

if ($propfiles != {}) {

            jbossas::makepropies { $propfiles:
                version         => $version,
                instancedir     => $instancedir,
                jboss_name      => $name,
            }
    }

and finally the makepropies code:

define jbossas::makepropies (
    $file           = $title,
    $version        = 7,
    $instancedir    = '',
    $jboss_name     = "jboss",

){
    file { "$instancedir_$jboss_name_$file" :
            ensure  => file,
            path    => $instancedir/configuration/$file,
            content => template("jbossas/jboss${version}/${file}.erb"),
            require => Jbossas::Profile[$jboss_name],
    }
}

As soon as i create a second node and want to apply the manifest the error i get is:

Error: Duplicate declaration: Jbossas::Makepropies[kupo.properties] is already declared in file /etc/puppet/modules/jbossas/manifests/instance.pp:111; cannot redeclare at /etc/puppet/modules/jbossas/manifests/instance.pp:111 on node jb7-dev.localdomain

I just started with puppet this week, so my expirience is like 0.
I've searched a lot, found virtual/realize things, but couldn't find anything that solved my problem.

Thanks in advance!

Best Answer

This is because you're defining two jbossas:makepropies resources with the same name, regardless of the name of the top-level jbossas::instance resource, so both 'node01' and 'node02' are attempting to create jbossas:makepropies with a title of 'kupo.properties'.

This is caused by Puppet's lack of full looping ability within manifests. If you declare a variable as an array, there's no way (that I know of) to loop through that array within your manifests.

You can get around this by differentiating the resource names:

jbossas::instance { 'node01':
     ...
    propfiles => [ "${name)_kupo.properties", "${name}_web.properties" ],
}

Then strip this out in jbossass:makepropies

define jbossas:makepropies (
  $version        = 7,
  $instancedir    = '',
  $jboss_name     = "jboss",
) {

  $title_array = split($title,'_')
  $file_name = $title_array[1]

  file { "${instancedir}_${jboss_name}_${file_name}" :
    ensure  => file,
    path    => "${instancedir}/configuration/${file_name}",
    content => template("jbossas/jboss${version}/${file}.erb"),
    require => Jbossas::Profile[$jboss_name],
  }

}

It's by no means the most eloquent solution, but without full loop support within Puppet, it's the best that I know of - the most programmatic solution would be to write something like this in jbossas::instance (I'm using pseudocode below):

foreach ($propfiles as $propfile) {
  jbossas::makepropies { $propfile:
    version         => $version,
    instancedir     => $instancedir,
    jboss_name      => $name,
  }
}

See this StackOverflow question for more details.