Khaled
Khaled

Reputation: 838

Ansible playbook with loop double iterates the task on hosts

The playbook copies local files to servers, and then changes the permissions of one of the files:

- hosts: servers
  tasks:
    - include_vars: certs-list.yml

    - name: Transfer files
      copy:
        src: "{{ item.src_folder }}"
        dest: "{{ item.dest_folder }}"
      delegate_to: "{{ item.dest_server }}"
      loop: "{{ certs }}"
      register: certificate_copied

    - name: Ensure privkey.pem right permissions
      file:
        path: "{{ item.dest_folder }}privkey.pem"
        mode: '600'
      with_items: "{{ certs }}"

Here I do specify a list, which file goes to which server:

#certs-list.yml
certs:
  - name: minio box1-1
    src_folder: certificates/com/xxx/box/1/
    dest_server: host-101.xxx.com
    dest_folder: /tmp/box1/
  - name: minio box1-2
    src_folder: certificates/com/xxx/box/2/
    dest_server: host-202.xxx.com
    dest_folder: /tmp/box2/

Here is my hosts inventory

[servers]
host-101.xxx.com
host-202.xxx.com

Here is the output:

PLAY [servers] *****************************************************************

TASK [Gathering Facts] *********************************************************
ok: [host-101.mydomain.com]
ok: [host-202.mydomain.com]

TASK [include_vars] ************************************************************
ok: [host-101.mydomain.com]
ok: [host-202.mydomain.com]

TASK [Transfer files] **********************************************************
changed: [host-101.mydomain.com -> host-101.mydomain.com] => (item={'name': 'minio box1-1', 'src_folder': 'certificates/com/mydomain/box/1/', 'dest_server': 'host-101.mydomain.com', 'dest_folder': '/tmp/box1/'})
changed: [host-202.mydomain.com -> host-101.mydomain.com] => (item={'name': 'minio box1-1', 'src_folder': 'certificates/com/mydomain/box/1/', 'dest_server': 'host-101.mydomain.com', 'dest_folder': '/tmp/box1/'})
changed: [host-101.mydomain.com -> host-202.mydomain.com] => (item={'name': 'minio box1-2', 'src_folder': 'certificates/com/mydomain/box/2/', 'dest_server': 'host-202.mydomain.com', 'dest_folder': '/tmp/box2/'})
ok: [host-202.mydomain.com -> host-202.mydomain.com] => (item={'name': 'minio box1-2', 'src_folder': 'certificates/com/mydomain/box/2/', 'dest_server': 'host-202.mydomain.com', 'dest_folder': '/tmp/box2/'})

TASK [Ensure privkey.pem right permissions] ************************************
changed: [host-101.mydomain.com] => (item={'name': 'minio box1-1', 'src_folder': 'certificates/com/mydomain/box/1/', 'dest_server': 'host-101.mydomain.com', 'dest_folder': '/tmp/box1/'})
failed: [host-202.mydomain.com] (item={'name': 'minio box1-1', 'src_folder': 'certificates/com/mydomain/box/1/', 'dest_server': 'host-101.mydomain.com', 'dest_folder': '/tmp/box1/'}) => {"ansible_loop_var": "item", "changed": false, "item": {"dest_folder": "/tmp/box1/", "dest_server": "host-101.mydomain.com", "name": "minio box1-1", "src_folder": "certificates/com/mydomain/box/1/"}, "msg": "file (/tmp/box1/privkey.pem) is absent, cannot continue", "path": "/tmp/box1/privkey.pem", "state": "absent"}
failed: [host-101.mydomain.com] (item={'name': 'minio box1-2', 'src_folder': 'certificates/com/mydomain/box/2/', 'dest_server': 'host-202.mydomain.com', 'dest_folder': '/tmp/box2/'}) => {"ansible_loop_var": "item", "changed": false, "item": {"dest_folder": "/tmp/box2/", "dest_server": "host-202.mydomain.com", "name": "minio box1-2", "src_folder": "certificates/com/mydomain/box/2/"}, "msg": "file (/tmp/box2/privkey.pem) is absent, cannot continue", "path": "/tmp/box2/privkey.pem", "state": "absent"}
changed: [host-202.mydomain.com] => (item={'name': 'minio box1-2', 'src_folder': 'certificates/com/mydomain/box/2/', 'dest_server': 'host-202.mydomain.com', 'dest_folder': '/tmp/box2/'})

PLAY RECAP *********************************************************************
host-101.mydomain.com : ok=3    changed=1    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
host-202.mydomain.com : ok=3    changed=1    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

The playbook iterates the task on each host 2 times!

The copy process goes well and the right files are copied to the right server, even when it is iterated wrongly.

But through the permissions task, the playbook tries to find all copied files on all hosts.

I would be very thankful for the help.

Upvotes: 1

Views: 678

Answers (1)

Vladimir Botka
Vladimir Botka

Reputation: 67959

Iterate selected items only, e.g. given the inventory

shell> cat hosts
host-101.xxx.com ansible_host=10.1.0.61
host-202.xxx.com ansible_host=10.1.0.62

and the tree

shell> tree box/
box/
├── 1
│   └── privkey.pem
└── 2
    └── privkey.pem

The play

- hosts: host-101.xxx.com,host-202.xxx.com
  vars:
    certs:
      - name: minio box1-1
        src_folder: box/1/
        dest_server: host-101.xxx.com
        dest_folder: /tmp/box1/
      - name: minio box1-2
        src_folder: box/2/
        dest_server: host-202.xxx.com
        dest_folder: /tmp/box2/
  tasks:
    - name: Transfer files
      copy:
        src: "{{ item.src_folder }}"
        dest: "{{ item.dest_folder }}"
      loop: "{{ certs|selectattr('dest_server', 'eq', inventory_hostname) }}"

    - name: Ensure privkey.pem right permissions
      file:
        path: "{{ item.dest_folder }}privkey.pem"
        mode: '0600'
      loop: "{{ certs|selectattr('dest_server', 'eq', inventory_hostname) }}"

will copy the files to the remote nodes and change the mode

shell> ssh [email protected] ls -la /tmp/box1/
total 26
drwxr-xr-x   2 admin  wheel   3 Aug 15 14:53 .
drwxrwxrwt  11 root   wheel  12 Aug 15 14:53 ..
-rw-------   1 admin  admin   0 Aug 15 14:53 privkey.pem

shell> ssh [email protected] ls -la /tmp/box2/
total 26
drwxr-xr-x   2 admin  wheel   3 Aug 15 14:53 .
drwxrwxrwt  11 root   wheel  12 Aug 15 14:53 ..
-rw-------   1 admin  admin   0 Aug 15 14:53 privkey.pem

Upvotes: 1

Related Questions