Using Puppet Templates
Puppet supports templates and templating via ERB, which is part of the Ruby standard library and is used for many other projects including Ruby on Rails. Templates allow you to manage the content of template files, for example configuration files that cannot yet be managed as a Puppet type.
Evaluating templates
Templates are evaluated via a simple function:
$value = template("mytemplate.erb")
You can specify the full path to your template, or you can put all your templates in Puppet's templatedir, which usually defaults to /var/puppet/templates (you can find out what it is on your system by running puppet --configprint templatedir).
Templates are always evaluated by the parser, not by the client. This means that if you are using puppetmasterd, then the templates only need to be on the server, and you never need to download them to the client. There's no difference to the client between using a template and specifying all of the text as a string. This also means that any client-specific variables (facts) are learned first by puppetmasterd during the client start-up phase, then those variables are available for substitution within templates.
Using templates
Templating is pretty simple: You can directly reference any variables within your template that are defined within the enclosing scope.
This is especially useful for generating complete files; here is how I generate the Apache configuration for my Trac sites:
define tracsite($cgidir, $tracdir) {
file { "trac-$name":
path => "/etc/apache2/trac/$name.conf",
owner => root,
group => root,
mode => 644,
require => File[apacheconf],
content => template("tracsite.erb"),
notify => Service[apache2]
}
symlink { "tracsym-$name":
path => "$cgidir/$name.cgi",
ensure => "/usr/share/trac/cgi-bin/trac.cgi"
}
}
And then here's my template:
<Location "/cgi-bin/ <%= name %>.cgi">
SetEnv TRAC_ENV "/export/svn/trac/<%= name %>"
</Location>
# You need something like this to authenticate users
<Location "/cgi-bin/<%= name %>.cgi/login">
AuthType Basic
AuthName "Trac"
AuthUserFile /etc/apache2/auth/svn
Require valid-user
</Location>
You can see that I put each Trac configuration into a separate file, and then I just tell Apache to load all of these files:
Include /etc/apache2/trac/[^.#]*
The above template is quite simple, in that it only uses the Puppet-defined name variable, but it provides a clean separation between the format of the configuration file and how I generate it.
Combining templates
You can also put several templates together by specifying
template(/path/to/template1,/path/to/template2)
Iteration
Puppet's templates also support iteration. If the variable you are accessing is an array, you can iterate over it. Given Puppet code like this:
$values = [val1, val2, otherval]
You could have a template like this:
<% values.each do |val| -%> Some stuff with <%= val %> <% end -%>
This would produce:
Some stuff with val1 Some stuff with val2 Some stuff with otherval
Note that normally, ERB template lines that just have code on them would get translated into blank lines. To prevent this, we use the close tag -%> instead of %>.
Internally, Puppet's values get translated to real Ruby values, including true and false, so you can be pretty confident that variables will behave as you might expect.
Conditionals
The ERB templating supports conditionals. Such a construct:
<% if broadcast != "NONE" %> broadcast <%= broadcast %> <% end %>
is a quick and easy way to conditionally put content in templates.
Templates and variables
You can also use templates to create variables not just file content.
myvariable = template('/var/puppet/template/myvar')
Out of scope variables
You can access out of scope variables explicitly with the lookupvar function, similar to the use of variables in Writing Your Own Functions. For example:
<%= scope.lookupvar('apache::user') %>
Syntax Checking
ERB files are easy to syntax check. For a file mytemplate.erb, run
erb -x -T '-' mytemplate.erb | ruby -c
The trim option specified corresponds to what Puppet uses.