mike.schmidt
mike.schmidt

Reputation: 173

puppet 4.7 - how can I execute something at the end of a run?

I need to execute something as the very last thing of a puppet apply run. I tried to do that by defining a stage 'last', but the syntax restrictions on declaring a class in resource mode are a problem.

Is there a good way to use stages like this? Or is there some other way to make sure some class is executed last?

for example, this gives me an error for a duplicate declaration(sometimes, and I'm not sure why at this point):

class xyz::firstrun {

  exec { 'exec_firstrun':
    onlyif => '/usr/bin/test -e /tmp/firstrun.sh',
    command => '/tmp/firstrun.sh',
    path => ['/usr/bin/','/usr/sbin'],
    creates => '/tmp/firstrun.done',
  }

}

class { 'xyz::firstrun':
    stage => last,
}

Sometimes, the firstrun class runs without error, but in the main stage.

Upvotes: 2

Views: 4038

Answers (2)

John Bollinger
John Bollinger

Reputation: 180201

I'm not a big fan of run stages, but they are the the right tool for this job. It's a bit unclear exactly what gives you the duplicate declaration error you describe, but if, for example, your class definition and class declaration both appear in the same file, then that might be a problem.

Here's how a solution using run stages might look:

environments/production/modules/site/manifests/stages.pp

class site::stages {
  stage { 'last':
    # Stage['main'] does not itself need to be declared
    require => Stage['main'],
  }
}

environments/production/modules/xyz/manifests/firstrun.pp

class xyz::firstrun {

  exec { 'exec_firstrun':
    onlyif => '/usr/bin/test -e /tmp/firstrun.sh',
    command => '/tmp/firstrun.sh',
    path => ['/usr/bin/','/usr/sbin'],
    creates => '/tmp/firstrun.done',
  }

}

environments/production/manifests/nodes.pp

node 'foobar.my.com' {
  include 'site::stages'
  include 'something::else'

  # Must use a resource-like declaration to assign a class to a stage
  class { 'xyz::firstrun':
    stage => 'last'
  }
}

Note that although include-like class declarations are generally to be preferred, you must use a resource-like declaration to assign a class to a non-default stage. You must therefore also be careful to avoid declaring such classes more than once.

Upvotes: 4

Atmesh Mishra
Atmesh Mishra

Reputation: 549

You can use puppet relationship and ordering to do this. (1) If you want to execute the entire class at the end, you can include your class in init.pp and user ordering arrow (->) to execute it after all other classes.

example:

file: /etc/puppet/modules/tomcat/init.pp

class tomcat {

  include ::archive
  include ::stdlib

  class { '::tomcat::tomcatapiconf': }->

  class { '::tomcat::serverconfig': }
}

(2) If you want a specific resource in a class to execute at the end, you can use the same arrow (->) within the class or use before or require in the resource

example:

file { '/etc/profile.d/settomcatparam.sh':
  ensure => file,
  before => File_line['/etc/profile.d/settomcatparam.sh'],
}

file_line { '/etc/profile.d/settomcatparam.sh':
  path => '/etc/profile.d/settomcatparam.sh',
  ine => 'export LD_LIBRARY_PATH=/usrdata/apps/sysapps/apr/lib:/usrdata/apps/sysapps/apr-util/lib:/usrdata/apps/sysapps/tomcat-native/lib:$LD_LIBRARY_PATH',
}

OR

exec { 'configure apr-util':
  cwd     => "/tmp/apr-util-${tomcat::aprutilversion}/",
  command => "bash -c './configure --prefix=/usrdata/apps/sysapps/apr-util --with-apr=/usrdata/apps/sysapps/apr'",
} ->
exec { 'make apr-util':
  cwd     => "/tmp/apr-util-${tomcat::aprutilversion}/",
  command => 'make',
}

You can also use combination of before, require and ->. Just make sure you don't create a dependency cycle.

Upvotes: 1

Related Questions