logos

With Andrii Grytsenko


Technical Diary - With Andrii Grytsenko

Puppet modules mini how-to

Here I will try do describe basics in making puppet modules.

I will divide it on the 3 little parts:

  1. Structure of puppet modules
  2. Modules manifests
  3. Files
  4. Temlates


1. Structure of puppet modules


Puppet modules represents itself as a standalone directory inside the directory specified by modulepath variable at /etc/puppet/puppet.conf:


modulepath = /etc/puppet/modules

The directory tree has next structure:

my_module
        |- files
        |      |
        |      \- some_config.conf
        |- manifests
        |         |
        |         \- init.pp
        \- templates
                  |
                  \- some_template.erb

The module directory name should be the name of module and should match class name.

So there are three basic directories files, manifests, template.

The main directory is manifests and it should be exists as well as manifest file init.pp inside it.

files – contains configuration or other files which should be shared between other hosts. Like resolv.conf

templates – contains templates.

2. Modules manifests


Let’s look inside init.pp file. It have to contain at least one class with name matching madule name:

class my_module {
}

It also can inherits some other module/class

class my_module inherits other_module  {
}

It can be useful if some resource from third modules should be involved in your module’s manifest.

For example if you change php.ini in php module then after deployment you need to reload httpd daemon to make changes to take effect. Here is the part of httpd modules describes reload:

class httpd {
...
  exec { "httpd-reload":
      command => "/etc/init.d/httpd reload",
      refreshonly => true,
      require => [Package['httpd'], Exec["httpd-test-config"] ],
  }

  exec { "httpd-test-config":
      command => "/usr/sbin/apachectl configtest",
      refreshonly => true,
  }

...
}

and part used in php module:

class php inherits httpd {
...
  file { "/etc/php.ini":
         ensure => present,
         owner  => root,
         group  => root,
         mode   => 644,
         source => "puppet:///php/php.init",
         notify => Service["httpd"],
  }
...
}

The class can have next objects:

  • package
  • service
  • file
  • exec

Examples of each of them:

package { package_name:
        ensure => present|latest,
    }

 

service { "service_name":
    ensure => stopped|running,
    enable => false|true,
}

 

exec { "exec_name":
    command => "some command to reload",
}


3. Files


There are no any special requirement to share a file between system. To deploy file to systems with activated module create new object in manifest:

file { "/where/to/deploy/filename":
  ensure => link|directory|present|absent,
  target => "/path/to/deployed/file",
  owner  => "root",
  group  => "root",
  mode   => "777",
  recurse => true|false,
  ignore => [".svn", "some_file"], # applied to directories
  source => "puppet:///module_name/file_to_deploy/",
  notify => Service["my_service"],
}

Most interesting parameters are notify and source. First parameter triggers some command my_service(described earlier in this or in inherited class) shortly afterwards file changed. And second parameter is specified path to file at puppet side. Value puppet:///module_name/php.d/ means that file should be located at /path/to/puppet/modules/modules_name/file/file_to_deploy. So if your need to deploy php.ini from php class to /etc/php.ini on client node put file php.ini into /etc/puppet/modules/php/files/php.ini(it’s default module path).


4. Templates


Template allows describe content of file depends on user’s and system’s variables using loops and conditions. To use file in class as well as file – describe it as content instead of source

file { '/test.file':
   content => template("my-modules/test.file.erb"),
}

Here are couple examples of using templates.
/etc/resolv.conf:

define variables at manifest:

$domainname = example.com
$nameservers = ['192.168.0.1', '192.168.0.2']

resolv.conf.erb:

domain
search

nameserver

On client side we’ll get:

domain example.com
nameserver 192.168.0.1
nameserver 192.168.0.2

Example #2 sent different content depends on node name:


   content for node host1
   where fqdm stands for fully qualified domain name

   content for all node who hostname match 'host2*' regexp

Template file should be located at /etc/puppet/modules/my-module/manifests/ directory.