Project

General

Profile

Instantiate Puppet resources » History » Version 5

Dominic Cleal, 02/12/2015 11:49 AM
mistakes!

1 1 Dominic Cleal
h1. Instantiate Puppet resources
2
3
Foreman acts as an external node classifier (ENC) for Puppet, which allows it to pass a list of classes, global and class parameters.  It isn't able to instantiate individual resources (such as a file or package), or a defined type through this interface.
4
5
Instead, you have a few possible approaches.
6
7 2 Dominic Cleal
h2. Creating a simple wrapper class or module
8 1 Dominic Cleal
9
Resources should generally be kept in a class which can then be included where needed.  For static resources, this is the best way.
10
11
* "Learning Puppet — Modules and Classes":https://docs.puppetlabs.com/learning/modules1.html
12
13
h2. Basic dynamic resources with arrays
14
15
If the resources you're managing are simple and all have the same properties and parameters, you can use Puppet's array resource declaration syntax ("array of title docs":https://docs.puppetlabs.com/puppet/3/reference/lang_resources.html#array-of-titles) to create many resources at once.
16
17
In this example to install a list of packages, we create /etc/puppet/environments/production/modules/packages/manifests/init.pp with:
18
19
<pre>
20
class packages($list = []) {
21
  package { $list:
22
    ensure => installed,
23
  }
24
}
25
</pre>
26
27
When you import this "packages" class, it will have a "list" parameter.  In Foreman's UI, go to _Configure_, _Puppet classes_, "packages", _Smart class parameters_ and tick the _Override_ checkbox on the "list" parameter.  Set the _Parameter type_ to _json_ and use "JSON syntax":http://www.w3schools.com/json/json_syntax.asp to set the list parameter to an array of values, e.g.
28
29
    ["httpd","vim"]
30
31
You can then override this per host or host group and supply a new array.
32 2 Dominic Cleal
33
h2. Advanced dynamic resources with create_resources
34
35
Puppet ships a "create_resources function":https://docs.puppetlabs.com/references/stable/function.html#createresources (since Puppet 2.7) that takes a hash of resources to instantiate, and this hash can again be passed into a class as a parameter.
36
37
Use a similar pattern to the example above, but this time we'll pass an entire hash in:
38
39
<pre>
40
class packages($resources = {}) {
41
  create_resources('package', $resources)
42
}
43
</pre>
44
45
For the parameter value, again set the parameter type to JSON or YAML and then store a hash such as this (JSON example):
46
47
<pre>
48
{"httpd":{"ensure":"installed"},"vim":{"ensure":"installed"},"emacs":{"ensure":"absent"}}
49
</pre>
50
51 3 Dominic Cleal
Note that the keys of the first level of the hash are the names of the resources (what usually goes after the resource type on the first list), and then the values are a full hash of the properties and parameters of the resource.  You'll need to supply them all ("type documentation":http://docs.puppetlabs.com/references/stable/type.html).
52 2 Dominic Cleal
53
Also important is that JSON hashes do not have the same syntax as Puppet.  JSON uses colons (":") as key/value separators, while Puppet uses "=>".  Foreman will give a parse error if you try using "=>"!
54
55
Foreman can store complex parameters using YAML or JSON, here's a YAML example which may be easier to read and work with:
56
57
<pre>
58
---
59
httpd:
60
  ensure: installed
61
vim:
62
  ensure: installed
63
emacs:
64 1 Dominic Cleal
  ensure: absent
65 3 Dominic Cleal
</pre>
66
67
h2. Using defined types to minimise duplication
68
69
Using create_resources means all resource properties/params need to be passed in.  When they're often the same, or you have multiple resources to instantiate, it's usually simpler to wrap it all in a defined type and then instantiate that.  Here's an example to manage services:
70
71
/etc/puppet/environments/production/modules/services_wrapper/manifests/single_service.pp (depends on "stdlib":https://forge.puppetlabs.com/puppetlabs/stdlib):
72
<pre>
73 5 Dominic Cleal
define services_wrapper::single_service($start = true) {
74 3 Dominic Cleal
  service { $title:
75 5 Dominic Cleal
    ensure => str2bool($start) ? {
76 4 Dominic Cleal
      true  => 'running',
77
      false => 'stopped',
78
    },
79 5 Dominic Cleal
    enable => str2bool($start),
80 3 Dominic Cleal
  }
81
}
82
</pre>
83
84
/etc/puppet/environments/production/modules/services_wrapper/manifests/init.pp:
85
<pre>
86
class services_wrapper($resources = {}) {
87
  create_resources('services_wrapper::single_service', $resources)
88
}
89
</pre>
90
91
And then in the parameter:
92
93
<pre>
94
---
95
httpd:
96
dbus:
97
nfs:
98
  start: false
99 2 Dominic Cleal
</pre>