Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In puppet, how to stop a service, perform some action and then start the service?

Tags:

puppet

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?

like image 884
Anand Patel Avatar asked Dec 24 '14 11:12

Anand Patel


2 Answers

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

like image 71
BMW Avatar answered Oct 14 '22 00:10

BMW


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.

like image 32
Felix Frank Avatar answered Oct 13 '22 22:10

Felix Frank