I have the following YAML in my SaltStack Pillar:
prometheus:
services:
cassandra:
enabled: False
cockroachdb:
enabled: True
haproxy:
enabled: True
swift:
enabled: False
I want to be able to loop over a list of enabled services.
{% for enabled_service_name in prometheus.services | selectattr('enabled') %}
{{ enabled_service_name }}
{% endfor %}
However, this doesn't work because the attribute I'm trying to filter on is in a nested dictionary below the service name:
{'cassandra': {'enabled': False},
'cockroachdb': {'enabled': True},
'haproxy': {'enabled': True},
'swift': {'enabled': False}}
I can obviously achieve what I want by applying a conditional test inside the loop:
{% for name, properties in prometheus.services | dictsort %}
{% if properties.enabled %}
configuration for {{ name }}
{% endif %}
{% endfor %}
However, I will be looping over this list often and would prefer to have Jinja apply the filter in-line in the for loop.
Is there a way to filter by the value of an item in the nested dictionary?
Well, I think the better structured the yaml file in this case the more options you have to resolve the issue.
I would suggest the below restructure:
prometheus:
services:
- name: cassandra
enabled: False
- name: cockroachdb
enabled: True
- name: haproxy
enabled: True
- name: swift
enabled: False
Then you can iterate in different ways, this might be one way:
{{ prometheus.services | selectattr('enabled', True) | map(attribute='name') | list }}
I hope this helps!
Without changing the structure of your pillar, you can divide your list into two groups via groupby.
{% for group in prometheus.services.items() | groupby ('1.enabled') %}
{% if group.grouper = True %}
{% set enabled_services = group.list %}
{% else %}
{% set disabled_services = group.list %}
{% endif %}
{% endfor %}
It looks a bit more complicated, but it's useful if you need to loop through both lists.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With