running handlers

i’m trying to copy a bunch of ssl ca certs into a directory. this works file with the copy module and if it sees a new one it runs a handler to rehash all the certs in the directory to create *.0 symlinks to each of the certs

however, if an additional cert gets put in there by someone and they don’t rehash the directory, now there’s a cert without a hash

i can count the *.crt’s and the *.0’s using the find module, which puts a ‘matched’ number into the ansible registered variable from the find, but i can’t figure a way to run the handler to rehash the directory if the counts aren’t equal

i found some other examples where people just run handlers based on command: /bin/true with changed_when: true, but i don’t want to run it all the time, only if the counts aren’t equal

any suggestions?

FWIW, instead of handlers, get the lists of the certs and
links, and iterate the difference

    - find:
        paths: /tmp/ansible/certs
        patterns: '*.crt'
      register: out_crt

    - find:
        paths: /tmp/ansible/certs
        patterns: '*.0'
        file_type: link
      register: out_lnk

    - file:
        state: link
        src: /tmp/ansible/certs/{{ item }}.crt
        dest: /tmp/ansible/certs/{{ item }}.0
      loop: "{{ certs | difference(links) }}"
      vars:
        certs: "{{ out_crt.files |
                   json_query('.path') |
                   map('basename') |
                   map('splitext') |
                   map('first') }}"
        links: "{{ out_lnk.files |
                   json_query('.path') |
                   map('basename') |
                   map('splitext') |
                   map('first') }}"

Fit the paths to your needs.

thanks, eventually after a few hours i came to a similar conclusion, i was hoping there was a more elegant way which didn’t need a series of finds

The complexity is a consequence of you requirement to
"rehash the directory if the counts aren't equal". You
can't compare *counts* without at least two *finds*. The
elegant way is a single *find* and iteration of all
certificates

    - find:
        paths: /tmp/ansible/certs
        patterns: '*.crt'
      register: out_crt

    - file:
        state: link
        src: /tmp/ansible/certs/{{ item }}.crt
        dest: /tmp/ansible/certs/{{ item }}.0
      loop: "{{ out_crt.files |
                json_query('.path') |
                map('basename') |
                map('splitext') |
                map('first') }}"

This is, however, less efficient. The options are limited
because *file* doesn't work with wildcards. If you don't
care about idempotency and the changed/failed status
*shell* also does the job

    - shell: |
        cd /tmp/ansible/certs &&
        for i in *.crt; do ln -s $i ${i%.crt}.0; done
      failed_when: false
      changed_when: false

You can write advanced scripts or custom filters that would
do what you want.