10

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.

Christophe Drevet
  • 1,962
  • 2
  • 17
  • 25

2 Answers2

17

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.

gpkvt
  • 191
  • 1
  • 6
3

I think the easiest way would be to put this state into another state file (mysql_master_status.sls) and not referencing it in the top.sls. Instead you execute this state once using salt 'target' state.sls mysql_master_status

Thomas

  • Yes, but I wanted to do this without manual interaction. My ultimate goal would be to create both master and slave MySQL server with salt, and start the replication automatically, using data given by the "once executed" state on the master. Thanks for your answer, though. – Christophe Drevet Dec 18 '13 at 10:20