advice on targeting in top.sls

956 views
Skip to first unread message

William Cannon

unread,
Feb 1, 2014, 10:32:38 PM2/1/14
to salt-...@googlegroups.com
I could use a little advice from the salt community on the topic of environment and grains targeting in the top.sls file.

Currently I am setting a grain on minions called "environment".  And, I have another grain of "roles", which is a list. 

The general idea is that a server has 1+ roles (e.g. webserver, database...) and belongs to one environment (e.g. "dev").

My working top.sls file looks something like this:

base:
  '*':
    - nothing  

dev:
  'G@environment:dev and G@roles:webserver':
    - match: compound
    - webserver

Is there a more elegant way to achieve this?  If so, can someone give a quick example?

Thanks in advance,
William

Ethan Erchinger

unread,
Feb 2, 2014, 11:28:57 AM2/2/14
to salt-...@googlegroups.com
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

William Cannon

unread,
Feb 2, 2014, 1:11:49 PM2/2/14
to salt-...@googlegroups.com
Thank you Ethan!  The examples you provided are great.  

Bowen

unread,
Feb 2, 2014, 6:45:13 PM2/2/14
to salt-...@googlegroups.com
Hi William,

My understanding (which may be incorrect) is that top.sls can actually be used to set the env grain. The cleanest way IMHO of doing what you're after would be to give each environment a unique domain and to then match on that. This takes care of the first part of your question. For the second part, including SLS base on a "role" grain, you're best to add some jinja:

dev:
    {% if 'webserver' in salt['grains.get']('role',[]) %}
    - webserver
    {% endif %}
    {% if 'database' in salt['grains.get']('role',[]) %}
    - database
    {% endif %}

Using the salt['grains.get'] function also allows you to set a default (in this case an empty array) so that things don't break if the role grain isn't set. Is this what you were hoping to achieve, or have I missed the point?

-
Bowen

Note: I haven't tested the above config. If you run in to problems with it let me know and I'll get something working on my test server.

Bowen

unread,
Feb 2, 2014, 6:57:32 PM2/2/14
to salt-...@googlegroups.com

First off, you could iterate over roles and simply apply them, as such:
{% for role in grains.get('roles') %}
'{{ role }}':
    - match: grain
    - {{ role }}
{% endfor %}

I agree that this is a very elegant solution, however, sooner or later you're going to want to add a new SLS to just one of your environments (dev?) and then this solution will no longer work (because the for loop generates the same config for each environment).

There may be duplication in explicitly defining each environment, but I think it makes your config more readable and gives you more flexibility. Of course the great thing about Salt is that there are many ways to perform the same task and so this boils down to a matter of preference and what you believe works best given your requirements.

-
Bowen

Bowen

unread,
Feb 2, 2014, 7:09:00 PM2/2/14
to salt-...@googlegroups.com
sooner or later you're going to want to add a new SLS to just one of your environments (dev?) and then this solution will no longer work (because the for loop generates the same config for each environment).

I see that I've been working my keyboard faster than my brain. Ethan does provide a solution for this and so I retract my previous statement.

-
Bowen 
Reply all
Reply to author
Forward
0 new messages