Loop over a list and copy a file if that file exists locally only

Viewed 216

my playbook uses 2 external files:

  • 1 file that holds the username and other variables:
  - name: jimi
    status: present
    sudo: "yes"
  • 1 file inside files/jimi.pub that holds the user's public key
-rw-rw-rw- 1 root root   0 Jul 19 10:45 jimi.pub

My playbook will create the user and copy the key, but if a user doesn't have the key file inside files/username.pub it will error out. My end goal is to copy the key only if the key file exists and if not, continue on to the next user in the list.

I can stat the file locally, but since it will loop over the users list, it will ultimately find a user without a key and error out.

Here is how the key file copy looks like:

  - name: Setting the authorized key for users
    authorized_key:
      user: "{{ item.name }}"
      key: "{{ lookup('file', 'files/'+ item.name + '.pub') }}"
      state: "{{ item.status }}"
    loop: "{{ users }}"  

How can I copy the key only if the key file exists and if not, continue on to the next user in the list without having the playbook error out!?

1 Answers

Local files can be easily tested. See Testing paths. For example, given the users

    users: [alice, bob, jimi]

and the files

shell> ls -1 files/
bob.pub
jimi.pub

The task

    - debug:
        msg: "Setting the authorized key for {{ item }}"
      loop: "{{ users }}"
      vars:
        _file: "files/{{ item }}.pub"
      when: _file is exists

gives

TASK [debug] **************************************************************
skipping: [localhost] => (item=alice) 
ok: [localhost] => (item=bob) => 
  msg: Setting the authorized key for bob
ok: [localhost] => (item=jimi) => 
  msg: Setting the authorized key for jimi

These tests always provide information about a path on the controller e.g. they are independent of the host the task is running at.

Related