index.rst 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. .. _thorium-reactor:
  2. =======================
  3. Thorium Complex Reactor
  4. =======================
  5. .. note::
  6. Thorium is a provisional feature of Salt and is subject to change
  7. and removal if the feature proves to not be a viable solution.
  8. .. note::
  9. Thorium was added to Salt as an experimental feature in the 2016.3.0
  10. release, as of 2016.3.0 this feature is considered experimental, no
  11. guarantees are made for support of any kind yet.
  12. The original Salt Reactor is based on the idea of listening for a specific
  13. event and then reacting to it. This model comes with many logical limitations,
  14. for instance it is very difficult (and hacky) to fire a reaction based on
  15. aggregate data or based on multiple events.
  16. The Thorium reactor is intended to alleviate this problem in a very elegant way.
  17. Instead of using extensive jinja routines or complex python sls files the
  18. aggregation of data and the determination of what should run becomes isolated
  19. to the sls data logic, makes the definitions much cleaner.
  20. Starting the Thorium Engine
  21. ===========================
  22. To enable the thorium engine add the following configuration to the engines
  23. section of your Salt Master or Minion configuration file and restart the daemon:
  24. .. code-block:: yaml
  25. engines:
  26. - thorium: {}
  27. Thorium Modules
  28. ===============
  29. Because of its specialized nature, Thorium uses its own set of modules. However,
  30. many of these modules are designed to wrap the more commonly-used Salt
  31. subsystems. These modules are:
  32. * local: Execution modules
  33. * runner: Runner modules
  34. * wheel: Wheel modules
  35. There are other modules that ship with Thorium as well. Some of these will be
  36. highlighted later in this document.
  37. Writing Thorium Formulas
  38. ========================
  39. Like some other Salt subsystems, Thorium uses its own directory structure. The
  40. default location for this structure is ``/srv/thorium/``, but it can be changed
  41. using the ``thorium_roots`` setting in the ``master`` configuration file.
  42. This would explicitly set the roots to the default:
  43. .. code-block:: yaml
  44. thorium_roots:
  45. base:
  46. - /srv/thorium
  47. Example ``thorium_roots`` configuration:
  48. .. code-block:: yaml
  49. thorium_roots:
  50. base:
  51. - /etc/salt/thorium
  52. It is also possible to use gitfs with Thorium,
  53. using the ``thoriumenv`` or ``thorium_top`` settings.
  54. Example using ``thorium_top``:
  55. .. code-block:: yaml
  56. thorium_top: salt://thorium/top.sls
  57. gitfs_provider: pygit2
  58. gitfs_remotes:
  59. - git@github.com:user/repo.git:
  60. - name: salt-backend
  61. - root: salt
  62. - base: master
  63. - git@github.com:user/repo.git:
  64. - name: thorium-backend
  65. - root: thorium
  66. - base: master
  67. - mountpoint: salt://thorium
  68. .. note::
  69. When using this method don't forget to prepend the mountpoint to files served by this repo,
  70. for example ``top.sls``:
  71. .. code-block:: yaml
  72. base:
  73. '*':
  74. - thorium.key_clean
  75. Example using ``thoriumenv``:
  76. .. code-block:: yaml
  77. thoriumenv: thorium
  78. gitfs_provider: pygit2
  79. gitfs_remotes:
  80. - git@github.com:user/repo.git:
  81. - name: salt-backend
  82. - root: salt
  83. - base: master
  84. - git@github.com:user/repo.git:
  85. - name: thorium-backend
  86. - root: thorium
  87. - saltenv:
  88. - thorium:
  89. - ref: master
  90. .. note::
  91. When using this method all state will run under the defined environment,
  92. for example ``top.sls``:
  93. .. code-block:: yaml
  94. thorium:
  95. '*':
  96. - key_clean
  97. The Thorium top.sls File
  98. ------------------------
  99. Thorium uses its own ``top.sls`` file, which follows the same convention as is
  100. found in ``/srv/salt/``:
  101. .. code-block:: yaml
  102. <srv>:
  103. <target>:
  104. - <formula 1>
  105. - <formula 2>
  106. - <etc...>
  107. For instance, a ``top.sls`` using a standard ``base`` environment and a single
  108. Thorium formula called ``key_clean``, would look like:
  109. .. code-block:: yaml
  110. base:
  111. '*':
  112. - key_clean
  113. Take note that the target in a Thorium ``top.sls`` is not used; it only exists
  114. to follow the same convention as other ``top.sls`` files. Leave this set to
  115. ``'*'`` in your own Thorium ``top.sls``.
  116. Thorium Formula Files
  117. ---------------------
  118. Thorium SLS files are processed by the same state compiler that processes Salt
  119. state files. This means that features like requisites, templates, and so on are
  120. available.
  121. Let's take a look at an example, and then discuss each component of it. This
  122. formula uses Thorium to detect when a minion has disappeared and then deletes
  123. the key from the master when the minion has been gone for 60 seconds:
  124. .. code-block:: yaml
  125. statreg:
  126. status.reg
  127. keydel:
  128. key.timeout:
  129. - delete: 60
  130. - require:
  131. - status: statreg
  132. There are two stanzas in this formula, whose IDs are ``statreg`` and
  133. ``keydel``. The first stanza, ``statreg``, tells Thorium to keep track of
  134. minion status beacons in its *register*. We'll talk more about the register in
  135. a moment.
  136. The second stanza, ``keydel``, is the one that does the real work. It uses the
  137. ``key`` module to apply an expiration (using the ``timeout`` function) to a
  138. minion. Because ``delete`` is set to ``60``, this is a 60 second expiration. If
  139. a minion does not check in at least once every 60 seconds, its key will be
  140. deleted from the master. This particular function also allows you to use
  141. ``reject`` instead of ``delete``, allowing for a minion to be rejected instead
  142. of deleted if it does not check in within the specified time period.
  143. There is also a ``require`` requisite in this stanza. It states that the
  144. ``key.timeout`` function will not be called unless the ``status.reg`` function
  145. in the ``statreg`` codeblock has been successfully called first.
  146. Thorium Links to Beacons
  147. ------------------------
  148. The above example was added in the 2016.11.0 release of Salt and makes use of the
  149. ``status`` beacon also added in the 2016.11.0 release. For the above Thorium state
  150. to function properly you will also need to enable the ``status`` beacon in the
  151. ``minion`` configuration file:
  152. .. code-block:: yaml
  153. beacons:
  154. status:
  155. - interval: 10
  156. This will cause the minion to use the status beacon to check in with the master
  157. every 10 seconds.
  158. The Thorium Register
  159. ====================
  160. In order to keep track of information, Thorium uses an in-memory register (or
  161. rather, collection of registers) on the master. These registers are only
  162. populated when told to by a formula, and they normally will be erased when the
  163. master is restarted. It is possible to persist the registers to disk, but we'll
  164. get to that in a moment.
  165. The example above uses ``status.reg`` to populate a register for you, which is
  166. automatically used by the ``key.timeout`` function. However, you can set your
  167. own register values as well, using the ``reg`` module.
  168. Because Thorium watches the event bus, the ``reg`` module is designed to look
  169. for user-specified tags, and then extract data from the payload of events that
  170. match those tags. For instance, the following stanza will look for an event
  171. with a tag of ``my/custom/event``:
  172. .. code-block:: yaml
  173. foo:
  174. reg.list:
  175. - add: bar
  176. - match: my/custom/event
  177. When such an event is found, the data found in the payload dictionary key of
  178. ``bar`` will be stored in a register called ``foo``. This register will store
  179. that data in a ``list``. You may also use ``reg.set`` to add data to a ``set()``
  180. instead.
  181. If you would like to see a copy of the register as it is stored in memory, you
  182. can use the ``file.save`` function:
  183. .. code-block:: yaml
  184. myreg:
  185. file.save
  186. In this case, each time the register is updated, a copy will be saved in JSON
  187. format at ``/var/cache/salt/master/thorium/saves/myreg``. If you would like to
  188. see when particular events are added to a list-type register, you may add a
  189. ``stamp`` option to ``reg.list`` (but not ``reg.set``). With the above two
  190. stanzas put together, this would look like:
  191. .. code-block:: yaml
  192. foo:
  193. reg.list:
  194. - add: bar
  195. - match: my/custom/event
  196. - stamp: True
  197. myreg:
  198. file.save
  199. If you would like to only keep a certain number of the most recent register
  200. entries, you may also add a ``prune`` option to ``reg.list`` (but not
  201. ``reg.set``):
  202. .. code-block:: yaml
  203. foo:
  204. reg.list:
  205. - add: bar
  206. - match: my/custom/event
  207. - stamp: True
  208. - prune: 50
  209. This example will only keep the 50 most recent entries in the ``foo`` register.
  210. Using Register Data
  211. -------------------
  212. Putting data in a register is useless if you don't do anything with it. The
  213. ``check`` module is designed to examine register data and determine whether it
  214. matches the given parameters. For instance, the ``check.contains`` function
  215. will return ``True`` if the given ``value`` is contained in the specified
  216. register:
  217. .. code-block:: yaml
  218. foo:
  219. reg.list:
  220. - add: bar
  221. - match: my/custom/event
  222. - stamp: True
  223. - prune: 50
  224. check.contains:
  225. - value: somedata
  226. Used with a ``require`` requisite, we can call one of the wrapper modules and
  227. perform an operation. For example:
  228. .. code-block:: yaml
  229. shell_test:
  230. local.cmd:
  231. - tgt: dufresne
  232. - func: cmd.run
  233. - arg:
  234. - echo 'thorium success' > /tmp/thorium.txt
  235. - require:
  236. - check: foo
  237. This stanza will only run if the ``check.contains`` function under the ``foo``
  238. ID returns true (meaning the match was found).
  239. There are a number of other functions in the ``check`` module which use
  240. different means of comparing values:
  241. * ``gt``: Check whether the register entry is greater than the given value
  242. * ``gte``: Check whether the register entry is greater than or equal to the given value
  243. * ``lt``: Check whether the register entry is less than the given value
  244. * ``lte``: Check whether the register entry is less than or equal to the given value
  245. * ``eq``: Check whether the register entry is equal to the given value
  246. * ``ne``: Check whether the register entry is not equal to the given value
  247. There is also a function called ``check.event`` which does not examine the
  248. register. Instead, it looks directly at an event as it is coming in on the
  249. event bus, and returns ``True`` if that event's tag matches. For example:
  250. .. code-block:: yaml
  251. salt/foo/*/bar:
  252. check.event
  253. run_remote_ex:
  254. local.cmd:
  255. - tgt: '*'
  256. - func: test.version
  257. - require:
  258. - check: salt/foo/*/bar
  259. This formula will look for an event whose tag is ``salt/foo/<anything>/bar`` and
  260. if it comes in, issue a ``test.version`` to all minions.
  261. Register Persistence
  262. --------------------
  263. It is possible to persist the register data to disk when a master is stopped
  264. gracefully, and reload it from disk when the master starts up again. This
  265. functionality is provided by the returner subsystem, and is enabled whenever
  266. any returner containing a ``load_reg`` and a ``save_reg`` function is used.