One option is to maintain a map file that is only data, no logic, as
perhaps a straight YAML file. You have to repeat the filter/merge
logic in each but that's typically just ~two lines. E.g.,
# map.yaml
Debian:
pkg: apache2
RedHat:
pkg: httpd
# some.sls
#!py
import yaml
def run():
with open('map.yaml', 'rb') as f:
map = yaml.safe_load(f.read())
apache = __salt__.grains.filter_by(map,
merge=__salt__.pillar.get('apache:lookup'))
return {...}
# someother.sls
{% import_yaml 'map.yaml' as map %}
{% set apache = salt.grains.filter_by(map,
merge=salt.pillar.get('apache:lookup')) %}
The best permanent solution, IMO, is to expose Salt's renderer modules
directly via an execution module wrapper. It wouldn't be much code to
implement. There's a new module named 'slsutil' [1] that would be a
good home for such an addition. I expect the interface would be as
simple as the following.
{% set apache = salt.slsutil.renderer('map.sls') %}
[1]
https://github.com/saltstack/salt/blob/develop/salt/modules/slsutil.py
Where the map file could be written using any combination of Salt's
renderer modules in the normal way. The top she-bang respected as
normal. The only contract for use as a map file would be the final
result would need to produce a data structure.
# map.sls
#!jinja|yaml
{% set apache = salt['grains.filter_by']({
...normal jinja map file here...
}, merge=salt.pillar.get('apache:lookup')) %}
{# Output the resulting Jinja data structure in YAML format, per the
she-bang, to make it universally available. #}
{{ apache | yaml() }}
The following would be functionally equivalent to the above, but using
a different render pipe.
# 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
And regardless of the contents of the map file, it would be available
by simply calling the proposed `slsutil.renderer()` function.
If you're interesting in taking a stab at it, I'd love to see it in
core. The following is a working POC.
import salt.template
import salt.loader
def renderer(path_or_string, default_renderer='jinja|yaml'):
renderers = salt.loader.render(__opts__, __salt__)
return salt.template.compile_template(
path_or_string,
renderers,
default_renderer)
See also:
https://github.com/saltstack/salt/blob/develop/salt/template.py
https://github.com/saltstack/salt/blob/develop/salt/utils/templates.py