Webair
Webair

Reputation: 105

looping using with_fileglob

How do i loop using "with_fileglob". I am trying to copy files matching wildcard, but with different permissions at the destination.

- hosts: myhost
  gather_facts: no
  tasks:
  - name: Ansible copy test
    copy:
      src: "{{ item.origin }}"
      dest: /home/user1/tmps/
      owner: user1
      mode: "{{item.mode}}"
    with_fileglob:
      - { origin: '/tmp/hello*', mode: '640'}
      - { origin: '/tmp/hi*', mode: '600'}

It throws error as below:

An exception occurred during task execution. To see the full traceback, use 
-vvv. The error was: AttributeError: 'dict' object has no attribute 'rfind'

Upvotes: 4

Views: 9716

Answers (2)

techraf
techraf

Reputation: 68549

I think the cleanest way is to implement this, would be a nested loop with include_tasks.

Where you main playbook file contains:

...

vars:
  my_patterns:
    - origin: "/tmp/hello*"
      mode: "0640"
    - origin: "/tmp/hi*"
      mode: "0600"

tasks:
  - include_tasks: "my_glob.yml"
    with_items: "{{ my_patterns }}"
    loop_control:
      loop_var: my_pattern

...

and a subordinate my_glob.yml-tasks file:

---
- name: Ansible copy test
  copy:
    src: "{{ item }}"
    dest: /home/user1/tmps/
    owner: user1
    mode: "{{ my_pattern.mode }}"
  with_fileglob: "{{ my_pattern.origin }}"

Alternative method

Using Jinja2 to populate a list of objects { 'path': '...', 'mode': '...' }' based on fileglob-lookup plugin results.

vars:
  my_patterns:
    - origin: '/tmp/hello*'
      mode: '0640'
    - origin: '/tmp/hi*'
      mode: '0600'
tasks:
  - copy:
      src: "{{ item.paht }}"
      dest: /home/user1/tmps/
      owner: user1
      mode: "{{ item.mode }}"
    with_items: "[{% for match in my_patterns %}{% for file in lookup('fileglob', match.origin, wantlist=True) %}{ 'path':'{{ file }}','mode':'{{ match.mode }}'}{% if not loop.last %},{% endif %}{% endfor %}{% if not loop.last %},{% endif %}{% endfor %}]"

The above works if patterns are matched, you'd need to add checks if the results are not empty.

Upvotes: 5

ilias-sp
ilias-sp

Reputation: 6685

according to the documentation, you cant pass to the fileglob a dictionary variable, adding the desired file permissions after copy as you have attempted (i mean the declaration { origin: '/tmp/hello*', mode: '640'}).

simple module call that will work for you:

- hosts: localhost
  gather_facts: no
  tasks:
  - name: Ansible copy test
    copy:
      src: "{{ item }}"
      dest: /SAMBA_ROOT/TEMP/
      owner: root
    with_fileglob:
      - '/tmp/hello*'
      - '/tmp/hi*'

if you want to have each of the file group have different file permissions, i suggest you use 2 different calls where the mode is "hardcoded", for example:

- hosts: localhost
  gather_facts: no
  tasks:
  - name: copy hello files
    copy:
      src: "{{ item }}"
      dest: /SAMBA_ROOT/TEMP/
      owner: root
      mode: 0640
    with_fileglob:
      - '/tmp/hello*'

  - name: copy hi files
    copy:
      src: "{{ item }}"
      dest: /SAMBA_ROOT/TEMP/
      owner: root
      mode: 0600
    with_fileglob:
      - '/tmp/hi*'

Upvotes: 0

Related Questions