melvil james
melvil james

Reputation: 611

Puppet calls same service in multiple module?

I have a puppet module A. In that module I have a service restart for a change in file.

class A::test1 { 
  include ::corednsclient
  service { 'sshd':
    ensure => running,
    enable => true,
  }
}

Now , I have a different puppet module B. In that module also I have to restart the same service for a change in another file.

Now , the problem is that I'm getting the following:

Duplicate declaration error

when I'm doing /opt/puppetlabs/bin/puppet apply --modulepath=/abc xyz/site.pp

If I runs each module independently as puppet apply -e 'include moduleA' and puppet apply -e 'include moduleB' , Both would works fine. But puppet apply globally seems to be failing.

Any help would be highly appreciated !

Error: Evaluation Error: Error while evaluating a Resource Statement,
 Duplicate declaration: Service[sshd] is already declared in file 
 /export/content/ucm/puppet/modules/coresshd/manifests/configure.pp:28; cannot
 redeclare at 
 /export/content/ucm/puppet/modules/corednsclient/manifests/daemon_reload.pp:10 at 
 /export/content/ucm/puppet/modules/corednsclient/manifests/daemon_reload.pp:10:3 on 
 node lor1-0002276.int.xxx.com .

Upvotes: 1

Views: 1872

Answers (1)

Alex Harvey
Alex Harvey

Reputation: 15472

Yes, this is normal. Puppet only allows resources to be declared once. In general, if you have code like:

class aaa {
  notify { 'xxx': message => 'yyy' }
}

class bbb {
  notify { 'xxx': message => 'yyy' }
}

include aaa
include bbb

Puppet apply that and you will see an error like this:

Error: Evaluation Error: Error while evaluating a Resource Statement,
 Duplicate declaration: Notify[xxx] is already declared at (file: ...test.pp, 
 line: 2); cannot redeclare (file: ...test.pp, line: 6) (file: ...test.pp, line: 6,
 column: 3) on node ...

Workarounds

Solution 1 Refactor so both classes inherit a third class

Generally, the best way to resolve this is to refactor your code so that there is a third class that contains the duplicated resource, and other classes include that using the include function, like this:

class ccc {
  notify { 'xxx': message => 'yyy' }
}

class aaa {
  include ccc
}

class bbb {
  include ccc
}

include aaa
include bbb

That works fine.

Note that this only works because the include function can be called any number of times, unlike a resource declaration - also unlike the resource-like class declarations.

You can read more about "include-like v resource-like class declarations" here.

Solution 2 Use virtual resources

You can also use virtual resources. Refactor like this:

class ccc {
  @notify { 'xxx': message => 'yyy' }
}

class aaa {
  include ccc
  realize Notify['xxx']
}

class bbb {
  include ccc
  realize Notify['xxx']
}

include aaa
include bbb

An added advantage of this one is you can use resource collectors and select only specific resources from a set of virtual resources, like this:

class ccc {
  @notify { 'ppp': message => 'xxx' }
  @notify { 'qqq': message => 'yyy' }
  @notify { 'rrr': message => 'zzz' }
}

class aaa {
  include ccc
  Notify <| message == 'xxx' |>
}

class bbb {
  include ccc
  Notify <| message == 'xxx' or message == 'yyy' |>
}

include aaa
include bbb

If you don't need this functionality here, as appears the case, you probably should use the first proposal.

Solution 3 Use ensure resource

Another option is the ensure_resources function in stdlib:

class aaa {
  ensure_resources('notify', {'xxx' => {'message' => 'yyy'}})
}

class bbb {
  ensure_resources('notify', {'xxx' => {'message' => 'yyy'}})
}

include aaa
include bbb

Solution 4 Use defined

Historically this is strongly advised against, although the docs do not mention any reason to not use it. It is possible to use the defined like this:

class aaa {
  if ! defined(Notify['xxx']) {
    notify { 'xxx': message => 'yyy' }
  }
}

class bbb {
  if ! defined(Notify['xxx']) {
    notify { 'xxx': message => 'yyy' }
  }
}

include aaa
include bbb

This way, the resource is added to the catalog only if it is not already in there.

Upvotes: 4

Related Questions