2
votes

I have a task in my Ansible playbook that I'm wanting iterate over each host in the group that I have and for each host I would like to assign a name from the hostname list that I've created in the vars folder.

I'm familiar with looping through inventory already by writing loop: "{{ groups['mygroup'] }}" and I have a list of hostnames I would like to assign each IP in 'mygroup' within the host file.

# In tasks file - roles/company/tasks/main.yml
- name: change hostname
  win_hostname:
    name: "{{ item }}"
  loop: "{{ hostname }}"
  register: res

# In the Inventory file
[company]
10.0.10.128
10.0.10.166
10.0.10.200

# In vars - roles/company/vars/main.yml
hostname:
  - GL-WKS-18
  - GL-WKS-19
  - GL-WKS-20

# site.yml file located under /etc/ansible
- hosts: company
  roles:
    - common
    - company #This is where the loop exists mentioned above.

# Command to run playbook
ansible-playbook -i hosts company.yml

I seem to have the individual pieces down or know about it, but how can I combine iterating over hosts from an inventory group and assign names that I have in an already created list (in roles vars folder) already?

UPDATE the task mentioned above has been updated to reflect changes mentioned in answer:

- name: change hostname
  win_hostname:
    name: "{{ item.1 }}"
  loop: {{ groups.company|zip(hostname)|list }}"
  register: res

However the output I'm getting is incorrect, this should not run 9 times rather only three times, once per IP in the [company] group in the inventory. Also there are only three hostnames in a list that need to be assigned to each of the hosts in the inventory sheet.

changed: [10.0.10.128] => (item=[u'10.0.10.128', u'GL-WKS-18'])
changed: [10.0.10.166] => (item=[u'10.0.10.128', u'GL-WKS-18'])
changed: [10.0.10.200] => (item=[u'10.0.10.128', u'GL-WKS-18'])
changed: [10.0.10.128] => (item=[u'10.0.10.166', u'GL-WKS-19'])
changed: [10.0.10.166] => (item=[u'10.0.10.166', u'GL-WKS-19'])
changed: [10.0.10.200] => (item=[u'10.0.10.166', u'GL-WKS-19'])
ok: [10.0.10.128] => (item=[u'10.0.10.200', u'GL-WKS-20'])
ok: [10.0.10.166] => (item=[u'10.0.10.200', u'GL-WKS-20'])
ok: [10.0.10.200] => (item=[u'10.0.10.200', u'GL-WKS-20'])
1

1 Answers

3
votes

Whenever I have a question about looping in Ansible I also go visit the Loops documentation. It sounds like you want to iterate over two lists in parallel, pairing an item from the list of hosts in your inventory with an item from the list of hostnames. In previous versions of Ansible that would suggest using the with_together loop, while with more recent versions of Ansible that suggests the zip filter (there's an example in the docs here).

To demonstrate this for your use case, I started with an inventory file that has three hosts:

[mygroup]
hostA ansible_host=localhost
hostB ansible_host=localhost
hostC ansible_host=localhost

And the following playbook:

---
- hosts: all

- hosts: localhost
  gather_facts: false
  vars:
    hostnames:
      - hostname01
      - hostname02
      - hostname03
  tasks:
    - name: change hostname
      debug:
        msg:
          win_hostname:
            name: "{{ item }}"
      loop: "{{ groups.mygroup|zip(hostnames)|list }}"

Here I'm using a debug task instead of actually running the win_hostname task. The output of running:

ansible-playbook -i hosts playbook.yml

Looks like:

TASK [change hostname] ********************************************************************************************************************************
ok: [localhost] => (item=[u'hostA', u'hostname01']) => {
    "msg": {
        "win_hostname": {
            "name": [
                "hostA", 
                "hostname01"
            ]
        }
    }
}
ok: [localhost] => (item=[u'hostB', u'hostname02']) => {
    "msg": {
        "win_hostname": {
            "name": [
                "hostB", 
                "hostname02"
            ]
        }
    }
}
ok: [localhost] => (item=[u'hostC', u'hostname03']) => {
    "msg": {
        "win_hostname": {
            "name": [
                "hostC", 
                "hostname03"
            ]
        }
    }
}

As you can see, it's paired each host from the inventory with a hostname from the hostnames list.

Update

Based on the additional information you've provided, I think what you actually want is this:

    - name: change hostname
      win_hostname:
        name: "{{ hostnames[group.company.index(inventory_hostname) }}"

This will assign one value from hostname to each host in your inventory. We're looking up the position of the current inventory_hostname in your group, and then using that to index into the hostnames list.