Puppet Resource Ordering Options

Over the years Puppet has handled resources ordering without explicit dependencies in different ways, with the release of Puppet 3.3.0 they’ve exposed this ordering logic to the admin with three interesting options.

To test these options out we’ll use the ‘ordering’ test module shown below. We include three classes, ordering::beta, ordering::alpha and ordering::gamma (note that the includes are not in alphabetically sorted order). Each of these classes has three notify statements that show a number and the class they are contained in.

$ find

./modules
./modules/ordering
./modules/ordering/manifests
./modules/ordering/manifests/init.pp
./modules/ordering/manifests/alpha.pp
./modules/ordering/manifests/beta.pp
./modules/ordering/manifests/gamma.pp

$ find -type f | xargs -n 1 cat

class ordering {
  include ordering::beta
  include ordering::alpha
  include ordering::gamma
}

class ordering::alpha {
  notify { "Hello number 1 from ordering::alpha": }
  notify { "Hello number 2 from ordering::alpha": }
  notify { "Hello number 3 from ordering::alpha": }
}

class ordering::beta {
  notify { "Hello number 1 from ordering::beta": }
  notify { "Hello number 2 from ordering::beta": }
  notify { "Hello number 3 from ordering::beta": }
}

class ordering::gamma {
  notify { "Hello number 1 from ordering::gamma": }
  notify { "Hello number 2 from ordering::gamma": }
  notify { "Hello number 3 from ordering::gamma": }
}

First we’ll try the default option - title-hash. This randomly orders resources, but will be consistent across runs and nodes. We’ll do two runs of each option to see if anything changes.

  puppet apply --modulepath modules -e 'include ordering'  --ordering title-hash | grep -v Stage

Notice: Hello number 3 from ordering::alpha
Notice: Hello number 1 from ordering::alpha
Notice: Hello number 2 from ordering::alpha
Notice: Hello number 1 from ordering::beta
Notice: Hello number 2 from ordering::beta
Notice: Hello number 2 from ordering::gamma
Notice: Hello number 3 from ordering::gamma
Notice: Hello number 1 from ordering::gamma
Notice: Hello number 3 from ordering::beta

  puppet apply --modulepath modules -e 'include ordering'  --ordering title-hash | grep -v Stage

Notice: Hello number 3 from ordering::alpha
Notice: Hello number 1 from ordering::alpha
Notice: Hello number 2 from ordering::alpha
Notice: Hello number 1 from ordering::beta
Notice: Hello number 2 from ordering::beta
Notice: Hello number 2 from ordering::gamma
Notice: Hello number 3 from ordering::gamma
Notice: Hello number 1 from ordering::gamma
Notice: Hello number 3 from ordering::beta

This confirms that the ordering is consistent between runs. It starts off predictably with ordering::alpha running first but note the ordering::beta at the end, and the difference in ordering of the notifys within each class. Hopefully you can see that it’s not an ordering you should rely upon within your own classes or assume you can predict.

Now we’ll look at the manifest value, or ‘chef mode’ as I’ve heard it nicknamed. This option will cause the resources to be actioned in in exactly the order you’ve written.

  puppet apply --modulepath modules -e 'include ordering'  --ordering manifest | grep -v Stage

Notice: Hello number 1 from ordering::beta
Notice: Hello number 2 from ordering::beta
Notice: Hello number 3 from ordering::beta

Notice: Hello number 1 from ordering::alpha
Notice: Hello number 2 from ordering::alpha
Notice: Hello number 3 from ordering::alpha

Notice: Hello number 1 from ordering::gamma
Notice: Hello number 2 from ordering::gamma
Notice: Hello number 3 from ordering::gamma

  puppet apply --modulepath modules -e 'include ordering'  --ordering manifest | grep -v Stage

Notice: Hello number 1 from ordering::beta
Notice: Hello number 2 from ordering::beta
Notice: Hello number 3 from ordering::beta

Notice: Hello number 1 from ordering::alpha
Notice: Hello number 2 from ordering::alpha
Notice: Hello number 3 from ordering::alpha

Notice: Hello number 1 from ordering::gamma
Notice: Hello number 2 from ordering::gamma
Notice: Hello number 3 from ordering::gamma

I’ve spaced the output slightly you can see that the order is consistent between runs and grouped in order, by class. Looking at the notify output you can see it’s been produced exactly as we wrote the classes.

The third and final option is my personal favourite and something I’ve already enabled on some of my dev puppet masters. Setting the ordering to random does exactly what the name implies, it orders resources, including includes!, randomly within a single run and across multiple runs.

  puppet apply --modulepath modules -e 'include ordering'  --ordering random | grep -v Stage

Notice: Hello number 3 from ordering::gamma
Notice: Hello number 2 from ordering::gamma
Notice: Hello number 2 from ordering::alpha
Notice: Hello number 3 from ordering::alpha
Notice: Hello number 2 from ordering::beta
Notice: Hello number 3 from ordering::beta
Notice: Hello number 1 from ordering::beta
Notice: Hello number 1 from ordering::alpha
Notice: Hello number 1 from ordering::gamma

  puppet apply --modulepath modules -e 'include ordering'  --ordering random | grep -v Stage

Notice: Hello number 1 from ordering::beta
Notice: Hello number 1 from ordering::alpha
Notice: Hello number 2 from ordering::beta
Notice: Hello number 3 from ordering::beta
Notice: Hello number 3 from ordering::alpha
Notice: Hello number 2 from ordering::alpha
Notice: Hello number 2 from ordering::gamma
Notice: Hello number 1 from ordering::gamma
Notice: Hello number 3 from ordering::gamma

This is a great way to find implicit relationships that have accidentally slipped in to modules before they become real problems. I’d recommend having development hosts and CI boxes running under random to help keep your code explicit and honest.

As a reminder these options -DO NOT- change explicit relationships in your classes and modules. If explicit ordering is required for your resources, and especially if you upload the modules to the puppetforge or github where you have no visibility of peoples puppet settings, you should continue to use requires / notify / before / after metaparameters even if you set ordering to manifest.