Hey William,
If you do actually have states that match your roles by name, you could definitely simplify things, from a manually targeting in top.sls perspective.
First off, you could iterate over roles and simply apply them, as such:
{% for role in grains.get('roles') %}
'{{ role }}':
- match: grain
- {{ role }}
{% endfor %}
If the environment portion isn't handled in the state file itself, you could target them as well:
{% for role in grains.get('roles') %}
'{{ role }}':
- match: grain
- {{ role }}.{{ grains.get('environment') }}
{% endfor %}
This second one is pretty elegant, in that all you would need to do is create a
webserver.dev state, which could contain something like:
include:
- webserver
extend:
<id dec>:
- source: salt://dev/webserver/file.conf
This would use the same state for both prod, dev, qa but would override the interesting pieces with simple changes. Of course, that could also be handled via Pillar, matching based on role as well and setting the source file path, then just referencing that in the state file. Either way, it gives you the flexibility to make those changes while not duplicating your work.
All of that said, targeting non-existing states in the top file will throw errors on the client, just in-case there is a typo or similar. You could protect yourself using something similar to this:
Hope that helps.
Ethan