playbook to compare and update hostvars in host file

Hello All,

I am trying to update /etc/hosts file if there is any changes in the host extra variables by comparing it from a csv file

[windows]
Server01.test.com ansible_user=“admin” ansible_password=“password”
Server02.test.com ansible_user=“admin” ansible_password=“Welcome”

So suppose the password is changed for the systems .

password.csv
Server01.test.com passwordNew
Server02.test.com WelcomeNew

So, how to compare and change the values in the existing host file.

Please if anyone having any idea or script for this will be a great help for me.

Thanks in advance

Regards
Harsh

You now appear to have two sources of truth. I would try to have one. Removing the data from the inventory seems the easiest.

Use "read_csv" to read the data. For example

  - read_csv:
      path: password.csv
      delimiter: ' '
      fieldnames: [host, passwd]
    register: my_db
  - debug:
      var: my_db.list

There are more options to replace the passwords. Edit the host file
(1,2), create new host file from a template 93), or create new group
dynamically (4).

1) Module "replace", which might the first choice, seems to have an
issue #47917. The parameter "after' doesn't work as expected.
https://github.com/ansible/ansible/issues/47917#issuecomment-686339762

For example, the parameter "after" doesn't match the section
"[windows]" in the task below. If you remove the "after" parameter
the task works fine. If there are more sections (groups) with the
same hosts all passwords will be replaced not only the passwords in
the section [windows]

  - replace:
      path: hosts
      after: '^\[windows\]$'
      regexp: '^{{ item.host }}(.*)ansible_password=(.*)$'
      replace: '{{ item.host }}\1ansible_password="{{ item.passwd
    }}"'
    loop: "{{ my_db.list }}"

2) Module "lineinfile" works as expected, but also here it's not
possible to select a section of the file

  - lineinfile:
    path: hosts
      regexp: '^{{ item.host }}(.*)ansible_password=(.*)$'
      line: '{{ item.host }}\1ansible_password="{{ item.passwd }}"'
    loop: "{{ my_db.list }}"

3) The only save option seems to be "template", but you'll have to
keep all data of the hosts in a data structure. Either a list or a
dictionary.

4) There is one more option. Create new group of hosts in the first
play dynamically and use it in the second play. For example, the
playbook below

  - hosts: localhost
    tasks:
      - read_csv:
          path: password.csv
          delimiter: ' '
          fieldnames: [host, passwd]
        register: my_db
      - add_host:
          groups:
            - my_windows
          hostname: "{{ item.host }}"
          ansible_user: admin
          ansible_password: "{{ item.passwd }}"
        loop: "{{ my_db.list }}"
  - hosts: my_windows
    gather_facts: false
    tasks:
      - debug:
          var: ansible_password

gives (abridged)

  TASK [debug] ****
  ok: [Server01.test.com] => {
      "ansible_password": "passwordNew"
  }
  ok: [Server02.test.com] => {
      "ansible_password": "WelcomeNew"
  }

Hello Visser,

Thanks for your reply. Can you give an example on what you explained like Removing the data from the inventory seems the easiest .How to achieve this.

Thanks in advance.

Regards
Harsh

Hello Vladimir,

I am following your 4th option ie Create new group of hosts in the first play dynamically and use it in the second play .

It is executing successfully , but inside /etc/hosts no entry is found for the host name and password.

Please help me on this.

Thanks,

Regards
Harsh