automationansible

How to register files that changed with ansible.posix.synchronize in Ansible


I have the following task that copy certain files from a host to another:

- name: Copy the Quadlet files for rootless containers
  ansible.posix.synchronize:
    src: ./files/quadlet-files/homeserver/
    dest: /home/user/.config/containers/systemd/
    rsync_opts:
      - '--include=*.container'
      - '--exclude=*'
      - '--chmod=D700,F600'
  register: changed_quadlet_files
  notify:
    - Restart container(s)
   

I'd like to have a handler that takes as input the name of the files that have changed without the .container extension

Something like this:

- name: Restart container(s)
  ansible.builtin.systemd:
    name: "{{ item }}"
    state: restarted
    scope: user
  loop:
    -  LIST_FROM_SYNCRONIZE_TASK

Is it possible?


Solution

  • Unfortunately, you can't format the output because of the bug. But, you can parse the output on your own. For example, given the tree for testing

    shell> tree /tmp/ansible/
    /tmp/ansible/
    ├── dest
    └── src
        ├── a
        ├── b
        └── c
    

    Register the output

        - synchronize:
            src: /tmp/ansible/src/
            dest: /tmp/ansible/dest
          register: out
          notify: Restart containers
    

    gives

      out:
        changed: true
        cmd: /usr/bin/rsync --delay-updates -F --compress --archive --out-format='<<CHANGED>>%i %n%L' /tmp/ansible/src/ /tmp/ansible/dest
        failed: false
        msg: |-
          .d..t...... ./
          >f+++++++++ a
          >f+++++++++ b
          >f+++++++++ c
        rc: 0
        stdout_lines:
        - .d..t...... ./
        - '>f+++++++++ a'
        - '>f+++++++++ b'
        - '>f+++++++++ c'
    

    Parse the output

      changed_files: "{{ out.stdout_lines |
                         select('match', '>f') |
                         map('split') |
                         map('last') }}"
    

    and use it in the handler. For example,

        - name: Restart containers
          debug:
            msg: "Restart {{ item }}"
          loop: "{{ changed_files }}"
    

    gives

    ok: [localhost] => (item=a) => 
      msg: Restart a
    ok: [localhost] => (item=b) => 
      msg: Restart b
    ok: [localhost] => (item=c) => 
      msg: Restart c
    

    Example of a complete playbook for testing

    - hosts: localhost
    
      vars:
    
        changed_files: "{{ out.stdout_lines |
                           select('match', '>f') |
                           map('split') |
                           map('last') }}"
    
      tasks:
    
        - synchronize:
            src: /tmp/ansible/src/
            dest: /tmp/ansible/dest
          register: out
          notify: Restart containers
    
      handlers:
        
        - name: Restart containers
          debug:
            msg: "Restart {{ item }}"
          loop: "{{ changed_files }}"