Puppet: how to install package httpd only on specific nodes/ip? - puppet

Suppose 10 servers,but I want to install httpd only on two servers and OS must be Centos,I have tried with this manifest
class apache {
if $::operatingsystem == 'CentOS' {
package { "httpd":
ensure => latest
}
}
}
node '10.2.0.5' {
include apache
}
node '10.2.0.6' {
include apache
}
But apply catalog fail.
I have tried to replace apache with httpd..but no success.

Solution found, I had to declare a class called testmodule(name can be random) and select package for specific hosts,for other hosts I put nothing for now but I can select other actions.
Tested and works perfect.
class testmodule {
package { ['telnet', 'glusterfs', 'wget']:
ensure => installed,
}
}
node 'node1.mysite.example', 'node2.mysite.example' {
include testmodule
}
node 'default' {
}

Related

How to Require Another Custom Class Using Puppet

If I have two class's in my own puppet module and class 'b' has a dependency on class 'a'. How can I express this in my require statement:
# a.pp
class rehan::a {
package { 'javaruntime':
ensure => latest,
provider => chocolatey
}
}
# b.pp
class rehan::b {
file { 'C:\foo':
ensure => present,
require => Package['?????']
}
}
# site.pp
node default {
include rehan::a
include rehan::b
}
If you want to express a dependency of class b on class a (and also ensure that a is in the catalog):
class rehan::b {
require rehan::a
}
If you just one resource on rehan::b to depend on class A:
class rehan::b {
include rehan::a # ensure the class is in the catalog
file { 'C:\foo':
ensure => present,
require => Class['rehan::a'],
}
}
You can also express this relationship anywhere with Class['rehan::a'] -> Class['rehan::b'] (assuming both are included in the catalog).

Resolve conflicting package resource declarations

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', }
}

difference between require and ordering with puppet classes

