salt.renderers.stateconf.rst 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. ========================
  2. salt.renderers.stateconf
  3. ========================
  4. .. py:module:: salt.renderers.stateconf
  5. :maintainer: Jack Kuan <kjkuan@gmail.com>
  6. :maturity: new
  7. :platform: all
  8. This module provides a custom renderer that processes a salt file with a
  9. specified templating engine (e.g. Jinja) and a chosen data renderer (e.g. YAML),
  10. extracts arguments for any ``stateconf.set`` state, and provides the extracted
  11. arguments (including Salt-specific args, such as ``require``, etc) as template
  12. context. The goal is to make writing reusable/configurable/parameterized
  13. salt files easier and cleaner.
  14. To use this renderer, either set it as the default renderer via the
  15. ``renderer`` option in master/minion's config, or use the shebang line in each
  16. individual sls file, like so: ``#!stateconf``. Note, due to the way this
  17. renderer works, it must be specified as the first renderer in a render
  18. pipeline. That is, you cannot specify ``#!mako|yaml|stateconf``, for example.
  19. Instead, you specify them as renderer arguments: ``#!stateconf mako . yaml``.
  20. Here's a list of features enabled by this renderer.
  21. - Prefixes any state id (declaration or reference) that starts with a dot (``.``)
  22. to avoid duplicated state ids when the salt file is included by other salt
  23. files.
  24. For example, in the `salt://some/file.sls`, a state id such as ``.sls_params``
  25. will be turned into ``some.file::sls_params``. Example:
  26. .. code-block:: yaml
  27. #!stateconf yaml . jinja
  28. .vim:
  29. pkg.installed
  30. Above will be translated into:
  31. .. code-block:: yaml
  32. some.file::vim:
  33. pkg.installed:
  34. - name: vim
  35. Notice how that if a state under a dot-prefixed state id has no ``name``
  36. argument then one will be added automatically by using the state id with
  37. the leading dot stripped off.
  38. The leading dot trick can be used with extending state ids as well,
  39. so you can include relatively and extend relatively. For example, when
  40. extending a state in `salt://some/other_file.sls`, e.g.:
  41. .. code-block:: yaml
  42. #!stateconf yaml . jinja
  43. include:
  44. - .file
  45. extend:
  46. .file::sls_params:
  47. stateconf.set:
  48. - name1: something
  49. Above will be pre-processed into:
  50. .. code-block:: yaml
  51. include:
  52. - some.file
  53. extend:
  54. some.file::sls_params:
  55. stateconf.set:
  56. - name1: something
  57. - Adds a ``sls_dir`` context variable that expands to the directory containing
  58. the rendering salt file. So, you can write ``salt://{{sls_dir}}/...`` to
  59. reference templates files used by your salt file.
  60. - Recognizes the special state function, ``stateconf.set``, that configures a
  61. default list of named arguments usable within the template context of
  62. the salt file. Example:
  63. .. code-block:: yaml
  64. #!stateconf yaml . jinja
  65. .sls_params:
  66. stateconf.set:
  67. - name1: value1
  68. - name2: value2
  69. - name3:
  70. - value1
  71. - value2
  72. - value3
  73. - require_in:
  74. - cmd: output
  75. # --- end of state config ---
  76. .output:
  77. cmd.run:
  78. - name: |
  79. echo 'name1={{sls_params.name1}}
  80. name2={{sls_params.name2}}
  81. name3[1]={{sls_params.name3[1]}}
  82. '
  83. This even works with ``include`` + ``extend`` so that you can override
  84. the default configured arguments by including the salt file and then
  85. ``extend`` the ``stateconf.set`` states that come from the included salt
  86. file. (*IMPORTANT: Both the included and the extending sls files must use the
  87. stateconf renderer for this ``extend`` to work!*)
  88. Notice that the end of configuration marker (``# --- end of state config --``)
  89. is needed to separate the use of 'stateconf.set' form the rest of your salt
  90. file. The regex that matches such marker can be configured via the
  91. ``stateconf_end_marker`` option in your master or minion config file.
  92. Sometimes, it is desirable to set a default argument value that's based on
  93. earlier arguments in the same ``stateconf.set``. For example, it may be
  94. tempting to do something like this:
  95. .. code-block:: yaml
  96. #!stateconf yaml . jinja
  97. .apache:
  98. stateconf.set:
  99. - host: localhost
  100. - port: 1234
  101. - url: 'http://{{host}}:{{port}}/'
  102. # --- end of state config ---
  103. .test:
  104. cmd.run:
  105. - name: echo '{{apache.url}}'
  106. - cwd: /
  107. However, this won't work. It can however be worked around like so:
  108. .. code-block:: yaml
  109. #!stateconf yaml . jinja
  110. .apache:
  111. stateconf.set:
  112. - host: localhost
  113. - port: 1234
  114. {# - url: 'http://{{host}}:{{port}}/' #}
  115. # --- end of state config ---
  116. # {{ apache.setdefault('url', "http://%(host)s:%(port)s/" % apache) }}
  117. .test:
  118. cmd.run:
  119. - name: echo '{{apache.url}}'
  120. - cwd: /
  121. - Adds support for relative include and exclude of .sls files. Example:
  122. .. code-block:: yaml
  123. #!stateconf yaml . jinja
  124. include:
  125. - .apache
  126. - .db.mysql
  127. - ..app.django
  128. exclude:
  129. - sls: .users
  130. If the above is written in a salt file at `salt://some/where.sls` then
  131. it will include `salt://some/apache.sls`, `salt://some/db/mysql.sls` and
  132. `salt://app/django.sls`, and exclude `salt://some/users.ssl`. Actually,
  133. it does that by rewriting the above ``include`` and ``exclude`` into:
  134. .. code-block:: yaml
  135. include:
  136. - some.apache
  137. - some.db.mysql
  138. - app.django
  139. exclude:
  140. - sls: some.users
  141. - Optionally (enabled by default, *disable* via the `-G` renderer option,
  142. e.g. in the shebang line: ``#!stateconf -G``), generates a
  143. ``stateconf.set`` goal state (state id named as ``.goal`` by default,
  144. configurable via the master/minion config option, ``stateconf_goal_state``)
  145. that requires all other states in the salt file. Note, the ``.goal``
  146. state id is subject to dot-prefix rename rule mentioned earlier.
  147. Such goal state is intended to be required by some state in an including
  148. salt file. For example, in your webapp salt file, if you include a
  149. sls file that is supposed to setup Tomcat, you might want to make sure that
  150. all states in the Tomcat sls file will be executed before some state in
  151. the webapp sls file.
  152. - Optionally (enable via the `-o` renderer option, e.g. in the shebang line:
  153. ``#!stateconf -o``), orders the states in a sls file by adding a
  154. ``require`` requisite to each state such that every state requires the
  155. state defined just before it. The order of the states here is the order
  156. they are defined in the sls file. (Note: this feature is only available
  157. if your minions are using Python >= 2.7. For Python2.6, it should also
  158. work if you install the `ordereddict` module from PyPI)
  159. By enabling this feature, you are basically agreeing to author your sls
  160. files in a way that gives up the explicit (or implicit?) ordering imposed
  161. by the use of ``require``, ``watch``, ``require_in`` or ``watch_in``
  162. requisites, and instead, you rely on the order of states you define in
  163. the sls files. This may or may not be a better way for you. However, if
  164. there are many states defined in a sls file, then it tends to be easier
  165. to see the order they will be executed with this feature.
  166. You are still allowed to use all the requisites, with a few restrictions.
  167. You cannot ``require`` or ``watch`` a state defined *after* the current
  168. state. Similarly, in a state, you cannot ``require_in`` or ``watch_in``
  169. a state defined *before* it. Breaking any of the two restrictions above
  170. will result in a state loop. The renderer will check for such incorrect
  171. uses if this feature is enabled.
  172. Additionally, ``names`` declarations cannot be used with this feature
  173. because the way they are compiled into low states make it impossible to
  174. guarantee the order in which they will be executed. This is also checked
  175. by the renderer. As a workaround for not being able to use ``names``,
  176. you can achieve the same effect, by generate your states with the
  177. template engine available within your sls file.
  178. Finally, with the use of this feature, it becomes possible to easily make
  179. an included sls file execute all its states *after* some state (say, with
  180. id ``X``) in the including sls file. All you have to do is to make state,
  181. ``X``, ``require_in`` the first state defined in the included sls file.
  182. When writing sls files with this renderer, one should avoid using what can be
  183. defined in a ``name`` argument of a state as the state's id. That is, avoid
  184. writing states like this:
  185. .. code-block:: yaml
  186. /path/to/some/file:
  187. file.managed:
  188. - source: salt://some/file
  189. cp /path/to/some/file file2:
  190. cmd.run:
  191. - cwd: /
  192. - require:
  193. - file: /path/to/some/file
  194. Instead, define the state id and the ``name`` argument separately for each
  195. state. Also, the ID should be something meaningful and easy to reference within
  196. a requisite (which is a good habit anyway, and such extra indirection would
  197. also makes the sls file easier to modify later). Thus, the above states should
  198. be written like this:
  199. .. code-block:: yaml
  200. add-some-file:
  201. file.managed:
  202. - name: /path/to/some/file
  203. - source: salt://some/file
  204. copy-files:
  205. cmd.run:
  206. - name: cp /path/to/some/file file2
  207. - cwd: /
  208. - require:
  209. - file: add-some-file
  210. Moreover, when referencing a state from a requisite, you should reference the
  211. state's id plus the state name rather than the state name plus its ``name``
  212. argument. (Yes, in the above example, you can actually ``require`` the
  213. ``file: /path/to/some/file``, instead of the ``file: add-some-file``). The
  214. reason is that this renderer will re-write or rename state id's and their
  215. references for state id's prefixed with ``.``. So, if you reference ``name``
  216. then there's no way to reliably rewrite such reference.