With what you've seen this far, you might have got the impression that Puppet's DSL is a specialized scripting language. That is actually quite far from the truth. A manifest is not a script or program. The language is a tool to model a system state through a set of resources, including files, packages, and cron jobs, among others.
The whole paradigm is different from that of scripting languages. Ruby or Perl are imperative languages that are based around statements that will be evaluated in a strict order. The Puppet DSL is declarative, which means that the manifest declares a set of resources that are expected to have certain properties. These resources are put into a catalog, and Puppet then tries to build a path through all declared resources. The compiler parses the manifests in order, but the configurer applies resources in a very different way.
In other words, the manifests should always describe what you expect to be the end result. The specifics of what actions need to be taken to get there are decided by Puppet.
To make this distinction more clear, let's look at an example:
package { 'haproxy':
ensure => 'installed',
}
file {'/etc/haproxy/haproxy.cfg':
ensure => file,
owner => 'root',
group => 'root',
mode => '0644',
source => 'puppet:///modules/haproxy/etc/haproxy/haproxy.cfg',
}
service { 'haproxy':
ensure => 'running',
}
With this manifest, Puppet will make sure that the following state is reached:
- The HAproxy package is installed.
- The haproxy.cfg file has specific content, which has been prepared in a file in /etc/puppet/modules/.
- HAproxy is started.
To make this work, it is important that the necessary steps are performed in order:
- A configuration file cannot usually be installed before the package because there is not yet a directory to contain it
- The service cannot start before installation either. If it becomes active before the configuration is in place, it will use the default settings from the package instead
This point is being stressed because the preceding manifest does not, in fact, contain cues for Puppet to indicate such a strict ordering. Without explicit dependencies, Puppet is free to put the resources in any order it sees fit.
The recent versions of Puppet allow a form of local manifest-based ordering, so the presented example will actually work as is. The manifest-based ordering can be configured in the puppet.conf configuration file as follows:
ordering = manifest
This setting is default for Puppet 4. It is still important to be aware of the ordering principles because the implicit order is difficult to determine in more complex manifests, and as you will learn soon, there are other factors that will influence the order.