“So why use modules? Well, if the application, daemon, or function you are configuring contains multiple classes, files, and/or templates, the easiest way to package these resources is to modularize them. Modules make management of configuration collections easier and more structured.”
— from book “Pulling Strings with Puppet“
Modules appear to mainly be a way to group multiple files and resources for an application. Modules require a longer folder path than classes do:
Class: /etc/puppet/manifests/classes/mysql.pp /etc/puppet/files/my.cnf
Module: /etc/puppet/modules/mysql/manifests/init.pp /etc/puppet/modules/mysql/files/my.cnf
The only downside I can see for modules is more typing into longer paths, and de-centralization of files. It seems more practical (to me, at this point) to have all the masterfiles for all classes under /etc/puppet/files in case someone else needs to easily update them. But best practices strongly encourage use of modules, so…
What to add to site.pp to enable module:
#/etc/puppet/manifests/site.pp: import "mysql" node default { include mysql }
When referring to the fileserver source for the init.pp config file, in this example, mysql’s my.cnf, you can change the way the file is called:
Class: source => "puppet:///files/my.cnf"
change to:
Module: source => "puppet:///mysql/my.cnf"
A module’s init.pp appears to be the same as a class .pp file, except for the source path.
Postfix module: (based on example in “Pulling Strings with Puppet”)
# Copy all required postfix files, run newaliases if /etc/aliases has changed, and restart postfix last. class postfix { $packagelist = ["postfix.$architecture"] package {$packagelist: ensure => installed"} postfix::postfix_files { "/etc/aliases": mode => "640", source => "aliases"; "/etc/postfix/main.cf": source => "main.cf"; "/etc/postfix/master.cf": source => "master.cf"; "/etc/postfix/canonical": source => "canonical" } # Ensure that the postfix service is installed and running. # Restart the service if main.cf changes. service { "postfix": enable => "true", ensure => "running", restart => true, require => Package["postfix.$architecture"], subscribe => File["/etc/postfix/main.cf"], } # Define some variables that will apply to all of the files define postfix::postfix_files($owner = root, $group = root, $mode = 644, $source, $backup = false, $recurse = false, $ensure = file) { file { $name: mode => $mode, owner => $owner, group => $group, backup => $backup, recurse => $recurse, ensure => $ensure, require => Package["postfix.$architecture"], source => "puppet:///postfix/$source" } } # Rerun newaliases and restart postfix if aliases updated: exec {newaliases: command => "/usr/sbin/postalias /etc/aliases ; service postfix restart", subscribe => File["/etc/aliases"], refreshonly => true, } }
Some more examples of Puppet classes
class for ldconfig and ld.so.conf:
# /etc/puppet/manifests/classes/ldconfig.pp class ldconfig { file { "/etc/ld.so.conf": owner => root, group => root, mode => 644, source => "puppet:///files/ld.so.conf", } # rerun ldconfig if the .conf file has changed exec { ldlibcfg: command => "/sbin/ldconfig", subscribe => File["/etc/ld.so.conf"], refreshonly => true } }
snmpd:
# /etc/puppet/manifests/classes/snmpd.pp# class snmpd { file { "/etc/snmp/snmpd.conf": owner => root, group => root, mode => 644, source => "puppet:///files/snmpd.conf", } # Copy snmpd.options to reduce snmp logging noise file { "/etc/sysconfig/snmpd.options": owner => root, group => root, mode => 755, source => "puppet:///files/snmpd.options", require => File["/etc/snmp/snmpd.conf"], } # Restart snmpd service only if file has changed exec { snmpd_restart: command => "/etc/init.d/snmpd restart", subscribe => File["/etc/snmp/snmpd.conf"], refreshonly => true } }