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
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.