This tutorial builds on the topic covered in part 1 <states_pt1>
. It is recommended that you begin there.
In the last Salt States tutorial we covered the basics of installing a package. In this tutorial we will modify our webserver.sls
file to be more complicated, have requirements, and use even more Salt States.
You can specify multiple state declarations <state declaration>
under an ID declaration
. For example, a quick modification to our webserver.sls
to also start Apache if it is not running:
apache:
pkg:
- installed
service:
- running
Try stopping Apache before running state.highstate
once again and observe the output.
As you have seen, sls modules are appended with the file extension .sls
and are referenced by name starting at the root of the state tree. An SLS module can be also defined as a directory. Demonstrate that now by creating a directory named webserver
and moving and renaming webserver.sls
to webserver/init.sls
. Your state directory should now resemble:
|- top.sls
`- webserver/
`- init.sls
Organizing SLS modules
You can place additional .sls
files in a state file directory. This affords much cleaner organization of your state tree on the filesystem. For example, if we created a webserver/django.sls
file that module would be referenced as webserver.django
.
In addition, States provide powerful includes and extending functionality which we will cover in Part 3 <states_pt3>
.
We now have a working installation of Apache so let's add an HTML file to customize our website. It isn't exactly useful to have a website without a webserver so we don't want Salt to install our HTML file until Apache is installed and running. Include the following at the bottom of your webserver/init.sls
file:
apache:
pkg:
- installed
service:
- running
/var/www/index.html: # ID declaration
file: # state declaration
- managed # function
- source: salt://webserver/index.html # function arg
- require: # requisite declaration
- pkg: apache # requisite reference
Again in line 1 is the ID declaration
. In this example it is the location we want to install our custom HTML file. (Note: the default location that Apache serves may differ from the above on your OS or distro. /srv/www
could also be a likely place to look.)
Line 2 the state declaration
. This example uses the Salt file
state <salt.states.file>
.
Line 3 is the function declaration
. The managed function
<salt.states.file.managed>
will download a file from the master and install it in the location specified.
Line 4 is a function arg declaration
which, in this example, passes the source
argument to the managed function
<salt.states.file.managed>
.
Line 5 is a requisite declaration
.
Line 6 is a requisite reference
which refers to a state and an ID. In this example, it is referring to the ID declaration
from our example in part 1 <states_pt1>
. This declaration tells Salt not to install the HTML file until Apache is installed.
Next, create the index.html
file and save it in the webserver
directory:
<html>
<head><title>Salt rocks</title></head>
<body>
<h1>This file brought to you by Salt</h1>
</body>
</html>
Last, call state.highstate <salt.modules.state.highstate>
again and the minion will fetch and execute the highstate as well as our HTML file from the master using Salt's File Server:
salt '*' salt.highstate
Verify that Apache is now serving your custom HTML.
require
vs. watch
There are two requisite declarations <requisite declaration>
, “require” and “watch”. Not every state supports “watch”. The service
state <salt.states.service>
does support “watch” and will restart a service based on the watch condition.
For example, if you use Salt to install an Apache virtual host configuration file and want to restart Apache whenever that file is changed you could modify our Apache example from earlier as follows:
/etc/httpd/extra/httpd-vhosts.conf:
file:
- managed
- source: salt://webserver/httpd-vhosts.conf
apache:
pkg:
- installed
service:
- running
- watch:
- file: /etc/httpd/extra/httpd-vhosts.conf
If the pkg and service names differ on your OS or distro of choice you can specify each one separately using a name declaration
which explained in Part 3 <states_pt3>
.
In part 3 <states_pt3>
we will discuss how to use includes, extends and templating to make hugely complicated State Tree configurations dead-simple.