In this example, Exec['/usr/local/bin/update_custom_timestamps.sh'] would happen after every resource in the ntp class, including the package, the file, and the service.

This feature also 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 very useful, especially in larger modules where you want to improve code readability by moving chunks of implementation into separate files.

However, 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 via 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 when a class should be contained. The contain function will declare the class with include-like behavior if it isn’t already declared, and will cause it to be contained by the surrounding class.

In an example NTP module where service configuration is moved out into its own class:

This will ensure that the exec will happen 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:

In this case, the ntp::service class will behave 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 will float out of order.