1
votes

I need some help here in determining the best way to do this and how to setup my playbook to appropriately pull variables for each node.

Lets say I have 3 hosts

/etc/ansible/hosts:

host1
host2
host3

I have a variable file with multiple entries in it

vars/IPs.yaml:

---
IP: ['192.168.77.35', '192.167.77.36', '192.168.77.37']

I am running this playbook:

network_change.yaml:

---
- hosts: all
  vars_files:
    - vars/IPs.yaml
  tasks:
    - name: Check 10G Interface
      stat:
        path: /etc/sysconfig/network-scripts/ifcfg-card-10Gb-1
      register: teng

    - name: Change 10G Interface Settings
      lineinfile:
        path: /etc/sysconfig/network-scripts/ifcfg-card-10Gb-1
        regexp: '{{item.From}}'
        line: '{{item.To}}'
      when: teng.stat.exists
      with_items:
       - { From: 'IPADDR=', To: 'IPADDR={{IP}}'}

I have this working for a single host just fine...but when I have multiple hosts I'm not sure how to loop through the IPs.yaml variables and pull the next value the next time the loop runs. Is there also a way for me to not use a dictionary .yaml variable, can I just use a raw text file that has the IPs on newlines?

Essentially I want to loop through and have the hosts show this in each of the respective hosts /etc/sysconfig/network-scripts/ifcfg-card-10Gb-1.

host1 = 'IPADDR=192.168.77.35'

host2 = 'IPADDR=192.168.77.36'

host3 = 'IPADDR=192.168.77.37'

The end game is to be able to do this over 100+ hosts with simple text files, rather than dictionary yaml files and will be including multiple variables, etc. The systems will all be able to be hit via dhcp/hostnames/IP.

1

1 Answers

1
votes

Create a dictionary with the data, e.g.

    - set_fact:
        _dict: '{{ dict(ansible_play_hosts|zip(IP)) }}'
      run_once: true

should give

  _dict:
    host1: 192.168.77.35
    host2: 192.167.77.36
    host3: 192.168.77.37

Then use this dictionary and select the IP, e.g.

    - name: Change 10G Interface Settings
      lineinfile:
        path: /etc/sysconfig/network-scripts/ifcfg-card-10Gb-1
        regexp: 'IPADDR='
        line: 'IPADDR={{ _dict[inventory_hostname] }}'
      when: teng.stat.exists

You might want to test it first, e.g.

    - name: Change 10G Interface Settings
      debug:
        msg: 'IPADDR={{ _dict[inventory_hostname] }}'

should give

ok: [host2] => 
  msg: IPADDR=192.167.77.36
ok: [host1] => 
  msg: IPADDR=192.168.77.35
ok: [host3] => 
  msg: IPADDR=192.168.77.37

The next option, instead of creating the dictionary, is to calculate the index in the list, e.g. should give the same result

    - name: Change 10G Interface Settings
      debug:
        msg: 'IPADDR={{ IP[_index|int] }}'
      vars:
        _index: '{{ ansible_play_hosts.index(inventory_hostname) }}'

Q: "Use a raw text file that has the IPs on newlines"

A: Create the file, e.g.

shell> cat IP.txt 
192.168.77.35
192.167.77.36
192.168.77.37

Create the list on the fly, e.g.

    - set_fact:
        IP: "{{ lookup('file', 'IP.txt').split('\n') }}"
      run_once: true

should give

  IP:
  - 192.168.77.35
  - 192.167.77.36
  - 192.168.77.37

The more robust solution would be to put the hashes into the file, e.g.

shell> cat IP.txt
host1: 192.168.77.35
host2: 192.167.77.36
host3: 192.168.77.37

Then the task

    - include_vars:
        file: IP.txt
        name: _dict

should create the dictionary

  _dict:
    host1: 192.168.77.35
    host2: 192.167.77.36
    host3: 192.168.77.37

But, the most simple solution would be to store this dictionary in IP.yml and put it into the directory group_vars/all.