1

Is there a better way to iterate through multiple files on the node machine using Ansible playbook and search n replace a particular line.

I have the following files in my directory and it needs to iterate through these files and check and replace a particular line in the file.

/opt/a1.conf
/opt/a2.con.f
/var/app1/conf/a3.conf
/etc/a5.conf
/etc/a6.conf
/etc/a7.conf
/etc/a8.conf
/etc/a9.conf

My Ansible Playbook can be formatted as follows:


- 
 name: Install nginx and other binaries using with_item and variables.
 gather_facts: yes
 hosts: aws1
 become_method: sudo
 become: yes
 tasks:
- name: Modify line to include Timeout
  become: yes
  become_method: sudo
    lineinfile:
    path: {{ item }}
    regexp: 'http\s+Timeout\s+\='
    line: 'http Timeout = 10'
    backup: yes
   with-items
     - /opt/a1.conf
     - /opt/a2.con.f
     - /var/app1/conf/a3.conf
     - /etc/a5.conf
     - /etc/a6.conf
     - /etc/a7.conf
     - /etc/a8.conf
     - /etc/a9.conf

This will actually work and help me. I could also create a vars.yaml file and add all these files and use them in "with_items" syntax. However this is actually making the playbook look to lengthy as the number of files to search are higher

We possibly can achieve the same thing effectively by using the jinja2 template using the "for" loop. EX: {% for item in vars.yml %}

and that would rather be an effective way to do it and wont make my Ansible playbook clumsy but I'm unable to figure the exact command for looping it.

Is there a jinja command to achieve the same or a better way to iterate through multiple files and not writing each of them into the playbook.

Thank you

anish anil
  • 2,299
  • 7
  • 21
  • 41
  • 2
    _Is there a jinja command to achieve the same or a better way to iterate through multiple files and not writing each of them into the playbook._ are you aware of the [lookup("fileglob")](https://docs.ansible.com/ansible/2.7/plugins/lookup/fileglob.html) plugin? I notice that you appear to have a finite number of directories, so expanding the globs of `*.conf` within them may do what you want – mdaniel Dec 13 '18 at 06:02
  • lookup("fileglob") plugin cannot be used as Matching is against local system files and not remote system files. :-( – anish anil Dec 14 '18 at 09:56
  • 1
    You can simulate a remote fileglob with https://stackoverflow.com/questions/33543551/is-there-with-fileglob-that-works-remotely-in-ansible/33544316 – JGK Dec 14 '18 at 10:50

1 Answers1

2

You don't need jinja2 for that. Why don't you use a separate file for the file list variable like vars.yml with the following contents:

---
files:
  - /opt/a1.conf
  - /opt/a2.con.f
  - /var/app1/conf/a3.conf
  - /etc/a5.conf
  - /etc/a6.conf
  - /etc/a7.conf
  - /etc/a8.conf
  - /etc/a9.conf

and include this file in your playbook:

---
- name: Install nginx and other binaries using with_item and variables.
  gather_facts: yes
  hosts: aws1
  become_method: sudo
  become: yes
  vars_files:
    - z.var

  tasks:
  - name: Modify line to include Timeout
    lineinfile:
      path: {{ item }}
      regexp: 'http\s+Timeout\s+\='
      line: 'http Timeout = 10'
      backup: yes
    loop:
      "{{ files }}"
JGK
  • 3,710
  • 1
  • 21
  • 26
  • Thank you, I had this workaround in place actually. I was more interested in finding the Jinga2 way of achieving it. – anish anil Dec 14 '18 at 09:22
  • 2
    What should then be inside the loop? The `lineinfile` task? This would be pretty ugly. The loop concept of ansible fits perfectly for your usecase. – JGK Dec 14 '18 at 10:56
  • Is there a way to use a file glob (in the template file) instead of hardcoding the filenames into that file? Sort of like the `with_fileglob` but for templates? – lonix Sep 19 '19 at 15:34
  • `with_fileglob` matching is against local system files on the Ansible controller. If you want to iterate a list of files on a remote node, use the `find` module. – JGK Sep 20 '19 at 06:32