SaltStack: How one can execute a state only once

saltstack

I have to execute a state only once. I couldn't find a simple way to do this.

Now, the context

I install two MySQL servers through salt. I want to make one a slave of the other.

In order to setup the slave, I need to get the master status informations at the end of the master installation:

SHOW MASTER STATUS;

Now, I can use a custom state executing the mysql.query function to get it.

mysql_master_status:
  mystate.query:
    - query: SHOW MASTER STATUS

But it will be executed every time the highstate is executed for my server. Thus giving different master information every time.

I tried to use a file existence as a flag:

/tmp/only_once:
  file.missing: []
mysql_master_status:
  mystate.query:
    - query: SHOW MASTER STATUS
    - require:
      - file: /tmp/only_once

It's working but I was not happy since I now have two failing states every time.

My custom solution

I ended with a new parameter for mystate, flag that create a flag file the first time it is executed, and returns with success if the file exists:

mysql_master_status:
  mystate.query:
    - query: SHOW MASTER STATUS
    - flag:  /tmp/only_once

And the question again

Still, I'd like to know if, and how, one would execute a state only once.

Best Answer

You can set a grain on the minion that indicates if the MySQL-State has run before. Just add this to your State:

mysql_master_status:
  mystate.query:
    - query: SHOW MASTER STATUS
  grains.present:
    - name: mysql
    - value: master

Then you can wrap things in your State you only want to run once between an if Statement:

{% if salt['grains.get']('mysql') != 'master' %}
...
{% endif %}

The advantage of this method is that you can now also keep track of your Minions who are MySQL-Masters. The downside is that you have to keep an eye on your grains so that the information won't get lost.