Explicit high-level dependencies in Puppet

October 9, 2019 

I've noticed that some people - I won't reveal their names here to protect them - love using contain and/or ordering arrows in Puppet. A typical use-case is for role classes:

class role::webserver {
  contain ::packetfilter::endpoint
  contain ::profile::monit
  contain ::profile::unixbase
  contain ::profile::ipa_client
  contain ::profile::webserver

  -> Class[::profile::monit]
  -> Class[::profile::unixbase]
  -> Class[::profile::ipa_client]
  -> Class[::profile::webserver]

The above code nicely ensures that all the classes get applied in the exact order defined above. What happens under the hood is that Puppet generates dependencies between the classes and applies them in order.

Serializing the execution order probably has some performance cost as Puppet is not able to run as many tasks at any given time as it otherwise could. I'm not sure if this has any practical effect. Another issue is that if Puppet run fails at any of the above classes none of the classes that come after will not get applied. So, instead of just one tiny thing failing a large chunk of the catalog fails.

I have not been a big fan of creating dependencies between high-level resources such as profiles. In pretty much all cases you need to define dependencies between resources anyways, and if you do that properly, you don't need to declare high-level dependencies at all.

That said, today was the first time I actually ran into a problem with the above pattern in roles (such as the above) when ipa-client package on a particular OS had a bug which caused ::profile::ipa_client to fail. So the belt and suspenders is not that bad, even if it is somewhat reduntant in many cases.

EDIT: fixed wrong terminology. The above did not represent the classic anchor pattern as I originally claimed.

Samuli Seppänen
Samuli Seppänen
Author archive