salt/doc/topics/tutorials/starting_states.rst

561 lines
17 KiB
ReStructuredText
Raw Normal View History

.. _starting-states:
2011-12-10 07:28:29 +00:00
=========================
How Do I Use Salt States?
=========================
Simplicity, Simplicity, Simplicity
Many of the most powerful and useful engineering solutions are founded on
simple principles. Salt States strive to do just that: K.I.S.S. (Keep It
Stupidly Simple)
2011-12-10 07:28:29 +00:00
The core of the Salt State system is the SLS, or **S**\ a\ **L**\ t
**S**\ tate file. The SLS is a representation of the state in which
a system should be in, and is set up to contain this data in a simple format.
This is often called configuration management.
2011-12-10 07:28:29 +00:00
.. note::
This is just the beginning of using states, make sure to read up on pillar
:ref:`Pillar <pillar-walk-through>` next.
2011-12-10 07:28:29 +00:00
It is All Just Data
===================
Before delving into the particulars, it will help to understand that the SLS
file is just a data structure under the hood. While understanding that the SLS
is just a data structure isn't critical for understanding and making use of
Salt States, it should help bolster knowledge of where the real power is.
2011-12-10 07:28:29 +00:00
SLS files are therefore, in reality, just :ref:`dictionaries
2013-07-23 22:05:59 +00:00
<python2:typesmapping>`, :ref:`lists <python2:typesseq>`, :ref:`strings
<python2:typesseq>`, and :ref:`numbers <python2:typesnumeric>`.
By using this approach Salt can be much more flexible. As one writes more state
files, it becomes clearer exactly what is being written. The result is a system
that is easy to understand, yet grows with the needs of the admin or developer.
2011-12-10 07:28:29 +00:00
The Top File
============
The example SLS files in the below sections can be assigned to hosts using a
file called :strong:`top.sls`. This file is described in-depth :ref:`here
<states-top>`.
2011-12-10 07:28:29 +00:00
2011-12-10 07:28:29 +00:00
Default Data - YAML
===================
By default Salt represents the SLS data in what is one of the simplest
2012-05-23 04:43:12 +00:00
serialization formats available - `YAML`_.
2011-12-10 07:28:29 +00:00
A typical SLS file will often look like this in YAML:
2011-12-10 07:28:29 +00:00
2013-04-29 23:26:49 +00:00
.. note::
These demos use some generic service and package names, different
distributions often use different names for packages and services. For
instance `apache` should be replaced with `httpd` on a Red Hat system.
2013-04-30 19:15:01 +00:00
Salt uses the name of the init script, systemd name, upstart name etc.
based on what the underlying service management for the platform. To
get a list of the available service names on a platform execute the
service.get_all salt function.
2013-04-29 23:26:49 +00:00
Information on how to make states work with multiple distributions
is later in the tutorial.
2011-12-10 07:28:29 +00:00
.. code-block:: yaml
apache:
pkg.installed: []
service.running:
2011-12-10 07:28:29 +00:00
- require:
- pkg: apache
This SLS data will ensure that the package named apache is installed, and
that the apache service is running. The components can be explained in a
simple way.
The first line is the ID for a set of data, and it is called the ID
2011-12-10 07:28:29 +00:00
Declaration. This ID sets the name of the thing that needs to be manipulated.
The second and third lines contain the state module function to be run, in the
format ``<state_module>.<function>``. The ``pkg.installed`` state module
function ensures that a software package is installed via the system's native
package manager. The ``service.running`` state module function ensures that a
given system daemon is running.
Finally, on line five, is the word ``require``. This is called a Requisite
Statement, and it makes sure that the Apache service is only started after
a successful installation of the apache package.
2011-12-10 07:28:29 +00:00
2012-05-23 04:43:12 +00:00
.. _`YAML`: http://yaml.org/spec/1.1/
2011-12-10 07:28:29 +00:00
Adding Configs and Users
========================
2012-05-23 04:43:12 +00:00
When setting up a service like an Apache web server, many more components may
need to be added. The Apache configuration file will most likely be managed,
2011-12-10 07:28:29 +00:00
and a user and group may need to be set up.
.. code-block:: yaml
apache:
pkg.installed: []
service.running:
2011-12-10 07:28:29 +00:00
- watch:
- pkg: apache
- file: /etc/httpd/conf/httpd.conf
- user: apache
user.present:
2011-12-10 07:28:29 +00:00
- uid: 87
- gid: 87
- home: /var/www/html
- shell: /bin/nologin
- require:
- group: apache
group.present:
2011-12-10 07:28:29 +00:00
- gid: 87
- require:
- pkg: apache
/etc/httpd/conf/httpd.conf:
file.managed:
2011-12-10 07:28:29 +00:00
- source: salt://apache/httpd.conf
- user: root
- group: root
- mode: 644
This SLS data greatly extends the first example, and includes a config file,
a user, a group and new requisite statement: ``watch``.
Adding more states is easy, since the new user and group states are under
2012-05-23 04:43:12 +00:00
the Apache ID, the user and group will be the Apache user and group. The
2011-12-10 07:28:29 +00:00
``require`` statements will make sure that the user will only be made after
2012-05-23 04:43:12 +00:00
the group, and that the group will be made only after the Apache package is
2011-12-10 07:28:29 +00:00
installed.
2014-04-30 20:55:30 +00:00
Next, the ``require`` statement under service was changed to watch, and is
2011-12-10 07:28:29 +00:00
now watching 3 states instead of just one. The watch statement does the same
thing as require, making sure that the other states run before running the
state with a watch, but it adds an extra component. The ``watch`` statement
will run the state's watcher function for any changes to the watched states.
So if the package was updated, the config file changed, or the user
2011-12-10 07:28:29 +00:00
uid modified, then the service state's watcher will be run. The service
state's watcher just restarts the service, so in this case, a change in the
config file will also trigger a restart of the respective service.
2011-12-10 07:28:29 +00:00
Moving Beyond a Single SLS
==========================
When setting up Salt States in a scalable manner, more than one SLS will need
to be used. The above examples were in a single SLS file, but two or more
SLS files can be combined to build out a State Tree. The above example also
references a file with a strange source - ``salt://apache/httpd.conf``. That
file will need to be available as well.
2011-12-10 07:28:29 +00:00
The SLS files are laid out in a directory structure on the Salt master; an
SLS is just a file and files to download are just files.
2011-12-10 07:28:29 +00:00
2012-05-23 04:43:12 +00:00
The Apache example would be laid out in the root of the Salt file server like
2014-07-14 17:37:13 +00:00
this:
.. code-block:: text
2011-12-10 07:28:29 +00:00
apache/init.sls
apache/httpd.conf
2011-12-10 07:28:29 +00:00
So the httpd.conf is just a file in the apache directory, and is referenced
directly.
2015-05-18 16:12:07 +00:00
.. include:: ../../_incl/_incl/sls_filename_cant_contain_period.rst
2015-01-20 04:19:23 +00:00
But when using more than one single SLS file, more components can be added to
the toolkit. Consider this SSH example:
2011-12-10 07:28:29 +00:00
``ssh/init.sls:``
2011-12-10 07:28:29 +00:00
.. code-block:: yaml
2011-12-10 07:28:29 +00:00
openssh-client:
pkg.installed
/etc/ssh/ssh_config:
file.managed:
2011-12-10 07:28:29 +00:00
- user: root
- group: root
- mode: 644
- source: salt://ssh/ssh_config
- require:
- pkg: openssh-client
``ssh/server.sls:``
2011-12-10 07:28:29 +00:00
.. code-block:: yaml
include:
- ssh
openssh-server:
pkg.installed
2011-12-10 07:28:29 +00:00
sshd:
service.running:
2011-12-10 07:28:29 +00:00
- require:
- pkg: openssh-client
- pkg: openssh-server
- file: /etc/ssh/banner
- file: /etc/ssh/sshd_config
/etc/ssh/sshd_config:
file.managed:
2011-12-10 07:28:29 +00:00
- user: root
- group: root
- mode: 644
- source: salt://ssh/sshd_config
- require:
- pkg: openssh-server
/etc/ssh/banner:
file:
- managed
- user: root
- group: root
- mode: 644
- source: salt://ssh/banner
- require:
- pkg: openssh-server
.. note::
Notice that we use two similar ways of denoting that a file
is managed by Salt. In the `/etc/ssh/sshd_config` state section above,
we use the `file.managed` state declaration whereas with the
`/etc/ssh/banner` state section, we use the `file` state declaration
and add a `managed` attribute to that state declaration. Both ways
produce an identical result; the first way -- using `file.managed` --
is merely a shortcut.
2014-07-14 17:37:13 +00:00
Now our State Tree looks like this:
.. code-block:: text
2011-12-10 07:28:29 +00:00
apache/init.sls
apache/httpd.conf
ssh/init.sls
ssh/server.sls
ssh/banner
ssh/ssh_config
ssh/sshd_config
2011-12-10 07:28:29 +00:00
This example now introduces the ``include`` statement. The include statement
includes another SLS file so that components found in it can be required,
watched or as will soon be demonstrated - extended.
The include statement allows for states to be cross linked. When an SLS
has an include statement it is literally extended to include the contents of
the included SLS files.
2013-06-21 00:51:19 +00:00
Note that some of the SLS files are called init.sls, while others are not. More
info on what this means can be found in the :ref:`States Tutorial
<sls-file-namespace>`.
2011-12-10 07:28:29 +00:00
Extending Included SLS Data
===========================
Sometimes SLS data needs to be extended. Perhaps the apache service needs to
watch additional resources, or under certain circumstances a different file
needs to be placed.
In these examples, the first will add a custom banner to ssh and the second will
add more watchers to apache to include mod_python.
2011-12-10 07:28:29 +00:00
``ssh/custom-server.sls:``
2011-12-10 07:28:29 +00:00
.. code-block:: yaml
include:
- ssh.server
extend:
/etc/ssh/banner:
file:
- source: salt://ssh/custom-banner
``python/mod_python.sls:``
2011-12-10 07:28:29 +00:00
.. code-block:: yaml
include:
- apache
extend:
apache:
service:
- watch:
- pkg: mod_python
mod_python:
pkg.installed
2011-12-10 07:28:29 +00:00
The ``custom-server.sls`` file uses the extend statement to overwrite where the
2011-12-10 07:28:29 +00:00
banner is being downloaded from, and therefore changing what file is being used
to configure the banner.
In the new mod_python SLS the mod_python package is added, but more importantly
the apache service was extended to also watch the mod_python package.
2015-05-18 16:12:07 +00:00
.. include:: ../../_incl/extend_with_require_watch.rst
2011-12-10 07:28:29 +00:00
2011-12-10 07:28:29 +00:00
Understanding the Render System
===============================
Since SLS data is simply that (data), it does not need to be represented
2011-12-10 07:28:29 +00:00
with YAML. Salt defaults to YAML because it is very straightforward and easy
to learn and use. But the SLS files can be rendered from almost any imaginable
medium, so long as a renderer module is provided.
The default rendering system is the ``yaml_jinja`` renderer. The
2012-05-23 04:43:12 +00:00
``yaml_jinja`` renderer will first pass the template through the `Jinja2`_
2011-12-10 07:28:29 +00:00
templating system, and then through the YAML parser. The benefit here is that
full programming constructs are available when creating SLS files.
Other renderers available are ``yaml_mako`` and ``yaml_wempy`` which each use
the `Mako`_ or `Wempy`_ templating system respectively rather than the jinja
templating system, and more notably, the pure Python or ``py``, ``pydsl`` &
``pyobjects`` renderers.
The ``py`` renderer allows for SLS files to be written in pure Python,
allowing for the utmost level of flexibility and power when preparing SLS
data; while the :mod:`pydsl<salt.renderers.pydsl>` renderer
provides a flexible, domain-specific language for authoring SLS data in Python;
and the :mod:`pyobjects<salt.renderers.pyobjects>` renderer
gives you a `"Pythonic"`_ interface to building state data.
2011-12-10 07:28:29 +00:00
2012-05-23 04:43:12 +00:00
.. _`Jinja2`: http://jinja.pocoo.org/
.. _`Mako`: http://www.makotemplates.org/
.. _`Wempy`: https://fossil.secution.com/u/gcw/wempy/doc/tip/README.wiki
.. _`"Pythonic"`: http://legacy.python.org/dev/peps/pep-0008/
2012-05-23 04:43:12 +00:00
.. note::
2014-07-14 17:37:13 +00:00
The templating engines described above aren't just available in SLS files.
They can also be used in :mod:`file.managed <salt.states.file.managed>`
states, making file management much more dynamic and flexible. Some
examples for using templates in managed files can be found in the
documentation for the :mod:`file state <salt.states.file>`, as well as the
:ref:`MooseFS example<jinja-example-moosefs>` below.
Getting to Know the Default - yaml_jinja
----------------------------------------
2011-12-10 07:28:29 +00:00
The default renderer - ``yaml_jinja``, allows for use of the jinja
2012-05-23 04:43:12 +00:00
templating system. A guide to the Jinja templating system can be found here:
http://jinja.pocoo.org/docs
2011-12-10 07:28:29 +00:00
When working with renderers a few very useful bits of data are passed in. In
the case of templating engine based renderers, three critical components are
2012-05-23 04:43:12 +00:00
available, ``salt``, ``grains``, and ``pillar``. The ``salt`` object allows for
any Salt function to be called from within the template, and ``grains`` allows
for the Grains to be accessed from within the template. A few examples:
2011-12-10 07:28:29 +00:00
``apache/init.sls:``
.. code-block:: jinja
2011-12-10 07:28:29 +00:00
apache:
pkg.installed:
2011-12-10 07:28:29 +00:00
{% if grains['os'] == 'RedHat'%}
- name: httpd
{% endif %}
service.running:
2011-12-10 07:28:29 +00:00
{% if grains['os'] == 'RedHat'%}
- name: httpd
{% endif %}
- watch:
- pkg: apache
- file: /etc/httpd/conf/httpd.conf
- user: apache
user.present:
2011-12-10 07:28:29 +00:00
- uid: 87
- gid: 87
- home: /var/www/html
- shell: /bin/nologin
- require:
- group: apache
group.present:
2011-12-10 07:28:29 +00:00
- gid: 87
- require:
- pkg: apache
/etc/httpd/conf/httpd.conf:
file.managed:
2011-12-10 07:28:29 +00:00
- source: salt://apache/httpd.conf
- user: root
- group: root
- mode: 644
This example is simple. If the ``os`` grain states that the operating system is
2012-05-23 04:43:12 +00:00
Red Hat, then the name of the Apache package and service needs to be httpd.
2011-12-10 07:28:29 +00:00
.. _jinja-example-moosefs:
2011-12-10 07:28:29 +00:00
A more aggressive way to use Jinja can be found here, in a module to set up
a MooseFS distributed filesystem chunkserver:
``moosefs/chunk.sls:``
.. code-block:: jinja
2011-12-10 07:28:29 +00:00
include:
- moosefs
{% for mnt in salt['cmd.run']('ls /dev/data/moose*').split() %}
/mnt/moose{{ mnt[-1] }}:
mount.mounted:
2011-12-10 07:28:29 +00:00
- device: {{ mnt }}
- fstype: xfs
- mkmnt: True
file.directory:
2011-12-10 07:28:29 +00:00
- user: mfs
- group: mfs
- require:
- user: mfs
- group: mfs
{% endfor %}
/etc/mfshdd.cfg:
file.managed:
2011-12-10 07:28:29 +00:00
- source: salt://moosefs/mfshdd.cfg
- user: root
- group: root
- mode: 644
- template: jinja
- require:
- pkg: mfs-chunkserver
/etc/mfschunkserver.cfg:
file.managed:
2011-12-10 07:28:29 +00:00
- source: salt://moosefs/mfschunkserver.cfg
- user: root
- group: root
- mode: 644
- template: jinja
- require:
- pkg: mfs-chunkserver
mfs-chunkserver:
pkg.installed: []
2011-12-10 07:28:29 +00:00
mfschunkserver:
service.running:
2011-12-10 07:28:29 +00:00
- require:
{% for mnt in salt['cmd.run']('ls /dev/data/moose*') %}
- mount: /mnt/moose{{ mnt[-1] }}
- file: /mnt/moose{{ mnt[-1] }}
{% endfor %}
- file: /etc/mfschunkserver.cfg
- file: /etc/mfshdd.cfg
- file: /var/lib/mfs
This example shows much more of the available power of Jinja.
2011-12-10 07:28:29 +00:00
Multiple for loops are used to dynamically detect available hard drives
and set them up to be mounted, and the ``salt`` object is used multiple
times to call shell commands to gather data.
2014-12-12 19:32:58 +00:00
Introducing the Python, PyDSL, and the Pyobjects Renderers
----------------------------------------------------------
2011-12-10 07:28:29 +00:00
Sometimes the chosen default renderer might not have enough logical power to
2012-05-23 04:43:12 +00:00
accomplish the needed task. When this happens, the Python renderer can be
used. Normally a YAML renderer should be used for the majority of SLS files,
but an SLS file set to use another renderer can be easily added to the tree.
2011-12-10 07:28:29 +00:00
2012-05-23 04:43:12 +00:00
This example shows a very basic Python SLS file:
2011-12-10 07:28:29 +00:00
``python/django.sls:``
2011-12-10 07:28:29 +00:00
.. code-block:: python
#!py
def run():
'''
Install the django package
'''
return {'include': ['python'],
'django': {'pkg': ['installed']}}
2011-12-10 07:28:29 +00:00
This is a very simple example; the first line has an SLS shebang that
2011-12-10 07:28:29 +00:00
tells Salt to not use the default renderer, but to use the ``py`` renderer.
Then the run function is defined, the return value from the run function
must be a Salt friendly data structure, or better known as a Salt
:ref:`HighState data structure<states-highstate>`.
2011-12-10 07:28:29 +00:00
Alternatively, using the :mod:`pydsl<salt.renderers.pydsl>`
renderer, the above example can be written more succinctly as:
.. code-block:: python
#!pydsl
include('python', delayed=True)
state('django').pkg.installed()
The :mod:`pyobjects<salt.renderers.pyobjects>` renderer
provides an `"Pythonic"`_ object based approach for building the state data.
The above example could be written as:
.. code-block:: python
#!pyobjects
include('python')
Pkg.installed("django")
These Python examples would look like this if they were written in YAML:
2011-12-10 07:28:29 +00:00
.. code-block:: yaml
include:
- python
django:
pkg.installed
2011-12-10 07:28:29 +00:00
This example clearly illustrates that; one, using the YAML renderer by default
is a wise decision and two, unbridled power can be obtained where needed by
using a pure Python SLS.
[2016.3] Merge forward from 2015.8 to 2016.3 (#32784) * json encode arguments passed to an execution module function call this fixes problems where you could pass a string to a module function, which thanks to the yaml decoder which is used when parsing command line arguments could change its type entirely. for example: __salt__['test.echo')('{foo: bar}') the test.echo function just returns the argument it's given. however, because it's being called through a salt-call process like this: salt-call --local test.echo {foo: bar} salt thinks it's yaml and therefore yaml decodes it. the return value from the test.echo call above is therefore a dict, not a string. * Prevent crash if pygit2 package is requesting re-compilation of the e… (#32652) * Prevent crash if pygit2 package is requesting re-compilation of the entire library on production systems (no *devel packages) * Fix PEP8: move imports to the top of the file * Move logger up * Add log error message in case if exception is not an ImportError * align OS grains from older SLES with current one (#32649) * Fixing critical bug to remove only the specified Host instead of the entire Host cluster (#32640) * yumpkg: Ignore epoch in version comparison for explict versions without an epoch (#32563) * yumpkg: Ignore epoch in version comparison for explict versions without an epoch Also properly handle comparisions for packages with multiple versions. Resolves #32229 * Don't attempt downgrade for kernel and its subpackages Multiple versions are supported since their paths do not conflict. * Lower log level for pillar cache (#32655) This shouldn't show up on salt-call runs * Don't access deprecated Exception.message attribute. (#32556) * Don't access deprecated Exception.message attribute. To avoid a deprecation warning message in logs. There is a new function salt.exceptions.get_error_message(e) instead. * Fixed module docs test. * Fix for issue 32523 (#32672) * Fix routes for redhat < 6 * Handle a couple of arguments better (Azure) (#32683) * backporting a fix from develop where the use of splay would result in seconds=0 in the schedule.list when there was no seconds specified in the origina schedule * Handle when beacon not configured and we try to enable/disable them (#32692) * Handle the situation when the beacon is not configured and we try to disable it * a couple more missing returns in the enable & disable * Check dependencies type before appling str operations (#32693) * Update external auth documentation to list supported matcher. (#32733) Thanks to #31598, all matchers are supported for eauth configuration. But we still have no way to use compound matchers in eauth configuration. Update the documentation to explicitly express this limitation. * modules.win_dacl: consistent case of dacl constants (#32720) * Document pillar cache options (#32643) * Add note about Pillar data cache requirement for Pillar targeting method * Add `saltutil.refresh_pillar` function to the scheduled Minion jobs * Minor fixes in docs * Add note about relations between `pillar_cache` option and Pillar Targeting to Master config comments with small reformatting * Document Pillar Cache Options for Salt Master * Document Minions Targeting with Mine * Remove `saltutil.refresh_pillar` scheduled persistent job * Properly handle minion failback failure. (#32749) * Properly handle minion failback failure. Initiate minion restart if all masters down on __master_disconnect like minion does on the initial master connect on start. * Fixed unit test * Improve documentation on pygit2 versions (#32779) This adds an explanation of the python-cffi dep added in pygit2 0.21.0, and recommends 0.20.3 for LTS distros. It also links to the salt-pack issue which tracks the progress of adding pygit2 to our Debian and Ubuntu repositories. * Pylint fix
2016-04-25 21:26:09 +00:00
Running and Debugging Salt States
---------------------------------
Once the rules in an SLS are ready, they should be tested to ensure they
work properly. To invoke these rules, simply execute
``salt '*' state.apply`` on the command line. If you get back only
hostnames with a ``:`` after, but no return, chances are there is a problem with
one or more of the sls files. On the minion, use the ``salt-call`` command to
examine the output for errors:
.. code-block:: bash
salt-call state.apply -l debug
This should help troubleshoot the issue. The minion can also be started in the
foreground in debug mode by running ``salt-minion -l debug``.
Next Reading
============
With an understanding of states, the next recommendation is to become familiar
with Salt's pillar interface:
:ref:`Pillar Walkthrough <pillar-walk-through>`