Search code examples
puppet

Duplicate declaration of same resource defined in separate classes


I have a class definition which requires the build-essential package:

class erlang($version = '17.3') {

  package { "build-essential": 
    ensure => installed
  }
  ...
}

Another class in a different module also requires the build-essential package:

class icu {

  package { "build-essential": 
    ensure => installed
  }
  ...
}

However, when I try to perform puppet apply, the error I receive is:

Error: Duplicate declaration: Package[build-essential] is already declared in file /vagrant/modules/erlang/manifests/init.pp:18; cannot redeclare at /vagrant/modules/libicu/manifests/init.pp:17 on node vagrant-ubuntu-trusty-64.home

I was expecting classes to encapsulate the resources they use but this doesn't seem to be the case? How can I resolve this clash?


Solution

  • This is common question when dealing with multiple modules.

    There's a number of ways of doing this, the best practise is to modularise and allow the installation of build essential as a parameter:

    class icu ($manage_buildessential = false){
    
      if ($manage_buildessential == true) {
       package { "build-essential": 
         ensure => installed
       }
     }
    }
    

    Then, where you want to include your ICU class:

    class {'icu':
       manage_buildessential => 'false',
    }
    

    However, for a quick and dirty fix:

    if ! defined(Package['build-essential']) {
        package { 'build-essential': ensure => installed }
    }
    

    Or if you have puppetlabs-stdlib module:

    ensure_packages('build-essential')