I have a puppet class that uses the apt library and puppet's stdlib, this is the code:
class mymodule::gcc_48
{
if $::lsbdistrelease == 12.04 {
include apt
apt::ppa { 'ppa:ubuntu-toolchain-r/test': }
ensure_packages( ['gcc-4.8', 'g++-4.8'] )
exec { 'update_alternatives_gcc':
command => '/usr/sbin/update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 50',
creates => '/etc/alternatives/gcc'
}
exec { 'update_alternatives_gpp':
command => '/usr/sbin/update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 50',
creates => '/etc/alternatives/g++'
}
}
}
I need puppet to do all of these things in the order it's written (well, except for the last two exec) but it's not clear to me how to write the dependency relationship that includes ensure_packages. I tried using the ordering arrows (->) but these don't work with functions (i.e. with ensure_packages).
As written, the resources are applied all out of order and it takes several runs of puppet for everything to work.
I want to try to keep all of this code in the same class if that's possible.
Here is my understand. Set the class apt::ppa as below:
apt::ppa { 'ppa:ubuntu-toolchain-r/test':
# Here puts your code for this class apt::ppa,
before => Package['gcc-4.8', 'g++-4.8']
}
I recommend to go through this document: Learning Puppet — Resource Ordering
Related
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.
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.
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.
So I am using the https://forge.puppetlabs.com/pdxcat/nrpe module to try to figure out automation of NRPE across hosts.
One of the available usages is
nrpe::command {
'check_users':
ensure => present,
command => 'check_users -w 5 -c 10';
}
Is there anyway to make a "group" of these commands and have them called on specific nodes?
For example:
you have 5 different nrpe:command each defining a different check, and then call those specific checks?
I am basically trying to figure out if I could group certain checks/commands together instead of setting up a ton of text in the main sites.pp file. This would also allow for customized templates/configurations across numerous nodes.
Thanks!
EDIT:
This is the command and what it's supposed to do when called on with the 'check_users' portion. If I could have a class with a set of "nrpe:command" and just call on that class THROUGH the module, it should work. Sorry, though. Still new at puppet. Thanks again.
define nrpe::command (
$command,
$ensure = present,
$include_dir = $nrpe::params::nrpe_include_dir,
$libdir = $nrpe::params::libdir,
$package_name = $nrpe::params::nrpe_packages,
$service_name = $nrpe::params::nrpe_service,
$file_group = $nrpe::params::nrpe_files_group,
) {
file { "${include_dir}/${title}.cfg":
ensure => $ensure,
content => template('nrpe/command.cfg.erb'),
owner => root,
group => $file_group,
mode => '0644',
require => Package[$package_name],
notify => Service[$service_name],
}
}
What version are you talking about? In puppet latest versions, inheritance is deprecated, then you shouldn't use it.
The easiest way would be to use "baselines".
Assuming you are using a manifests directory (manifest = $confdir/manifests inside your puppet.conf), simply create a $confdir/manifests/minimal.pp (or $confdir/manifests/nrpe_config.pp or whatever class name you want to use) with the content below:
class minimal {
nrpe::command { 'check_users':
ensure => present,
command => 'check_users -w 5 -c 10',
}
}
Then just call this class inside your node definitions (let's say in $confdir/manifests/my_node.pp) :
node 'my_node.foo.bar' {
include minimal
}
Puppet Version: 3.2.4 (Puppet Enterprise 3.0.1)
In order to better support nagios cfg_dir and cfg_file directives in the config file, I've created the following class(es), one for each option:
# Class to add a cfg_dir to the nagios configuration file
class nagios::server::cfg_dir (
$config_dir,
$nagios_user,
$nagios_group,
$nagios_config_file = '/etc/nagios3/nagios.cfg',
)
{
# Build the config dir
file {$config_dir:
ensure => directory,
owner => $nagios_user,
group => $nagios_group,
mode => '0750',
}
# Append cfg_dir=$config_dir path to nagios.cfg file
augeas { "cfg_dir=$config_dir in $nagios_config_file":
incl => "$nagios_config_file",
lens => 'NagiosCfg.lns',
changes => "set cfg_dir/[last()+1] ${config_dir}",
require => File[$nagios_config_file],
}
}
Trying to use this construct inside nagios::server, I have this:
# Set up config directories
each($cfg_dir) |$x| {
class { 'nagios::server::cfg_dir':
config_dir => $x,
nagios_user => $nagios_user,
nagios_group => $nagios_group,
nagios_config_file => $nagios_config_file,
}
}
Which should, in theory, execute the class instantiation for each path passed in to the nagios::server class like so:
class{'::nagios::server': cfg_dir => ['/etc/nagios.d','/etc/nagios/objects'] }
However, I run into this issue:
Error: Could not match |$x| at /tmp/vagrant-puppet-1/modules-2/nagios/manifests/server.pp:181 on node localhost.localdomain
Can someone provide a working example of each in use? Am I expecting too much from this built-in puppet function?
Aside from a few of the code grammar issues above, I've found that this construct is only evaluated in the future parser:
puppet apply --parser=future --modulepath ...
http://docs.puppetlabs.com/puppet/latest/reference/experiments_lambdas.html
Still getting past other dependency issues. What pattern would I use to support this with the current parser instead of future? A custom function?
The answer to my follow-up question is to use defined types:
http://docs.puppetlabs.com/learning/definedtypes.html
Simply changing the above code from a class to a define and assign $config_dir the value from $target,
define nagios::server::cfg_dir (
$config_dir = $target,
$nagios_user,
$nagios_group,
$nagios_config_file = '/etc/nagios3/nagios.cfg',
){...
you can use constructs such as:
nagios::server::cfg_dir { '/etc/nagios.d/', '/etc/nagios/objects':
nagios_user => 'nagios',
nagios_group => 'nagios'
}
This solves the issue for me.
We are attempting to use the camptocamp/puppet-nagios module, but we're running into a packaging naming conflict between vanilla CentOS repositories and RPMForge/RepoForge. The nsca daemon in CentOS provides the same service as the nagios-nsca package in RepoForge. In attempt to install the RepoForge package yet satisify the Package requirement for nsca resource, I've added this to my node definition:
include ::nagios
package { 'nagios-nsca': ensure => installed, alias => 'nsca', }
include ::nagios::nsca::server
The resulting error is:
Error: Duplicate declaration: Package[nsca] is already declared in
file /tmp/vagrant-puppet-1/modules-0/role/manifests/nagios.pp:45;
cannot redeclare at
/tmp/vagrant-puppet-1/modules-2/nagios/manifests/nsca/server.pp:24
The next test was to use order and calling the class directly from the node:
include ::nagios
package { 'nagios-nsca': ensure => installed, alias => 'nsca', } ->
class {'::nagios::nsca::server' : }
The code in question inside the nagios/manifests/nsca/server.pp file is:
class nagios::nsca::server(
$decryption_method = pick($nagios_nsca_decryption_method, '0'),
) {
include ::nagios::params
# variables used in ERB template
$basename = $nagios::params::basename
if !defined (Package['nsca']) {
package {'nsca':
ensure => installed;
}
}
Any insight as to what's happening here? I can always fork the camptocamp/puppet-nagios code and force the behavior we want, but I'd rather not.
Due to ! defined(Package['title']) not working as expected. I fixed this by giving nagios::nsca::server an additional parameter of nsca_package, including a default value of nsca to preserve current behavior:
--- a/manifests/nsca/server.pp
+++ b/manifests/nsca/server.pp
## -11,6 +11,7 ##
#
class nagios::nsca::server(
$decryption_method = pick($nagios_nsca_decryption_method, '0'),
+ $nsca_package = 'nsca'
) {
include ::nagios::params
## -20,6 +21,7 ## class nagios::nsca::server(
if !defined (Package['nsca']) {
package {'nsca':
+ name => $nsca_package,
ensure => installed;
}
}
Use for this new parameter would be:
node 'my-nagios-server.local' {
include ::nagios
class {'::nagios::nsca::server': nsca_package => 'nagios-nsca', }
}
I want to override parameters of base nodes. What I want to get is a pattern like this:
# File manifests/nodes.pp
node myDefault {
class { 'my::common::puppet_setup':
service => 'enable',
pushable => 'disable',
}
# Do lots of default things ...
}
node 'myFirstNode' inherits myDefault {
# Do something ...
}
node 'mySecondNode' inherits myDefault {
class { 'my::common::puppet_setup::params':
service => 'disable',
pushable => 'enable',
}
}
I understood the the puppet documentation, i could do this by writing my module like this:
# File modules/my/manifests/common/puppet_setup.pp
class my::common::puppet_setup (
$pushable = $my::common::puppet_setup::params::pushable,
$service = $my::common::puppet_setup::params::service,
) inherits my::common::puppet_setup::params {
# package that configures puppet node
# input value validation
validate_re($pushable, ['^enable$', '^disable$', '^ignore$', ])
validate_re($service, ['^enable$', '^disable$', '^ignore$', '^cron$', ])
# setup puppet, start or disable agent, put ssh keys for push ...
}
class my::common::puppet_setup::params {
$pushable = 'enable'
$service = 'enable'
$puppetserver = 'puppet.my.site.de'
case $::osfamily {
'Debian': {
}
default: {
fail("not implemented yet for {::operatingsystem}")
}
}
}
The Documentations on puppet website says:
When a derived class is declared, its base class is automatically declared first (if it wasn’t already declared elsewhere).
But i get this error (some indentation added):
mySecondNode# puppet agent --test --environment dev_my
Error: Could not retrieve catalog from remote server:
Error 400 on SERVER: Duplicate declaration:
Class[My::Common::Puppet_setup::Params] is already declared;
cannot redeclare at /.../puppet/manifests/nodes.pp:16 on node mySecondNode
Warning: Not using cache on failed catalog
Error: Could not retrieve catalog; skipping run
I'm reading on this for a week and i guess my understanding ist totally wrong somewhere, although i used the puppetlabs ntp modules as an example.
what am i missing?
You should check Inheritance section from http://docs.puppetlabs.com/puppet/latest/reference/lang_node_definitions.html
Puppet treats node definitions like classes. It does not mash the two together and then compile the mix; instead, it compiles the base class, then compiles the derived class, which gets a parent scope and special permission to modify resource attributes from the base class.
One of the good solutions is to use roles and profiles, there's a great blog post about it:
http://garylarizza.com/blog/2014/02/17/puppet-workflow-part-2/
You can use virtual resources :
http://docs.puppetlabs.com/guides/virtual_resources.html