Salt style guide#
While state IDs with spaces are easier to read, they are also easier to mistype: for example, in
require arguments. As such, prefer hyphens to spaces in state IDs.
Our use is limited to:
Activating and running a Python command within a virtual environment
Running a custom script that is specific to our services
Running a system command for which Salt has no relevant function (rare)
Excluding virtual environments,
cmd.run is used less than 10 times in the repository.
cmd.run, you should set an
onchanges requisite or a
creates argument. Otherwise, a
cmd.run function is run each time its state file is applied.
Our use is limited to:
Adding a system cron job, as these are easier to find in
Writing a custom file or creating a custom directory that is specific to our services
Updating a system file for which Salt has no relevant function (uncommon)
Note that unarchiving files (whether local or remote) should use the archive.extracted function.
True and the
source is remote, then the file will never be updated. Use
The Salt documentation states:
By default if a service is triggered to refresh due to a watch statement the service is restarted. If the desired behavior is to reload the service, then set the reload value to True.
Some configuration changes require a reload only, while others require a restart. To support both, we author IDs like:
apache2: service.running: - name: apache2 - enable: True apache2-reload: module.wait: - name: service.reload - m_name: apache2 proxy: apache_module.enabled: - name: proxy - watch_in: - service: apache2 enable conf letsencrypt.conf: apache_conf.enabled: - name: letsencrypt - watch_in: - module: apache2-reload
In this example, enabling the
proxy module causes the
apache2 service to restart, whereas enabling the
letsencrypt configuration causes it to reload.
As the Salt documentation states, with respect to whether to use an include or the top file:
If a Salt state always needs some other state, then using an include is a better choice. If only some systems should receive both Salt states, including both states in the top file gives you the flexibility to choose which systems receive each.
In other words: If running
state.apply my-state fails with an error like:
- Cannot extend ID 'my-id' in 'base:my-state'. It is not part of the high state. This is likely due to a missing include statement or an incorrectly typed ID. Ensure that a state with an ID of 'my-id' is available in environment 'base' and to SLS 'my-state'
then the state file that defines the
my-id ID should be included in the
my-state file. Otherwise, it shouldn’t.
require is easier to reason about than
require_in, because code typically declares its own dependencies.
onchanges makes the state apply only if its required state generates changes, and is used exclusively with the
cmd.runfunction (which otherwise always applies).
require_in in exceptional circumstances: for example, to require a state created by a macro.
As the Salt documentation states:
Jinja macros are useful for one thing and one thing only: creating mini templates that can be reused and rendered on demand.
All macros are defined in lib.sls.
set_firewall() and unset_firewall() make sense as macros, because different state files might want to open or close different ports based on Pillar data. For example, the
apachefile opens or closes ports 80 and 443 based on the
create_user()makes sense as a macro, because users are created in many different contexts, and it is simpler to couple the user’s creation to that context, than to synchronize user creation and service configuration in separate places.
apache()makes sense as a macro, because sites are created in two different contexts: when processing
apache.sitesdata in the
python_appsdata in the
pythonfile. See #80.
Looping over Pillar data#
A few state files loop over Pillar data:
apache, included by the top file if the
apache.siteskey is set in Pillar data
python_apps, included by the state files of specific services
prometheus, included by the state file of the
prometheusservice, and by non-development targets in the top file
This pattern allows service-specific configuration values to live in Pillar, rather than in Salt.