Constructing Dependencies from a Pillar in Saltstack I'm trying to create a dummy state in Salt to pull dependencies from a list derived from a pillar.

In my top.sls file, I have:

base:
  '*':
    - components


Then, in components.sls, I have:

{% if 'components' in pillar.items() %}
include:
{% for component in pillar.get('components',[]) %}
  - {{ component }}
{% endfor %}
{% endif %}

{% if 'components' in pillar.items() %}
components:
  require:
{% for component in pillar.get('components',[]) %}
    - {{ component }}
{% endfor %}
{% endif %}


When I check the pillar contents, I see:

$ salt my-minion-id pillar.items

my-minion-id:
    ----------
    components:
        - a-dependency-name


But when I try to see the set of states, I see:

$ salt my-minion-id state.show_sls components

my-minion-id:
    ----------


...and that's it.

My ultimate goal, here, is to treat the minion as hostile, so I'm trying to pull role details out of pillars instead of assigning roles in my file_root's top.sls. It's my understanding that every minion has full access to the contents of the file_root, and I don't want a hostile minion to know the specific firewall or services of any unrelated node.

Edit:

I discovered that my pillar structure didn't support pillar merging, as it used lists, so I switched to a pillar-structure that used no-value dicts:

my-minion-id:
    ----------
    components:
        ----------
        a-dependency-name:
            None
This templated SLS file works splendidly:

{% if 'components' in salt.pillar.items() %}

include:
{% for component in salt.pillar.get('components').keys() %}
  - {{ component }}
{% endfor %}

{% endif %}


However, it requires changing my pillar key structure. From the original question, you see the structure as:

my-minion-id:
    ----------
    components:
        - a-dependency-name


Instead, it needs to be:

my-minion-id:
    ----------
    components:
        ----------
        a-dependency-name:
            None


Note that a-dependency-name is now a dict, and has a single key/value, None. Thus the pillar SLS file needs to change from

components:
  - a-dependency-name


to

components:
  a-dependency-name: ~


While you can get away with not using no-value dictionaries (and thus get rid of the .keys() in the template) and use lists instead, if you do that, you can't merge the components from multiple different pillars; each pillar Salt applies will override the components key from the previous, and the last pillar read will win. If you want to merge pillars (we are talking about role-based assignment, here), this would appear to be the necessary construct.

With that, the output of salt my-minion-id state.show_sls components is then correct:

$ salt my-minion-id state.show_sls components
my-minion-id:
    ----------
    a-dependency-name:
      ----------
      ...


pillar.items() in Jinja templates turns out not to be quite equivalent to salt.pillar.items(); if you try using pillar.ls(), for example, you may see the following error:

Rendering SLS 'base:components' failed: Jinja variable 'salt.pillar object' has no attribute 'ls'


Whether that means one should avoid the implicit salt. prefix shortcut Jinja provides, or instead use a construct like {% if pillar['components'] is defined %} (thanks, @brousch, for the advice), I can't say.