I want to achieve dependency between puppet classes, so that the classes (their content) get executed in a deterministic way. Reading the documentation I came up with the following two ways:
ORDERING
class Level1 {
Class['Level2']->Class[Level1']
package { "A":
ensure => "installed"
}
}
class Level2 {
include Level3
package { "B":
ensure => "installed"
}
}
class Level3 {
package { "C":
ensure => "installed"
}
}
according to the documentation
-> (ordering arrow) Causes the resource on the left to be applied before the resource on the right. Written with a hyphen and a
greater-than sign.
I expect the following to happen:
Level2 is called before Level1
package B or C get installed (order can be random because it was not specified)
package A gets installed.
REQUIRE
class Level1 {
require Level2
package { "A":
ensure => "installed"
}
}
class Level2 {
require Level3
package { "B":
ensure => "installed"
}
}
class Level3 {
package { "C":
ensure => "installed"
}
}
According to the documentation
cause every resource in the required classes to be applied
before any of the resources in the requiring class.
I expect the following to happen:
Level3 is called by Level2
package C gets installed
Level2 is called by Level1
package B gets installed
package A gets installed
alternative ORDERING
class Level1 {
Class['Level3']->Class['Level2']->Class[Level1']
package { "A":
ensure => "installed"
}
}
class Level2 {
package { "B":
ensure => "installed"
}
}
class Level3 {
package { "C":
ensure => "installed"
}
}
level 1 is needed by level 2
level 2 is needed by level 3
package C gets installed
package B gets installed
package A gets installed
Are my assumptions and conclusions correct?
I've been messing with these kind of dependencies for a while now and they don't seem to behave how I imagine them to behave. Maybe I'm missing something when it comes to the usage of require and -> when used with classes. Any feedback is appreciated!!
EDIT1
staging seems to be a good mechanism for fixing the dependency between two classes (see here), since you have to manually define the stage dependencies between each class pair. How would you use staging with three or four class levels?
EDIT2
Consider this more realistic case, where classes a used as wrappers to install multiple packages at the same time.
Every node is loading some pre-defined role:
node 'some-host' {
include role::processing_machine
}
the role is defined as follows:
class role::processing_machine {
include role::ubuntu_desktop_standard_software
include xorg::lts_12_04_quantal
include software::standard_packages
# define order in which classes should be executed
Class["role::ubuntu_desktop_standard_software"] -> Class["xorg::lts_12_04_quantal"] -> Class["software::standard_packages"] -> Class["role::processing_machine"]
}
and here's the role::ubuntu_desktop_standard_software definition:
class role::ubuntu_desktop_standard_software {
include role
include profile::ubuntu_desktop
include role::server::no_apache
# define order in which classes should be executed.
Class["role"] -> Class["profile::ubuntu_desktop"] -> Class["role::server::no_apache"] -> Class["role::ubuntu_desktop_standard_software"]
}
As you can see, I'm trying to chain multiple classes so that they get executed in a particular order (Class["a"] -> Class["b"]). Previously I've only used include in my classes but puppet would execute the include commands in arbitrary order, so that some commands (which have to run first!) wouldn't run first.
Despite these chaining efforts it still seems like puppet is executing the classes random fashion. What am I doing wrong? Is there a cleaner / better way of defining nodes so that I can be sure they are deployed in a particular, predefined way?
Here is an example :
class L {
package { "C" :
ensure => installed,
require => Package["A", "B",],
}
package { "B" :
ensure => installed,
require => Package["A"],
}
package { "A" :
ensure => installed,
}
}

Error about deprecated Puppet MySQL keeps showing up

This is my manifest:
class capstone() {
include apache
include mysql
class {'apache::vhost':
port => 80,
docroot => '/var/www/wordpress',
}
include 'apache::mod::php'
class {'mysql::server' :
root_password => 'foo',
override_options => {
'mysqld' => { 'max_connections' => '1024' },
}
}
class {'mysql::bindings' :
php_enable => true
}
}
I wrote this in modules/capstone/manifests/init.pp
Inside modules, I have stdlib, apache, concat, capstone, mysql, wordpress which are all downloaded except capstone.
My error is:
Error: ERROR: This class has been deprecated and the functionality moved
into mysql::server. If you run mysql::server without correctly calling
mysql:: server with the new override_options hash syntax you will revert
your MySQL to the stock settings. Do not proceed without removing this
class and using mysql::server correctly.
If you are brave you may set attempt_compatibility_mode in this class which
attempts to automap the previous settings to appropriate calls to
mysql::server at /root/radiant/modules/mysql/manifests/init.pp:89 on node kim.puppetlabs.vm
Error: ERROR: This class has been deprecated and the functionality moved
into mysql::server. If you run mysql::server without correctly calling
mysql:: server with the new override_options hash syntax you will revert
your MySQL to the stock settings. Do not proceed without removing this
class and using mysql::server correctly.
If you are brave you may set attempt_compatibility_mode in this class w
I have googled around and have followed the suggestions in other links but I still get the same error. Not sure where I have done wrong.
Please advise.
Two mistakes:
1) do not include mysql
2) did not state the vhosts name correctly
This is the working manifest:
class capstone() {
include apache
include apache::mod::php
apache::vhost { 'wordpress.example.com':
port => 80,
docroot => '/var/www/wordpress',
}
class {'mysql::server' :
root_password => 'foo',
override_options => {
'mysqld' => { 'max_connections' => '1024' },
}
}
class {'mysql::bindings' :
php_enable => true
}
}

check if a class exists

Is there a way to check in manifest files if a given class exists?
I want to do something like this:
class foo {
if exists( Class["foo::${lsbdistcodename}"] ) {
include foo::${lsbdistcodename}
}
}
So I can easily add distrubution / version specific classes which are then automatically included.
You should use defined instead of exists statement.
The following snippet works for me:
class foo {
if defined( "foo::${lsbdistcodename}") {
notify {'defined':}
include "foo::${lsbdistcodename}"
}
}
class foo::precise {
notify{'precise':}
}
[assuming you're running puppet version > 2.6.0]

Resources