Search code examples
nginxsalt-stack

Reload nginx config from salt state, only if the configtest passes


I've recently written a salt state which handles the nginx config for a number of servers from some static variables in pillar. I wanted to roll this out to all the servers, but before I did this I wanted to make sure before the config is applied on a server it has first been tested.

Nginx has an inbuilt configtest which I use frequently on command line, and I found that salt has an nginx module which can be used to run configtest.

I have the following in my state file:

reload-nginx:
  service.running:
    - enabled: True
    - reload: True
    - watch:
      - pkg: nginx
      - file: /etc/nginx/sites-available/*
      - file: /etc/nginx/nginx.conf

This should reload nginx if the config files change, or if the nginx install is upgraded/changed. I believe I can run a config test using the following in my state file (untested):

nginx-config-test:
  module.run:
    - name: nginx.configtest

And I believe if I add this state to the watch in the reload-nginx state it would reload if the configtest passed.

However, I want the reload to happen only if either of the config files have changed AND the config test passes, or if nginx changes AND the configtest passes. I see I can use onlyif to run a state if ALL of the things are True, and from experience you can' have multiple uses of the same method (so I can't have 3 different onlyif's - correct me if I am wrong).

But I don't see any way to reload nginx only if the config files have changed (or nginx has been updated) and the configtest has passed.

Is this possible?


Solution

  • Have the reload state watch the config-test state; have the config-test state watch the config files state and the pkg state. The test will only run if something changes, and the reload will only occur if the test runs and passes.

    Caveat: Structurally this will work, but I've never used nginx.configtest, so I can't promise it behaves the way you think.

    You will also need to use module.wait rather than module.run; watch statements don't work with .run. Reference here.

    So that becomes:

    reload-nginx:
      service.running:
        - name: nginx
        - enable: True
        - reload: True
        - watch:
          - module: nginx-config-test
    
    nginx-config-test:
      module.wait:
        - name: nginx.configtest
        - watch:
          - file: /etc/nginx/sites-available/*