larissaphone
larissaphone

Reputation: 193

How to loop through hosts and set variables at the same time with Ansible

I'm trying to simplify my Ansible Playbook for the deployment of a HA-Zookeeper-Cluster (3 instances). Since I need to set the Zookeeper-ID separately for each instance it looks like this now (excerpt):

- hosts: zoo1
  tasks:
    - include: tasks/install-zookeeper.yml ID=1

- hosts: zoo2
  tasks:
    - include: tasks/install-zookeeper.yml ID=2

- hosts: zoo3
  tasks:
    - include: tasks/install-zookeeper.yml ID=3

Now I think it should somehow be possible to do this in a loop. Here's some pseudocode of what I want:

- for i in (1,2,3):
  hosts: "zoo{{ i }}"
  tasks:
    - include tasks/install-zookeeper.yml ID="{{ i }}"

Is something like that possible?

Upvotes: 1

Views: 1137

Answers (2)

Vladimir Botka
Vladimir Botka

Reputation: 67959

The equivalent of

- for i in (1,2,3):
  hosts: "zoo{{ i }}"
  tasks:
    - include tasks/install-zookeeper.yml ID="{{ i }}"

might be implemented with the inventory and the playbook below

shell> cat hosts
[cluster1]
zoo1
zoo2
zoo3
shell> cat playbook.yml
- hosts: cluster1
  tasks:
    - include_tasks: install-zookeeper.yml
      vars:
        ID: "{{ inventory_hostname[3:0] }}"

Next option would be to use the part of the hostname that starts with a number. For example
      vars:
        ID: "{{ inventory_hostname|
                regex_replace('^(\\D*)(.*)$', '\\2') }}"

It's possible to dynamically change the inventory. For example,

shell> cat playbook.yml
- hosts: localhost
  tasks:
    - add_host:
        name: "zoo{{ item +1 }}"
        groups: cluster1
      loop: "{{ range(0, no_of_servers|default(3)|int)|list }}"

- hosts: cluster1
  tasks:
    - debug:
        msg: "{{ inventory_hostname|
                 regex_replace('^(\\D*)(.*)$', '\\2') }}"

gives

shell> ansible-playbook playbook.yml -e "no_of_servers=2"

ok: [zoo1] => 
  msg: '1'
ok: [zoo2] => 
  msg: '2'

Upvotes: 1

Zeitounator
Zeitounator

Reputation: 44595

Place the ID var per host in your inventory. This can be done directly in your inventory file or in a host_vars/YouHostInventoryName.yml file. See the inventory documentation for more info on this.

For this example, we can use a basic static yaml inventory:

---
all:
  hosts:
    zoo1:
      ID: 1
    zoo2:
      ID: 2
    zoo3:
      ID: 3

And now you just have to call you include on each host which will automatically get the correct ID from inventory:

- hosts: all
  tasks:
    - include_tasks: tasks/install-zookeeper.yml

Note: include is still supported but will be deprecated in more or less near future. You should move to the new <include|import>_<task|role|playbook> as stated in the notes of the above linked documentation.

Upvotes: 1

Related Questions