This page documents the standards for how to write common modules,as part of the Puppet Common Modules (PCM) project.
The Puppet Common Modules project is designed to provide a common architecture, documentation, language, and style for modules. Also included is a collection of common modules.
Module Standards:
- A single module should implement a specific functionality, service or application. As lak said “If i’d ask myself "is X up?” Then X should be a module."
- Modules should be independent, if at all possible. If a dependency is absolutely necessary, it must be clearly documented. The user should be able to download just the common module and any modules that s/he is interested in and have that work, with no other changes.
- Any function/fact/type/provider needed should be clearly specified and either in the Puppet core, the same module or in the common module.
- If one of the choices is “you can do that with a template”, that’s usually the right way.
Operating system differences should be specified in variables in a case at the start of the module, as follows:
class ssh::server { case $operatingsystem { "freebsd","openbsd": { $sshservice = "sshd" } debian: { $sshservice = "ssh" } } # use a constant title to facilitate stable relations service { "ssh::server": name => $sshservice, ensure => running, enable => true, } }Bigger operating system differences should be split out into their respective classes:
class ssh::server::common { service { 'ssh::server': ... } } class ssh::server::debian inherits ssh::server::common { Service['ssh::server'] { name => 'ssh' } } class ssh::server { include "ssh::server::$operatingsystem" }The Style Guide must be followed.
- All modules must be completely documented, as per the Puppet Manifest Documentation page.
User’s Best Practices:
- The standard modules should be downloaded and added at the end of the modulepath (i.e., modulepath = /etc/puppet/modules:/etc/puppet/common-modules)
- Override functionality from a module by extending the relevant
class or by wrapping a define:
# This class provides a extra layer of security by obscurity # through moving the sshd to a high port class ssh::server::extra_secure inherits ssh::server { Ssh::Conf['Port'] { value => 12345 } } # This define creates a apache::site for a specific customer define apache::customer_site($source) { apache::site { "cust_${name}": source => $source } # additional resources go here }
Naming Standard:
- If there is only one class in the module, it should be in init.pp and have the same name as the module.
- If there are are multiple classes in the module:
- Each (externally visible) class should be in a separate file, named after the class to facilitate autoloading.
- The base class that is inherited by the other classes (if any), should be called module::common.
- Other class names should describe the difference in function between the classes i.e., module::client and module::server.
- Each (externally visible) define be in a separate file, named after the class to facilitate autoloading. For groups of small and/or tightly related defines, putting them together into a single file might make sense. The module has to import that in the init.pp to facilitate autoloading.
Notes Needed:
- enough interested people with time
- a place to development, including bug tracker, release eng, etc
- some extensions to the puppet language, possibly (confine to os, for example)
- standards for modules
- a way to document modules (maybe comment style, maybe a puppet lang extension)
- we need way to do versioning on modules