I need to perform some action (configure something) after stopping the tomcat service. Once the configuration is complete, I need to ensure that the tomcat service is up and running again. I have written following puppet code for the same:
Service {'tomcat': ensure => stopped }
->
class {'config':}
->
Service {'tomcat': ensure => running }
On puppet apply, it is complaining that
'Error: Duplicate declaration: Service[tomcat] is already declared in file'
How to fix this problem. What is the recipe in puppet to stop a service, perform some action and then bring back the service again?
In puppet, you can't declare same service again. that's the error you have.
With puppet, you needn't care of tomcat stop/start processes. It takes care the final status (called "idemotency"). After you define the relationship between package, config files and services, it will do all jobs for you. For example, you need to understand below processes in puppet and the differences between ->
and ~>
.
Package['tomcat'] -> File['server.xml'] ~> Service['tomcat']
In your case, you apply the change in tomcat config file, and puppet will restart the tomcat services automatically.
For your reference, here is the copy-paste from Introduction to Puppet blog to explain what's the meaning of idempotency:
One big difference between Puppet and most other tools is that Puppet configurations are idempotent, meaning they can safely be run multiple times. Once you develop your configuration, your machines will apply the configuration often — by default, every 30 minutes — and Puppet will only make any changes to the system if the system state does not match the configured state.
Update 2016:
Here another official Puppet blog post on idempotency: https://puppet.com/blog/idempotence-not-just-a-big-and-scary-word
This is not directly possible with Puppet, as @BMW concludes correctly. There are some more points to note, however.
There is some promising work in progress that will add limited support for transitional state declaration. However, this will not (in its current alpha state at least) allow you to enter such a state in preparation for and during application of a whole class.
A common workaround for this kind of issue is to manage the entity in question with two or more resources. The exec
type is a good catch all solution because it can manage virtually anything. The obvious drawback is that the exec
will have to be tailored to your agents (what do you know - there's a point to Puppet's type system after all ;-). Assuming that the manifest will be for one platform only, this is simple:
exec {
'stop-tomcat':
command => 'service tomcat stop',
onlyif => 'service tomcat status',
before => [
Class['config'],
Service['config'],
],
}
Ordering the exec
before Service['config']
is redundant (because the service
requires the class
), but it is good practice to express that the service
resource should have the final say.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With