Reputation: 3779
Writing saltstack code, I find myself wanting to manipulate the data structures from the pillar in ways that are easy in python and rather cumbersome in jinja. At first it seemed that python-salt integration is easy enough, but I haven't found the details on how to do it.
What I want is to put something in salt/foo/init.sls
akin to this:
{% for key, value in my_function(pillar['one_thing'], pillar['another_thing']) %}
# declare some states parameterised by key and value
{% endfor %}
where my_function()
is simply a python function that expects to receive two dicts (what I pass from pillar) and returns another dict.
Is there a way to do this?
Upvotes: 1
Views: 3522
Reputation: 18753
Adding to the @lakier's answer and information you provided in its comment. State files are simply data structure generators, and salt use renderer pipes to decide how to produce data structures.
The default is jinja
to yaml
, which means jinja
finish its jobs and the result is piped to yaml
which then does its job, its represented as jinja | yaml
. You can use this pipe to compose renderers and connect multiple renderers in a series as per your liking.
Here is a full list of renderers that you can use for reference to compose and create custom renderer, for instance, #!jinja|py
There is also a renderer function in slsutil execution module which can be used to write sls in python
syntax, or any syntax you want, and pull it into jinja
,
Example,
map.sls
#!py
def run():
apache = __salt__.grains.filter_by({
...normal map here but as a python dict...
}, merge=__salt__.pillar.get('apache:lookup'))
return apache
it can be accessed from any other sls file. The following is a usage example in Jinja,
{% set apache = salt.slsutil.renderer('map.sls') %}
You can also render directly from command-line using slsutil,
salt '*' slsutil.renderer /path/to/file
salt '*' slsutil.renderer /path/to/file.jinja 'jinja'
salt '*' slsutil.renderer /path/to/file.sls 'jinja|yaml'
salt '*' slsutil.renderer string='Inline template! {{ saltenv }}'
salt '*' slsutil.renderer string='Hello, {{ name }}.' name='world'
Upvotes: 3
Reputation: 580
By default salt supports different renderers to write state files
One of them is just plain python, all you need to do is to start your file with proper shebang, implement run
method and return the same dict that you would when using default yaml
renderer:
#!py
def run():
return {"state_id": {
"cmd.run": [
{"name": "ls -al"}
]
}}
As an example you can look at this state describing redis orchestration
Upvotes: 3