Namespaces and autoloading

Class and defined type names can be broken up into segments called namespaces which enable the autoloader to find the class or defined type in your modules.

Syntax

Puppet class and defined type names can consist of any number of namespace segments separated by the double colon (::) namespace separator, analogous to the slash (/) in a file path.

class apache { ... }
class apache::mod { ... }
class apache::mod::passenger { ... }
define apache::vhost { ... }

Autoloader behavior

When a class or defined resource is declared, Puppet uses its full name to find the class or defined type in your modules. Every class and defined type must be in its own file in the module’s manifests directory, and each file must have the .pp file extension.

Names map to file locations as follows:
  • The first segment in a name, excluding the empty top namespace, identifies the module. If this is the only segment, the file name is init.pp.

  • The last segment identifies the file name, minus the .pp extension.

  • Any segments between the first and last are subdirectories under the manifests directory.

As a result, every class or defined type name maps directly to a file path within Puppet’s modulepath :
Name File path
apache <MODULE DIRECTORY>/apache/manifests/init.pp
apache::mod <MODULE DIRECTORY>/apache/manifests/mod.pp
apache::mod::passenger <MODULE DIRECTORY>/apache/manifests/mod/passenger.pp
Note: The init.pp file always contains a class or defined type with the same name as the module, and any other .pp file contains a class or defined type with at least two namespace segments. For example, apache.pp would contain a class named apache::apache. This means you can’t name a class <MODULE NAME>::init.

Nested definitions and missing files

If a class or defined type is defined inside another class or defined type definition, its name goes under the outer definition’s namespace.

This causes its real name to be something other than the name it was defined with. For example, in the following code, the interior class's real name is first::second:
class first {
  class second {
    ...
  }
}
However, searching your code for that real name returns nothing. Also, it causes class first::second to be defined in the wrong file. Avoid structuring your code like this.

If the manifest file that corresponds to a name doesn’t exist, Puppet continues to look for the requested class or defined type. It does this by removing the final segment of the name and trying to load the corresponding file, continuing to fall back until it reaches the module’s init.pp file.

Puppet loads the first file it finds like this, and raises an error if that file doesn’t contain the requested class or defined type.

This behavior allows you to put a class or defined type in the wrong file and still have it work. But structuring things this way is not recommended.