Blog: PHP, Python, Linux, Web services & Continuous delivery

Ensure the execution order of classes in Puppet using stages

In order to keep puppet manifests readable I'm organising the configuration using classes that (roughly) group steps by function such as PHP configuration, VHOST setup or Ruby installation. One of the main problems I (and several of my colleagues) were finding is that the order in which puppet classes are executed can change between one provision run and the next. However, with a little research (AKA reading the manual) I came across stages which exist to help with this very problem.

Puppet Stages

Puppet allows you to take a phased approach with the provisioning process, part of the stage definition is to declare if this stage should be executed before or after other stages. Once a stage is defined you then assign classes to it for execution. Puppet defines a 'main' stage by default in which all classes are added unless you specifically assign them to another stage as just described. The main stage is the starting point from which we reference when creating further stages.

The easiest way to explain is by example, the following snippet is the most reliable way I have found of defining stages in a manifest, the ordering of the stage and class definitions is important. The in-line comments in the example should help clarify the process.


 1 #####################
 2 # 1) Define the stages
 3 #####################
 4 
 5 stage { 'prereqs':
 6  before => Stage['main'],
 7 }
 8 
 9 stage { 'final':
10  require => Stage['main'],
11 }
12 
13 #####################
14 # 2) Define the classes
15 #####################
16 
17 # We don't care when this class is executed, it will
18 # be included at random in the main stage
19 class doThisWhenever1 {
20 
21 }
22 
23 # We don't care when this class is executed either, it will
24 # be included at random in the main stage
25 class doThisWhenever2 {
26 
27 }
28 
29 # We want this class to be executed before the
30 # main stage
31 class doThisFirst {
32 
33    exec {'firstThingsFirst':
34      command => '/bin/echo firstThingsFirst',
35    }
36 }
37 
38 # We want this class to be executed after the
39 # main stage
40 class doThisLast {
41 
42   exec {'lastly':
43      command => '/bin/echo lastly',
44    }
45 
46 }
47 
48 #####################
49 # 3) Assign the classes 
50 # to a stage
51 #####################
52 
53 class { 'doThisFirst': 
54   stage => prereqs,
55 }
56 
57 class { 'doThisLast':
58  stage => final,
59 }
60 
61 
62 include doThisFirst
63 include doThisLast   
comments powered by Disqus