• No results found

Manifests are collections of resources. They are the configuration scripts that

administrators use to manage the servers in their environments. The system administrator can define special attributes to relate various resources together. This gives the

administrator flexibility with how the manifest is structured.

Puppet does not necessarily process your manifest in the order that it is written. So, if there is a preferred order in which your resources should be handled, Puppet has special attributes, known as metaparameters, to define relationships between the resources in your manifests. These attributes are before, require, notify, and subscribe. The use

of metaparameters is unique to Puppet, and it is important that you keep them in mind if there is a preferred order of execution for your manifests. Listing 4-1 shows an example of the use of require and subscribe statements.

Listing 4-1 Puppet Manifest for an Apache Web Server

Click here to view code image package { ‘apache’:

name => ‘httpd’, ensure => installed, }

file {‘apacheconf’:

name => ‘/etc/httpd/conf/httpd.conf’, ensure => file,

mode => 600,

source => ‘/etc/puppet/files/httpd.conf’, require => Package[‘apache’],

}

service {‘apache’:

name => ‘httpd’, ensure => running, enable => true,

subscribe => File[‘apacheconf’], }

The manifest in Listing 4-1 will work on a CentOS server (that is, Puppet agent 2). You will need to type the code into a manifest file on the agent server, and be sure to use the pp extension in the filename. The manifest requires an Apache configuration file (see the file resource) that is compatible with the CentOS version that you are running. Be sure to change the file resource’s source attribute to reflect where you store the Apache

configuration file. Even if the configuration file is in the same directory as your manifest, provide the explicit path.

Let’s pause here to give you a chance to execute the code on your test machine.

Remember, the command to execute your manifest is as follows:

puppet apply filename.pp

If you would like to observe what the puppet code is doing, you can use the -d option with the apply command.

Now, getting back to the sample code: The require metaparameter in the file resource will ensure that the specified resource (Package["apache"]) exists before its own resource (file('apacheconf')) is deployed. This makes sense because there is no point in trying to deploy a configuration file for a service that does not exist!

The subscribe metaparameter behaves similarly to require, with an extra functionality: Puppet will monitor the target resource for any changes and perform an appropriate action in response. For a service resource, this would mean restarting the service after detecting a change in the configuration file.

Note

You might have noticed that I am capitalizing the Puppet type name when indicating the order relationship to an existing resource (for example,

subscribe => File['apacheconf']). This is a Puppet convention.

When you initially declare a resource, the type name is lowercase, and when you refer to it later on in the manifest, the first letter of the type name is uppercase.

The before and notify metaparameters are the opposite of require and

subscribe, respectively. If we used before and notify in our manifest, it would look similar to Listing 4-2.

Listing 4-2 Alternative Puppet Manifest for an Apache Web Server

Click here to view code image package { ‘apache’:

name => ‘httpd’, ensure => installed,

before => File[‘apacheconf’], }

file {‘apacheconf’:

name => ‘/etc/httpd/conf/httpd.conf’, ensure => file,

mode => 600,

source => ‘/etc/puppet/files/httpd.conf’, notify => Service[‘apache’],

}

service {‘apache’:

name => ‘httpd’, ensure => running, enable => true, }

There is another way to define relationships, and that’s with chaining arrows (-> for

before/require relationships and ~> for notify\subscribe relationships). In lieu of the metaparameter statements, the arrows can be placed between the resource

declarations, as shown in Listing 4-3.

Listing 4-3 Puppet Manifest Written with Chaining Arrows

Click here to view code image package { ‘apache’:

name => ‘httpd’, ensure => installed, }

->

file {‘apacheconf’:

name => ‘/etc/httpd/conf/httpd.conf’, ensure => file,

mode => 600,

source => ‘/etc/puppet/files/httpd.conf’, }

~>

service {‘apache’:

name => ‘httpd’, ensure => running, enable => true, }

As an alternative to placing the relationship arrows between the resources, you can just declare the resources and at the end of your manifest include the resource titles with the arrows drawn between them as follows:

Package[‘apache’] ->

File[‘apacheconf’] ~>

Service[‘apache’]

There isn’t a preferred method for defining the resource ordering. However, it is advised that your team decides on a convention that will be easiest for everyone to understand.

You can get creative with the placement of your resources in the manifest, but we

recommend adopting a logical progression when writing your Puppet code. (For instance, if resource B depends on resource A, list resource A before B in the manifest.) This will make it easier for other team members to understand the intentions of your workflow.

Also, in a year’s time, you might not even remember what your thought processes were when you wrote the manifest. As much as is possible, keep things simple.

Note

You may be wondering, “Why not just execute the Puppet code in the order that we write it?”

Even long-time Puppet users have given similar feedback, and Puppet has implemented manifest order analysis of resources (MOAR) starting with Puppet 3.3.0. MOAR will eventually become the default behavior in future releases of open source Puppet and Puppet Enterprise. However, users who prefer the current behavior (a.k.a. title hash) will be able to enable it.

The preceding examples show the quintessential approach to writing Puppet manifests:

package-file-system. You specify which package should be deployed, the related

configuration or content files for that package, and the service state (running, stopped, and so forth) of the package. It’s a great model to follow when you begin writing Puppet code regularly.