Saltstack Official OpenSSH Formula
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

448 lines
16KB

  1. .. _map.jinja:
  2. ``map.jinja``: gather formula configuration values
  3. ==================================================
  4. The `documentation`_ explains the use of a ``map.jinja`` to gather parameters values for a formula.
  5. As `pillars`_ are rendered on the Salt master for every minion, this increases the load on the master as the pillar values and the number of minions grows.
  6. As a good practice, you should:
  7. - store non-secret data in YAML files distributed by the `fileserver`_
  8. - store secret data in:
  9. - `pillars`_ (and look for the use of something like `pillar.vault`_)
  10. - `SDB`_ (and look for the use of something like `sdb.vault`_)
  11. Current best practice is to let ``map.jinja`` handle parameters from all sources, to minimise the use of pillars, grains or configuration from ``sls`` files and templates directly.
  12. .. contents:: **Table of Contents**
  13. For formula users
  14. -----------------
  15. Quick start: configure per role and per DNS domain name values
  16. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  17. We will see a quick setup to configure the ``TEMPLATE`` formula for different DNS domain name and several roles.
  18. For this example, I'll define 2 kinds of `fileserver`_ sources:
  19. 1. formulas git repositories with hard-coded version reference to avoid breaking my setup randomly at upstream update. they are the last sources where files are looked up
  20. 2. parameters of the formulas in the file backend `roots`_
  21. Configure the fileserver backends
  22. `````````````````````````````````
  23. I configure the `fileserver`_ backends to serve:
  24. 1. files from `roots`_ first
  25. 2. `gitfs`_ repositories last
  26. Create the file ``/etc/salt/master.d/fileserver.conf`` and restart the ``master``:
  27. .. code-block:: yaml
  28. ---
  29. ##
  30. ## file server
  31. ##
  32. fileserver_backend:
  33. # parameters values and override
  34. - roots
  35. # formulas
  36. - gitfs
  37. # The files in this directory will take precedence over git repositories
  38. file_roots:
  39. base:
  40. - /srv/salt
  41. # List of formulas I'm using
  42. gitfs_remotes:
  43. - https://github.com/saltstack-formulas/template-formula.git:
  44. - base: v4.1.1
  45. - https://github.com/saltstack-formulas/openssh-formula.git:
  46. - base: v2.0.1
  47. ...
  48. Create per DNS configuration for ``TEMPLATE`` formula
  49. `````````````````````````````````````````````````````
  50. Now, we can provides the per DNS domain name configuration files for the ``TEMPLATE`` formulas under ``/srv/salt/TEMPLATE/parameters/``.
  51. We create the directory for ``dns:domain`` grain and we add a symlink for the ``domain`` grain which is extracted from the minion ``id``:
  52. .. code-block:: console
  53. mkdir -p /srv/salt/TEMPLATE/parameters/dns:domain/
  54. ln -s dns:domain /srv/salt/TEMPLATE/parameters/domain
  55. We create a configuration for the DNS domain ``example.net`` in ``/srv/salt/TEMPLATE/parameters/dns:domain/example.net.yaml``:
  56. .. code-block:: yaml
  57. ---
  58. values:
  59. config: /etc/template-formula-example-net.conf
  60. ...
  61. We create another configuration for the DNS domain ``example.com`` in ``/srv/salt/TEMPLATE/parameters/dns:domain/example.com.yaml``:
  62. .. code-block:: yaml
  63. ---
  64. values:
  65. config: /etc/template-formula-{{ grains['os_family'] }}.conf
  66. ...
  67. Create per role configuration for ``TEMPLATE`` formula
  68. ``````````````````````````````````````````````````````
  69. Now, we can provides the per role configuration files for the ``TEMPLATE`` formulas under ``/srv/salt/TEMPLATE/parameters/``.
  70. We create the directory for roles:
  71. .. code-block:: console
  72. mkdir -p /srv/salt/TEMPLATE/parameters/roles
  73. We will define 2 roles:
  74. - ``TEMPLATE/server``
  75. - ``TEMPLATE/client``
  76. We create a configuration for the role ``TEMPLATE/server`` in ``/srv/salt/TEMPLATE/parameters/roles/TEMPLATE/server.yaml``:
  77. .. code-block:: yaml
  78. ---
  79. values:
  80. config: /etc/template-formula-server.conf
  81. ...
  82. We create another configuration for the role ``TEMPLATE/client`` in ``/srv/salt/TEMPLATE/parameters/roles/TEMPLATE/client.yaml``:
  83. .. code-block:: yaml
  84. ---
  85. values:
  86. config: /etc/template-formula-client.conf
  87. ...
  88. Enable roles and the ``dns:domain`` and ``domain`` grains for ``map.jinja``
  89. ```````````````````````````````````````````````````````````````````````````
  90. We need to redefine the sources for ``map.jinja`` to load values from our new configuration files, we provide a global configuration for all our minions.
  91. We create the global parameters file ``/srv/salt/parameters/map_jinja.yaml``:
  92. .. code-block:: yaml
  93. ---
  94. values:
  95. sources:
  96. # default values
  97. - "Y:G@osarch"
  98. - "Y:G@os_family"
  99. - "Y:G@os"
  100. - "Y:G@osfinger"
  101. - "C@{{ tplroot ~ ':lookup' }}"
  102. - "C@{{ tplroot }}"
  103. # Roles activate/deactivate things
  104. # then thing are configured depending on environment
  105. # So roles comes before `dns:domain`, `domain` and `id`
  106. - "Y:C@roles"
  107. # DNS domain configured (DHCP or resolv.conf)
  108. - "Y:G@dns:domain"
  109. # Based on minion ID
  110. - "Y:G@domain"
  111. # default values
  112. - "Y:G@id"
  113. ...
  114. The syntax is explained later at `Sources of configuration values`_.
  115. Bind roles to minions
  116. `````````````````````
  117. We associate roles `grains`_ to minion using `grains.append`_.
  118. For the servers:
  119. .. code-block:: console
  120. salt 'server-*' grains.append roles TEMPLATE/server
  121. For the clients:
  122. .. code-block:: console
  123. salt 'client-*' grains.append roles TEMPLATE/client
  124. .. note::
  125. Since we used ``Y:C@roles``, ``map.jinja`` will do a ``salt['config.get']('roles')`` to retrieve the roles so you could use any other method to bind roles to minions (`pillars`_ or `SDB`_) but `grains`_ seems to be the prefered method.
  126. Format of configuration YAML files
  127. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  128. When you write a new YAML file, note that it must conform to the following layout:
  129. - a mandatory ``values`` key to store the configuration values
  130. - two optional keys to configure the use of `salt.slsutil.merge`_
  131. - an optional ``strategy`` key to configure the merging strategy, for example ``strategy: 'recurse'``, the default is ``smart``
  132. - an optional ``merge_lists`` key to configure if lists should be merged or overridden for the ``recurse`` and ``overwrite`` strategy, for example ``merge_lists: 'true'``
  133. Here is a valid example:
  134. .. code-block:: yaml
  135. ---
  136. strategy: 'recurse'
  137. merge_lists: 'false'
  138. values:
  139. pkg:
  140. name: 'some-package'
  141. config: '/path/to/a/configuration/file'
  142. ...
  143. You can use `Jinja`_ as with any SLS files:
  144. .. code-block:: yaml
  145. ---
  146. strategy: 'overwrite'
  147. merge_lists: 'true'
  148. values:
  149. output_dir: /tmp/{{ grains['id'] }}
  150. ...
  151. Sources of configuration values
  152. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  153. Configuring ``map.jinja`` sources
  154. `````````````````````````````````
  155. The ``map.jinja`` file uses several sources where to lookup parameter values. The list of sources can be modified by two files:
  156. 1. a global ``salt://parameters/map_jinja.yaml``
  157. 2. a per formula ``salt://{{ tplroot }}/parameters/map_jinja.yaml``, it overrides the global configuration
  158. Each source definition has the form ``<TYPE>:<OPTION>@<KEY>`` where ``<TYPE>`` can be one of:
  159. - ``Y`` to load values from YAML files from the `fileserver`_, this is the default when no type is defined
  160. - ``C`` to lookup values with `salt['config.get']`_
  161. - ``G`` to lookup values with `salt['grains.get']`_
  162. - ``I`` to lookup values with `salt['pillar.get']`_
  163. The YAML type option can define the query method to lookup the key value to build the file name:
  164. - ``C`` to query with `salt['config.get']`_, this is the default when no query method is defined
  165. - ``G`` to query with `salt['grains.get']`_
  166. - ``I`` to query with `salt['pillar.get']`_
  167. The ``C``, ``G`` or ``I`` types can define the ``SUB`` option to store values in the sub key ``mapdata.<KEY>`` instead of directly in ``mapdata``.
  168. Finally, the ``<KEY>`` describes what to lookup to either build the YAML filename or gather values using one of the query methods.
  169. .. note::
  170. For the YAML type, if the ``<KEY>`` can't be looked up, then it's used a literal string path to a YAML file, for example: ``any/path/can/be/used/here.yaml`` will result in the loading of ``salt://{{ tplroot }}/parameters/any/path/can/be/used/here.yaml`` if it exists.
  171. The built-in ``map_jinja:sources`` is:
  172. .. code-block:: yaml
  173. - "Y:G@osarch"
  174. - "Y:G@os_family"
  175. - "Y:G@os"
  176. - "Y:G@osfinger"
  177. - "C@{{ tplroot ~ ':lookup' }}"
  178. - "C@{{ tplroot }}"
  179. - "Y:G@id"
  180. This is strictly equivalent to the following ``map_jinja.yaml`` using `Jinja`_:
  181. .. code-block:: sls
  182. values:
  183. sources:
  184. - "parameters/osarch/{{ salt['grains.get']('osarch') }}.yaml"
  185. - "parameters/os_family/{{ salt['grains.get']('os_family') }}.yaml"
  186. - "parameters/os/{{ salt['grains.get']('os') }}.yaml"
  187. - "parameters/osfinger/{{ salt['grains.get']('osfinger') }}.yaml"
  188. - "C@{{ tplroot ~ ':lookup' }}"
  189. - "C@{{ tplroot }}"
  190. - "parameters/id/{{ salt['grains.get']('id') }}.yaml"
  191. Loading values from the configuration sources
  192. `````````````````````````````````````````````
  193. For each configuration source defined in ``map_jinja:sources``, ``map.jinja`` will:
  194. #. load values depending on the source type:
  195. - for YAML file sources
  196. - if the ``<KEY>`` can be looked up, load values from the YAML file named ``salt://{{ tplroot }}/paramaters/<KEY>/{{ salt['<QUERY_METHOD>']('<KEY>') }}.yaml`` if it exists
  197. - otherwise, load the YAML file named ``salt://{{ tplroot }}/parameters/<KEY>.yaml`` if it exists
  198. - for ``C``, ``G`` or ``I`` source type, lookup the value of ``salt['<QUERY_METHOD>']('<KEY>')``
  199. #. merge the loaded values with the previous ones using `salt.slsutil.merge`_
  200. There will be no error if a YAML file does not exists, they are all optional.
  201. Configuration values from ``salt['config.get']``
  202. ````````````````````````````````````````````````
  203. For sources with of type ``C`` declared in ``map_jinja:sources``, you can configure the ``merge`` option of `salt['config.get']`_ by defining per formula ``strategy`` configuration key (retrieved with ``salt['config.get'](tplroot ~ ':strategy')`` with one of the following values:
  204. - ``recurse`` merge recursively dictionaries. Non dictionary values replace already defined values
  205. - ``overwrite`` new value completely replace old ones
  206. By default, no merging is done, the first value found is returned.
  207. Global view of the order of preferences
  208. ```````````````````````````````````````
  209. To summarize, here is a complete example of the load order of formula configuration values for an ``AMD64`` ``Ubuntu 18.04`` minion named ``minion1.example.net`` for the ``libvirt`` formula:
  210. #. ``parameters/defaults.yaml``
  211. #. ``parameters/osarch/amd64.yaml``
  212. #. ``parameters/os_family/Debian.yaml``
  213. #. ``parameters/os/Ubuntu.yaml``
  214. #. ``parameters/osfinger/Ubuntu-18.04.yaml``
  215. #. ``salt['config.get']('libvirt:lookup')``
  216. #. ``salt['config.get']('libvirt')``
  217. #. ``parameters/id/minion1.example.net``
  218. Remember that the order is important, for example, the value of ``key1:subkey1`` loaded from ``parameters/os_family/Debian.yaml`` is overridden by a value loaded from ``parameters/id/minion1.example.net``.
  219. For formula authors and contributors
  220. ------------------------------------
  221. Dependencies
  222. ^^^^^^^^^^^^
  223. ``map.jinja`` requires:
  224. - salt minion 2018.3.3 minimum to use the `traverse`_ jinja filter
  225. - to be located at the root of the formula named directory (e.g. ``libvirt-formula/libvirt/map.jinja``)
  226. - the ``libsaltcli.jinja`` library, stored in the same directory, to disable the ``merge`` option of `salt['config.get']`_ over `salt-ssh`_
  227. Use formula configuration values in ``sls``
  228. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  229. The ``map.jinja`` exports a unique ``mapdata`` variable which could be renamed during import.
  230. Here is the best way to use it in an ``sls`` file:
  231. .. code-block:: sls
  232. {#- Get the `tplroot` from `tpldir` #}
  233. {%- set tplroot = tpldir.split("/")[0] %}
  234. {%- from tplroot ~ "/map.jinja" import mapdata as TEMPLATE with context %}
  235. test-does-nothing-but-display-TEMPLATE-as-json:
  236. test.nop:
  237. - name: {{ TEMPLATE | json }}
  238. Use formula configuration values in templates
  239. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  240. When you need to process salt templates, you should avoid calling `salt['config.get']`_ (or `salt['pillar.get']`_ and `salt['grains.get']`_) directly from the template. All the needed values should be available within the ``mapdata`` variable exported by ``map.jinja``.
  241. Here is an example based on `template-formula/TEMPLATE/config/file.sls`_:
  242. .. code-block:: sls
  243. # -*- coding: utf-8 -*-
  244. # vim: ft=sls
  245. {#- Get the `tplroot` from `tpldir` #}
  246. {%- set tplroot = tpldir.split('/')[0] %}
  247. {%- set sls_package_install = tplroot ~ '.package.install' %}
  248. {%- from tplroot ~ "/map.jinja" import mapdata as TEMPLATE with context %}
  249. {%- from tplroot ~ "/libtofs.jinja" import files_switch with context %}
  250. include:
  251. - {{ sls_package_install }}
  252. TEMPLATE-config-file-file-managed:
  253. file.managed:
  254. - name: {{ TEMPLATE.config }}
  255. - source: {{ files_switch(['example.tmpl'],
  256. lookup='TEMPLATE-config-file-file-managed'
  257. )
  258. }}
  259. - mode: 644
  260. - user: root
  261. - group: {{ TEMPLATE.rootgroup }}
  262. - makedirs: True
  263. - template: jinja
  264. - require:
  265. - sls: {{ sls_package_install }}
  266. - context:
  267. TEMPLATE: {{ TEMPLATE | json }}
  268. This ``sls`` file expose a ``TEMPLATE`` context variable to the jinja template which could be used like this:
  269. .. code-block:: jinja
  270. ########################################################################
  271. # File managed by Salt at <{{ source }}>.
  272. # Your changes will be overwritten.
  273. ########################################################################
  274. This is another example file from SaltStack template-formula.
  275. # This is here for testing purposes
  276. {{ TEMPLATE | json }}
  277. winner of the merge: {{ TEMPLATE['winner'] }}
  278. .. _documentation: https://docs.saltstack.com/en/latest/topics/development/conventions/formulas.html#writing-formulas
  279. .. _fileserver: https://docs.saltstack.com/en/latest/ref/file_server
  280. .. _salt['config.get']: https://docs.saltstack.com/en/latest/ref/modules/all/salt.modules.config.html#salt.modules.config.get
  281. .. _salt['grains.get']: https://docs.saltstack.com/en/latest/ref/modules/all/salt.modules.grains.html#salt.modules.grains.get
  282. .. _salt['pillar.get']: https://docs.saltstack.com/en/latest/ref/modules/all/salt.modules.pillar.html#salt.modules.pillar.get
  283. .. _pillar.vault: https://docs.saltstack.com/en/latest/ref/pillar/all/salt.pillar.vault.html
  284. .. _pillars: https://docs.saltstack.com/en/latest/topics/pillar/
  285. .. _grains: https://docs.saltstack.com/en/latest/topics/grains/
  286. .. _grains.append: https://docs.saltstack.com/en/latest/ref/modules/all/salt.modules.grains.html#salt.modules.grains.append
  287. .. _SDB: https://docs.saltstack.com/en/latest/topics/sdb/index.html
  288. .. _sdb.vault: https://docs.saltstack.com/en/latest/ref/sdb/all/salt.sdb.vault.html
  289. .. _Jinja: https://docs.saltstack.com/en/latest/topics/jinja
  290. .. _roots: https://docs.saltstack.com/en/latest/ref/file_server/all/salt.fileserver.roots.html
  291. .. _gitfs: https://docs.saltstack.com/en/latest/topics/tutorials/gitfs.html
  292. .. _salt.slsutil.merge: https://docs.saltstack.com/en/latest/ref/modules/all/salt.modules.slsutil.html
  293. .. _traverse: https://docs.saltstack.com/en/latest/topics/jinja/index.html#traverse
  294. .. _salt-ssh: https://docs.saltstack.com/en/latest/topics/ssh/
  295. .. _template-formula/TEMPLATE/config/file.sls: https://github.com/saltstack-formulas/template-formula/blob/master/TEMPLATE/config/file.sls