Male Instructor: We previously saw we can tell Puppet
to copy a static file such as a simple configuration file
to a node, but most of the time you will
need Puppet to tweak the contents of a file
based on the value of certain facts about the node.
For example, if you were writing a module
to configure Apache, the config file entry
for the location of the ServerRoot would be different
for Debian based systems and Red Hat based systems.
Now you could, in theory,
just have a different static config file for each OS family.
But that would be maintenance nightmare
because most of the entries in the config file
would be the same for all OS families.
So if you ever needed to change any of those lines,
you'd have to change them in every single config file.
It would be much better to have a single file
with variables in it based on the OS family.
Puppet calls this type of file a template.
No I'm going to show you how we can
make our motd Apache module more robust by using a template.
Suppose instead of just having the message of the day
tell us what the Apache service is called,
we also want it to tell us the location
of Apache ServerRoot and document root.
Although we could do all of this
in our module's main manifest, it would make more sense
to create a template and just have the main manifest
use the template.
That way if we need to add more functionality
to the module then the main manifest
won't be cluttered with config file details.
Before we get started it's important to know Puppet
supports two different templating languages: EPP and ERB.
EPP wasn't available until Puppet 3.5
so a lot of the Puppet templates out there
are written in ERB.
However, I strongly recommend that you use EPP instead
because EPP uses the Puppet language.
It stands for Embedded Puppet.
Whereas ERB uses Ruby.
It stands for Embedded Ruby.
So with EPP the language is consistent
between your other Puppet files and your templates.
Also, unlike ERB, EPP supports parameters
and it has a much cleaner way of accessing variables.
First we have to create a directory for our template
because the Puppet module generate command
didn't create one.
It should be called templates.
Lets call our template motd.epp.
Although you don't have to use the EPP extension
you definitely should so that it will be obvious
which templating language it uses.
Lets do something simple first.
Let's just write a sentence
that says the name of the operating system.
Now what fact do we need to insert here?
Let's have a look at the list of core facts again.
Oh yeah, it's the name element of the OS fact.
We saw that one last time.
In an EPP template when you need to insert
some Puppet code, you just put some special tags around it.
The two main types of tags
are Expression-printing and Non-printing tags.
Use Expression-printing tags when you want to
insert an expression that will be evaluated
and printed in the file.
Use Non-printing tags when you need to
insert some code that won't print anything.
In this case, we need to use an Expression-printing tag
because we want to print the name of the operating system.
Now we need to go back to the main manifest
and tell it to use this template.
First we'll erase the selector we put in before.
Then we'll change the value of the content attribute
to be the template we just created.
We do that with the EPP function,
which is a built in function that knows how
to interpret templates written in EPP.
To call a function you just use the function name
and follow it with brackets
surrounding any arguments you need to pass.
In this case the argument is the name of the template.
First we put in a quote,
then the name of the module where the template resides,
then a slash then the template's file name.
Notice that this is not the path name,
because it doesn't mention the template's directory.
It's just the module name slash the template file name.
Then put in a closing quote and closing bracket.
Okay, let's give it a try.
Yes, it says that we're running Ubuntu.
Now that our template is working,
let's put in the information about Apache's service name,
service root, and document root.
The three new lines are very similar
to the line we already put in about the OS name.
I'll skip ahead instead of making you watch me type them in.
You can see that in each case there is a variable
surrounded by an Expression-printing tag.
I used variables instead of facts because Puppet
doesn't have any built-in facts about Apache.
So we'll have to set these variables first.
We could use a selector again but since we will
be setting three variables for each OS family
it might be easier to read if we use a case statement
to organize the information by OS family.
Since we will be writing code that just sets variables
rather than printing anything,
we need to use a Non-printing tag.
Then we type case followed by an expression
that we'll resolve to a value.
In this case we want the value
to be the name of the OS family.
So we'll put in the built-in fact for that.
Then we put in an opening brace.
On the next line, we put in one possible value,
we'll start with Debian, and we'll put it in quotes
because it's a string.
Then a colon and another opening brace.
On the next three lines, we'll set the three variables
to the appropriate Apache information.
I'll just skip ahead again.
Then we add a closing brace
and another potential value for the OS family, Red Hat.
I'll skip ahead after filling in the rest
of the case statement.
Now we'll put in a closing brace
for the whole case statement.
Also close off the Non-printing tag.
This time we'll use a slightly different closing tag
because we don't want this code
to produce a black line in the motd file.
You would think that a Non-printing tag
wouldn't print anything, but it actually prints a new line
unless you use a closing tag that strips that out.
The closing tag that does this is the same
except that it starts with a dash.
Alright let's see if it works.
Great, it printed out the right Apache
information for Ubuntu.
That's it for this lesson.