Containment enables you to control where and when specific parts of your Puppet code are executed. Containment is the relationship that resources have to classes and defined types.
Containment
Classes and defined type instances contain the resources they declare. Contained resources are not applied before the container begins, and they finish before the container finishes.
This means that if any resource or class forms a relationship with the container, it forms the same relationship with every resource inside the container.
class ntp {
file { '/etc/ntp.conf':
...
require => Package['ntp'],
notify => Service['ntp'],
}
service { 'ntp':
...
}
package { 'ntp':
...
}
}
include ntp
exec {'/usr/local/bin/update_custom_timestamps.sh':
require => Class['ntp'],
}
Here, Exec['/usr/local/bin/update_custom_timestamps.sh']
would happen after every resource in the ntp
class, including the package, file, and service.This feature allows you to notify and subscribe to classes and defined resource types as though they were a single resource.
Containing resources
Resources of both native and defined resource types are automatically contained by the class or defined type in which they are declared.
Containing classes
Having classes contain other classes can be useful, especially in larger modules where you want to improve code readability by moving chunks of implementation into separate files.
Unlike resources, Puppet does not automatically contain classes when they are declared inside another class. This is because classes can be declared in several places using include
and similar functions. Most of these places shouldn’t contain the class, and trying to contain it everywhere would cause huge problems. Instead, you must manually contain any classes that need to be contained.
The contain
function
Use the contain
function to declare that a class is contained. The contain
function uses include-like behavior, containing a class within a surrounding class.
In this NTP module example, the service configuration is moved out into its own class:
class ntp {
file { '/etc/ntp.conf':
...
require => Package['ntp'],
notify => Class['ntp::service'],
}
contain ntp::service
package { 'ntp':
...
}
}
include ntp
exec { '/usr/local/bin/update_custom_timestamps.sh':
require => Class['ntp'],
}
This ensures that the exec happens after all the resources in both class ntp
and class ntp::service
. If ntp::service
had been declared with include
instead of contain
, the exec would happen after the file and the package, but wouldn’t necessarily happen after the service.
To contain classes that are declared with the resource-like declaration syntax, use the contain
function after declaring the class:
class ntp {
# ...
class { 'ntp::service':
enable => true,
}
contain 'ntp::service'
# ...
}
Anchor pattern containment (for compatibility with Puppet version 3.4.0 and earlier)
Versions prior to Puppet 3.4.0 and Puppet Enterprise 3.2 do not ship with the contain
function. If your code needs to support these versions, it must contain classes with the anchor pattern.
puppetlabs/stdlib
module. which includes the dummy anchor
resource type.The containing class must include two uniquely-named
anchor
resources, which are resources that don’t have any effect on the target system, and only exist to form relationships with.Any contained classes must have relationships ensuring they happen after one anchor and before the other.
In this NTP module example, the service configuration is moved out into its own class:
class ntp {
file { '/etc/ntp.conf':
...
require => Package['ntp'],
notify => Class['ntp::service'],
}
include ntp::service
# roughly equivalent to "contain ntp::service":
anchor { 'ntp_first': } -> Class['ntp::service'] -> anchor { 'ntp_last': }
package { 'ntp':
...
}
}
include ntp
exec { '/usr/local/bin/update_custom_timestamps.sh':
require => Class['ntp'],
}
In this case, the ntp::service
class behaves like it’s contained by the ntp
class. Resources like the timestamp exec
can form relationships with the ntp
class and be assured that no relevant resources float out of order.