Docs: Module Fundamentals


Module Fundamentals

Puppet Modules

Modules are self-contained bundles of code and data. You can write your own modules or you can download pre-built modules from Puppet Labs’ online collection, the Puppet Forge.

Nearly all Puppet manifests belong in modules. The sole exception is the main site.pp manifest, which contains site-wide and node-specific code.

Every Puppet user should expect to write at least some of their own modules.

Using Modules

Modules are how Puppet finds the classes and types it can use — it automatically loads any class or defined type stored in its modules. Within a manifest or from an external node classifier (ENC), any of these classes or types can be declared by name:

    # /etc/puppetlabs/puppet/site.pp

    node default {
      include apache

      class {'ntp':
        enable => false;
      }

      apache::vhost {'personal_site':
        port    => 80,
        docroot => '/var/www/personal',
        options => 'Indexes MultiViews',
      }
    }

Likewise, Puppet can automatically load plugins (like custom native resource types or custom facts) from modules; see “Using Plugins” for more details.

To make a module available to Puppet, place it in one of the directories in Puppet’s modulepath.

The Modulepath

Note: The modulepath is a list of directories separated by the system path-separator character. On ‘nix systems, this is the colon (:), while Windows uses the semi-colon (;). The most common default modulepaths are:

  • /etc/puppetlabs/puppet/modules:/opt/puppet/share/puppet/modules (for Puppet Enterprise)
  • /etc/puppet/modules:/usr/share/puppet/modules (for open source Puppet)

Use puppet config print modulepath to see your currently configured modulepath.

If you want both puppet master and puppet apply to have access to the modules, set the modulepath in puppet.conf to go to the [main] block. Modulepath is also one of the settings that can be different per environment.

You can easily install modules written by other users with the puppet module subcommand. See “Installing Modules” for details.

Module Layout

On disk, a module is simply a directory tree with a specific, predictable structure:

  • MODULE NAME
    • manifests
    • files
    • templates
    • lib
    • tests
    • spec

Example

This example module, named “my_module,” shows the standard module layout in more detail:

  • my_module — This outermost directory’s name matches the name of the module.
    • manifests/ — Contains all of the manifests in the module.
      • init.pp — Contains a class definition. This class’s name must match the module’s name.
      • other_class.pp — Contains a class named my_module::other_class.
      • my_defined_type.pp — Contains a defined type named my_module::my_defined_type.
      • implementation/ — This directory’s name affects the class names beneath it.
        • foo.pp — Contains a class named my_module::implementation::foo.
        • bar.pp — Contains a class named my_module::implementation::bar.
    • files/ — Contains static files, which managed nodes can download.
      • service.conf — This file’s URL would be puppet:///modules/my_module/service.conf.
    • lib/ — Contains plugins, like custom facts and custom resource types. See “Using Plugins” for more details.
    • templates/ — Contains templates, which the module’s manifests can use. See “Templates” for more details.
      • component.erb — A manifest can render this template with template('my_module/component.erb').
    • tests/ — Contains examples showing how to declare the module’s classes and defined types.
      • init.pp
      • other_class.pp — Each class or type should have an example in the tests directory.
    • spec/ — Contains spec tests for any plugins in the lib directory.

Each of the module’s subdirectories has a specific function, as follows.

Manifests

Each manifest in a module’s manifests folder should contain one class or defined type. The file names of manifests map predictably to the names of the classes and defined types they contain.

init.pp is special and always contains a class with the same name as the module.

Every other manifest contains a class or defined type named as follows:

Name of module :: Other directories:: (if any) Name of file (no extension)
my_module ::   other_class
my_module :: implementation:: foo

Thus:

  • my_module::other_class would be in the file my_module/manifests/other_class.pp
  • my_module::implementation::foo would be in the file my_module/manifests/implementation/foo.pp

The double colon that divides the sections of a class’s name is called the namespace separator.

Allowed Module Names

Module names should only contain lowercase letters, numbers, and underscores, and should begin with a lowercase letter; that is, they should match the expression [a-z][a-z0-9_]*. Note that these are the same restrictions that apply to class names, but with the added restriction that module names cannot contain the namespace separator (::) as modules cannot be nested.

Although some names that violate these restrictions currently work, using them is not recommended.

Certain module names are disallowed:

  • main
  • settings

Files

Files in a module’s files directory are automatically served to agent nodes. They can be downloaded by using puppet:/// URLs in the source attribute of a file resource.

Puppet URLs work transparently in both agent/master mode and standalone mode; in either case, they will retrieve the correct file from a module.

Puppet URLs are formatted as follows:

Protocol 3 slashes “Modules”/ Name of module/ Name of file
puppet: /// modules/ my_module/ service.conf

So puppet:///modules/my_module/service.conf would map to my_module/files/service.conf.

Templates

Any ERB template (see “Templates” for more details) can be rendered in a manifest with the template function. The output of the template is a simple string, which can be used as the content attribute of a file resource or as the value of a variable.

The template function can look up templates identified by shorthand:

Template function (‘ Name of module/ Name of template ’)
template (' my_module/ component.erb ')

So template('my_module/component.erb') would render the template my_module/templates/component.erb.

Writing Modules

To write a module, simply write classes and defined types and place them in properly named manifest files as described above.

  • See here for more information on classes
  • See here for more information on defined types

Best Practices

The classes, defined types, and plugins in a module should all be related, and the module should aim to be as self-contained as possible.

Manifests in one module should never reference files or templates stored in another module.

Be wary of having classes declare classes from other modules, as this makes modules harder to redistribute. When possible, it’s best to isolate “super-classes” that declare many other classes in a local “site” module.

↑ Back to top