Search code examples
salt-project

How can I manually trigger cmd.wait scripts in Salt?


Say I have a cmd.wait script that watches a managed git repository for changes. What’s the best way to trigger that script even if the repo hasn’t changed?

Here's the scenario:

my-repo:
  git.latest:
    - name: git@github.com:my/repo.git
    - rev: master
    - target: /opt/myrepo
    - user: me
    - require:
        - pkg: git


syncdb:
  cmd.run:
    - name /opt/bin/syncdb.sh


load-resources:
  cmd.wait:
    - name: /opt/bin/load_script.py /opt/myrepo/resources.xml
    - require:
      - cmd: syncdb
    - watch:
      - git: my-repo


index-resources:
  cmd.wait:
    - name: /opt/bin/indexer.sh
    - watch:
        - cmd: load-resources

Say that I run this state, but syncdb fails. load-resources and index-resources fail as well because of missing prerequisites. But my-repo succeeded, and now has the latest checkout of the repository.

So I go ahead and fix the problem that was causing syncdb to fail, and it succeeds. But now my cmd.watch scripts won't run, because my-repo isn't reporting any changes.

I need to trigger, just once, load-resources, and going forward I want it to only trigger when the repo changes. Now, I could just change it to use cmd.run, but in actuality I have a bunch of these cmd.wait scripts in a similar state, and I really don't want to have to go through and switch them all and then switch them back. The same goes for introducing artificial changes into the git repo. There are multiple repos involved and that's annoying in many ways. Finally, I can foresee something like this happening again, and I want a sure solution for handling this case that doesn't involve a bunch of error-prone manual interventions.

So, is there a way to trigger those cmd.watch scripts manually? Or is there a clever way to rearrange the dependencies so that a manual triggering is possible?


Solution

  • Assuming the above sls lives in: /srv/salt/app.sls then you should be able to execute load-resources by doing this:

    $: salt '*appserver*' state.sls_id load-resources app base
    

    That said, there are surely many better ways to do this, so that you don't have to manually handle failures.

    You could change your load-resources to use cmd.run with unless command that actually checks whether the resources have been loaded or not. If that's not possible to do in business terms (i.e. no easy way to check), then something generic could do, this can be as simple as a file you create at the end of load_script.py. The file can contain the commit id of the git repo at the time of the import, and if the file doesn't exist or the commit id in the file is different than that of the current git repo, you know you have to re-import.

    A better variation would be to even bake the unless logic into load_script.py, which would make that script idempotent. Just like all salt modules. Your SLS file would be even simpler then.