123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356 |
- .. _compiler-ordering:
- =====================================
- Understanding State Compiler Ordering
- =====================================
- .. note::
- This tutorial is an intermediate level tutorial. Some basic understanding
- of the state system and writing Salt Formulas is assumed.
- Salt's state system is built to deliver all of the power of configuration
- management systems without sacrificing simplicity. This tutorial is made to
- help users understand in detail just how the order is defined for state
- executions in Salt.
- This tutorial is written to represent the behavior of Salt as of version
- 0.17.0.
- Compiler Basics
- ===============
- To understand ordering in depth some very basic knowledge about the state
- compiler is very helpful. No need to worry though, this is very high level!
- High Data and Low Data
- ----------------------
- When defining Salt Formulas in YAML the data that is being represented is
- referred to by the compiler as High Data. When the data is initially
- loaded into the compiler it is a single large python dictionary, this
- dictionary can be viewed raw by running:
- .. code-block:: bash
- salt '*' state.show_highstate
- This "High Data" structure is then compiled down to "Low Data". The Low
- Data is what is matched up to create individual executions in Salt's
- configuration management system. The
- low data is an ordered list of single state calls to execute. Once the
- low data is compiled the evaluation order can be seen.
- The low data can be viewed by running:
- .. code-block:: bash
- salt '*' state.show_lowstate
- .. note::
- The state execution module contains MANY functions for evaluating the
- state system and is well worth a read! These routines can be very useful
- when debugging states or to help deepen one's understanding of Salt's
- state system.
- As an example, a state written thusly:
- .. code-block:: yaml
- apache:
- pkg.installed:
- - name: httpd
- service.running:
- - name: httpd
- - watch:
- - file: apache_conf
- - pkg: apache
- apache_conf:
- file.managed:
- - name: /etc/httpd/conf.d/httpd.conf
- - source: salt://apache/httpd.conf
- Will have High Data which looks like this represented in json:
- .. code-block:: json
- {
- "apache": {
- "pkg": [
- {
- "name": "httpd"
- },
- "installed",
- {
- "order": 10000
- }
- ],
- "service": [
- {
- "name": "httpd"
- },
- {
- "watch": [
- {
- "file": "apache_conf"
- },
- {
- "pkg": "apache"
- }
- ]
- },
- "running",
- {
- "order": 10001
- }
- ],
- "__sls__": "blah",
- "__env__": "base"
- },
- "apache_conf": {
- "file": [
- {
- "name": "/etc/httpd/conf.d/httpd.conf"
- },
- {
- "source": "salt://apache/httpd.conf"
- },
- "managed",
- {
- "order": 10002
- }
- ],
- "__sls__": "blah",
- "__env__": "base"
- }
- }
- The subsequent Low Data will look like this:
- .. code-block:: json
- [
- {
- "name": "httpd",
- "state": "pkg",
- "__id__": "apache",
- "fun": "installed",
- "__env__": "base",
- "__sls__": "blah",
- "order": 10000
- },
- {
- "name": "httpd",
- "watch": [
- {
- "file": "apache_conf"
- },
- {
- "pkg": "apache"
- }
- ],
- "state": "service",
- "__id__": "apache",
- "fun": "running",
- "__env__": "base",
- "__sls__": "blah",
- "order": 10001
- },
- {
- "name": "/etc/httpd/conf.d/httpd.conf",
- "source": "salt://apache/httpd.conf",
- "state": "file",
- "__id__": "apache_conf",
- "fun": "managed",
- "__env__": "base",
- "__sls__": "blah",
- "order": 10002
- }
- ]
- This tutorial discusses the Low Data evaluation and the state runtime.
- Ordering Layers
- ===============
- Salt defines 2 order interfaces which are evaluated in the state runtime and
- defines these orders in a number of passes.
- Definition Order
- ----------------
- .. note::
- The Definition Order system can be disabled by turning the option
- ``state_auto_order`` to ``False`` in the master configuration file.
- The top level of ordering is the `Definition Order`. The `Definition Order`
- is the order in which states are defined in salt formulas. This is very
- straightforward on basic states which do not contain ``include`` statements
- or a ``top`` file, as the states are just ordered from the top of the file,
- but the include system starts to bring in some simple rules for how the
- `Definition Order` is defined.
- Looking back at the "Low Data" and "High Data" shown above, the order key has
- been transparently added to the data to enable the `Definition Order`.
- The Include Statement
- ~~~~~~~~~~~~~~~~~~~~~
- Basically, if there is an include statement in a formula, then the formulas
- which are included will be run BEFORE the contents of the formula which
- is including them. Also, the include statement is a list, so they will be
- loaded in the order in which they are included.
- In the following case:
- ``foo.sls``
- .. code-block:: yaml
- include:
- - bar
- - baz
- ``bar.sls``
- .. code-block:: yaml
- include:
- - quo
- ``baz.sls``
- .. code-block:: yaml
- include:
- - qux
- In the above case if ``state.apply foo`` were called then the formulas will be
- loaded in the following order:
- 1. quo
- 2. bar
- 3. qux
- 4. baz
- 5. foo
- The `order` Flag
- ----------------
- The `Definition Order` happens transparently in the background, but the
- ordering can be explicitly overridden using the ``order`` flag in states:
- .. code-block:: yaml
- apache:
- pkg.installed:
- - name: httpd
- - order: 1
- This order flag will over ride the definition order, this makes it very
- simple to create states that are always executed first, last or in specific
- stages, a great example is defining a number of package repositories that
- need to be set up before anything else, or final checks that need to be
- run at the end of a state run by using ``order: last`` or ``order: -1``.
- When the order flag is explicitly set the `Definition Order` system will omit
- setting an order for that state and directly use the order flag defined.
- Lexicographical Fall-back
- -------------------------
- Salt states were written to ALWAYS execute in the same order. Before the
- introduction of `Definition Order` in version 0.17.0 everything was ordered
- lexicographically according to the name of the state, then function then id.
- This is the way Salt has always ensured that states always run in the same
- order regardless of where they are deployed, the addition of the
- `Definition Order` method mealy makes this finite ordering easier to follow.
- The lexicographical ordering is still applied but it only has any effect when
- two order statements collide. This means that if multiple states are assigned
- the same order number that they will fall back to lexicographical ordering
- to ensure that every execution still happens in a finite order.
- .. note::
- If running with ``state_auto_order: False`` the ``order`` key is not
- set automatically, since the Lexicographical order can be derived
- from other keys.
- Requisite Ordering
- ------------------
- Salt states are fully declarative, in that they are written to declare the
- state in which a system should be. This means that components can require that
- other components have been set up successfully. Unlike the other ordering
- systems, the `Requisite` system in Salt is evaluated at runtime.
- The requisite system is also built to ensure that the ordering of execution
- never changes, but is always the same for a given set of states. This is
- accomplished by using a runtime that processes states in a completely
- predictable order instead of using an event loop based system like other
- declarative configuration management systems.
- Runtime Requisite Evaluation
- ----------------------------
- The requisite system is evaluated as the components are found, and the
- requisites are always evaluated in the same order. This explanation will
- be followed by an example, as the raw explanation may be a little dizzying
- at first as it creates a linear dependency evaluation sequence.
- The "Low Data" is an ordered list or dictionaries, the state runtime evaluates
- each dictionary in the order in which they are arranged in the list. When
- evaluating a single dictionary it is checked for requisites, requisites are
- evaluated in order, ``require`` then ``watch`` then ``prereq``.
- .. note::
- If using requisite in statements like require_in and watch_in these will
- be compiled down to require and watch statements before runtime evaluation.
- Each requisite contains an ordered list of requisites, these requisites are
- looked up in the list of dictionaries and then executed. Once all requisites
- have been evaluated and executed then the requiring state can safely be run
- (or not run if requisites have not been met).
- This means that the requisites are always evaluated in the same order, again
- ensuring one of the core design principals of Salt's State system to ensure
- that execution is always finite is intact.
- Simple Runtime Evaluation Example
- ---------------------------------
- Given the above "Low Data" the states will be evaluated in the following order:
- 1. The pkg.installed is executed ensuring that the apache package is
- installed, it contains no requisites and is therefore the first defined
- state to execute.
- 2. The service.running state is evaluated but NOT executed, a watch requisite
- is found, therefore they are read in order, the runtime first checks for
- the file, sees that it has not been executed and calls for the file state
- to be evaluated.
- 3. The file state is evaluated AND executed, since it, like the pkg state does
- not contain any requisites.
- 4. The evaluation of the service state continues, it next checks the pkg
- requisite and sees that it is met, with all requisites met the service
- state is now executed.
- Best Practice
- -------------
- The best practice in Salt is to choose a method and stick with it, official
- states are written using requisites for all associations since requisites
- create clean, traceable dependency trails and make for the most portable
- formulas. To accomplish something similar to how classical imperative
- systems function all requisites can be omitted and the ``failhard`` option
- then set to ``True`` in the master configuration, this will stop all state runs at
- the first instance of a failure.
- In the end, using requisites creates very tight and fine grained states,
- not using requisites makes full sequence runs and while slightly easier
- to write, and gives much less control over the executions.
|