SaltStack: dynamic sls (updated for 0.15.3)

Tags: , ,
Add comments

I’ve been learning and diving into SaltStack for about a month now, for both work and personal interest, that thing simply rocks. In the meantime, I’ve contributed a couple of modules, like bridging and Xen support, plus a couple of grains improvements for NetBSD.

But most of all, I’ve been preparing my ${DAYJOB} infrastructure for Salt, and I must say this has been much easier than I thought, thanks to this beautifully designed piece of code.
One aspect I’d like to share is the simple way I found to make a minion dynamically configured, through custom-made grains.

Like many companies, we have an Information System, which has a bunch of informations about everything on our network, and among those, the roles of the virtual machines which are started. Those informations are made available to a minion through an HTTP server, which will recognize the minion’s REMOTE_ADDR and tell him what are its «roles».

The webserver is our always-favorite nginx, which interfaces a WSGI server, uWSGI.

nginx‘s configuration is simple:

location / {
        include uwsgi_params;
        uwsgi_pass unix:///var/run/uwsgi/app/is/socket;

uwsgi application’s .ini is pretty trivial too:

workers = 2
log-date = true
plugins = python
chdir = /var/www/is
module = is

A very simple python script using resides in /var/www/is and gives the minion which will query him a YAML structured output containing, among other data, the minion‘s roles.

I wrote a basic grain module which retrieves those informations and make them available as grains for the minions:

$ cat _grains/ 

import requests
import yaml

def more_infos():
        Returns the minion's roles and stuff.
        r = requests.get('http://private.fqdn/')

        return yaml.load(r.text)

After deploying that grain module via salt '*' saltutil.sync_grains, the minions are now aware of what they’re meant to do, thus making a generic top.sls easy to write.

Thanks to Jinja2, a sls file can be made more dynamic, and we can write a very complex scenario within a couple of lines:

$ cat top.sls 

  {% set states = salt['cp.list_states'](env) %}

    - common
    {% if 'roles' in grains %}
    {% for role in grains['roles'] %}
    {% if role in states %}
    - {{ role }}
    {% endif %}  # state exists
    {% endfor %} # for roles
    {% endif %}  # role exists

  'virtual_subtype:Xen PV DomU':
    - match: grain
    - domus

  {% if grains['host'] in states %}
  {{ grains['host'] }}:
    - {{ grains['host'] }}
  {% endif %}

There we go, for every role a minion has, we can add a sls to match that role globally, as we can also add a very specific, host-related sls. Beautiful and handy, that’s what Salt is.

Update for Salt 0.15.3

Since Salt 0.15.3, a sls file can’t reference an non-existent state anymore, thus the additional checks in order to get sure the target state actually exists.

2 Responses to “SaltStack: dynamic sls (updated for 0.15.3)”

  1. Seb Says:

    Interesting stuff. Thanks :-)

  2. Adam S. Says:

    That looks very interesting. However I still do not completely understand how top.sls is going to look like once rendered.

    Could you provide an example of rendered top.sls for 2 minions, please ? That would help me immensly. Thanks!

Leave a Reply

WP Theme & Icons based on GlossyBlue by N.Design Studio
Banner from
Entries RSS Comments RSS Log in
Performance Optimization WordPress Plugins by W3 EDGE