Puppet – Ordering your resources

In Puppet, the resources in a manifest can potentially be applied in any order, rather than in the order it has been specified in the manifest. One way round this is to insert the following:

ordering = manifest

in the puppet.conf file. This is a good idea to do. On top of that you can override this with the use of special attributes called metaparameters which you can embed within your resource declarations.

 

The 4 main metaparameters for controlling the order that resources are:

  • before
  • require
  • notify
  • subscribe

Note: there is a also a resource type called “notify”. But here we are referring to the notify metaparameter which is a different thing.

These 4 are similar and can be paired up like this:

  • before and require
  • notifiy and subscribe

 

“Before” and “Require”

Here is the “before” attribute in action:

 
file {'/tmp/test1':
      ensure  => present,
      content => "Hi.",
 }

 notify {'/tmp/test1 has already been synced.':
      require => File['/tmp/test1'],                   # Note, you must capitalise, i.e. "File" and not "file"
 }

The above says that the “notify” resource requires the “/tmp/test1” resource to be applied first before it itself can be applied.

The above can also be rewritten using the “before” metaparameter to:

 

 file {'/tmp/test1':
      ensure  => present,
      content => "Hi.",
      before  => Notify['/tmp/test1 has already been synced.'], # Again "Notify" and not "notify"

 } 

 notify {'/tmp/test1 has already been synced.':}

 

Here we are saying that the ‘/tmp/test1’ file resource has to be applied before the notify resource.

As you can see we have done some capitalisation. The rule is that you only type in lowercase (when writing the resrouce’s type) when declaring a new resource. Any other situation will always call for writing in uppercase.

 

 

“Subscribe” and “Notify”

These are similar to require/before, in terms of ordering your resources. However it also has an extra “notification” feature which is used to “refresh” a resource.

This is useful if you make changes to a config file and then want to restart (aka refresh) the corresponding service so that it loads the new settings into memory.

In this situation puppet is smart enough to do resource refresh. E.g. if you have declared a service resource’s “ensure” attribute set as “running” then if that resource get’s applied by subscribe/notify, then it will restart itself. Here’s an example:

 

file { '/etc/ssh/sshd_config':
      ensure => file,
      mode   => 600,
      source => 'puppet:///modules/ssh/sshd_config',
    }
service { 'sshd':
      ensure    => running,
      enable    => true,
      subscribe => File['/etc/ssh/sshd_config'],
    }

In this example, the sshd service will be restarted if Puppet has to edit its config file, called “sshd_config”.

Here we used the “subscribe” attribute. But we can also achieve the same outcome using the notify attribute:

 

file { '/etc/ssh/sshd_config':
      ensure => file,
      mode   => 600,
      source => 'puppet:///modules/ssh/sshd_config',
      notify => Service['sshd'],
    }
service { 'sshd':
      ensure    => running,
      enable    => true,

    }

 

 

Chaining Arrows

Both the before+after and notify+subscribe relationships can be written in short-hand form with the help of the “chaining arrows” syntax. Chaining arrows also makes your code easier to read.

 

So far we have looked at 2 ways to represent the same ordering. One using the “Before” parameter and the other using the “after” parameter. However there are 2 more ways, but this time using chaining arrows “->”

 

 file {'/tmp/test1':
      ensure  => present,
      content => "Hi.",
 }

 notify {'after':
      message => '/tmp/test1 has already been synced.',
 }
 
 File['/tmp/test1'] -> Notify['after']           # here we used "->" to show the order. 

This is a lot easier to to read, and doesn’t require you to user the before/after metaparameters. Another even simpler way to write the above is:

 
file {'/tmp/test1':
      ensure  => present,
      content => "Hi.",
}
 ->
notify {'after':
      message => '/tmp/test1 has already been synced.',
}

 

We can do the same thing with subscribe/notify, but using “~>” instead of “->”.

A Common Scenario

 
You often find yourself performing a the following sequence of tasks:

  • install package
  • update config files
  • start service

In thi this situation you use the subscribe/notify to help sequence these tasks.

 

 

 

 

 

 

 

Autorequire

Sometimes puppet is smart enough to realise an order even if it hasn’t been explicitly specified. for example you have two resources, one of them creates a folder, and the other creates a file within that folder. In this situation puppet is smart enough to apply the folder resource followed by the file resource.

However it is best practice to not rely on autorequire and just specify the order explicitly.

 

 

 

https://docs.puppetlabs.com/learning/ordering.html

 

https://docs.puppetlabs.com/puppet/latest/reference/lang_relationships.html