2
votes

How do you run a task on each group, not just once for the groups?

I was excepting the Run this on each host tasks would run once for each group_var value. Instead it seems to just be picking one and running it.

I plan on breaking these across multiple servers later but for now it should be able to run on one autoscale, and then easy break it up into multiple autoscale groups later as demand increases.

playbook.yml:

---
# Run with: ansible-playbook -i localhost, playbook.yml
- name: Register Groups
  hosts: localhost
  connection: local
  tasks:
    - name: Add the groups
      add_host:
        name: localhost
        ansible_connection: local
        groups: rest-api, msg-consumer

- name: Run this on each host
  hosts:
    - rest-api
    - msg-consumer
  tasks:
    - name: Say type
      debug: var=item
      with_items: run_type

group_vars/rest-api:

---
run_type: web

group_vars/msg-consumer:

---
run_type: consumer

Output Ansible 1.8.2:

$ ansible-playbook -i localhost, playbook.yml

PLAY [Register Groups] ********************************************************

GATHERING FACTS ***************************************************************
ok: [localhost]

TASK: [Add the groups] ********************************************************
ok: [localhost]

PLAY [Run this on each host] **************************************************

GATHERING FACTS ***************************************************************
ok: [localhost]

TASK: [Say type] **************************************************************
ok: [localhost] => (item=consumer) => {
    "item": "consumer"
}

PLAY RECAP ********************************************************************
localhost                  : ok=4    changed=0    unreachable=0    failed=0

Note: It may be something else. I thought I could also clutter my playbook but breaking up the tasks like like follows:

---
- name: Register Groups
  hosts: localhost
  connection: local
  tasks:
    - name: Add the groups
      add_host:
        name: localhost
        ansible_connection: local
        groups: rest-api, msg-consumer

- name: Run this on each host
  hosts:
    - msg-consumer
  tasks:
    - name: Say type
      debug: var=item
      with_items: run_type

- name: Run this on each host
  hosts:
    - rest-api
  tasks:
    - name: Say type
      debug: var=item
      with_items: run_type

But the output for the 2nd playbook is:

$ ansible-playbook -i localhost, playbook2.yml

PLAY [Register Groups] ********************************************************

GATHERING FACTS ***************************************************************
ok: [localhost]

TASK: [Add the groups] ********************************************************
ok: [localhost]

PLAY [Run this on each host] **************************************************

GATHERING FACTS ***************************************************************
ok: [localhost]

TASK: [Say type] **************************************************************
ok: [localhost] => (item=consumer) => {
    "item": "consumer"
}

PLAY [Run this on each host] **************************************************

GATHERING FACTS ***************************************************************
ok: [localhost]

TASK: [Say type] **************************************************************
ok: [localhost] => (item=consumer) => {
    "item": "consumer"
}

PLAY RECAP ********************************************************************
localhost                  : ok=6    changed=0    unreachable=0    failed=0

Edit: Yet Another attempt to access the data, it looks like group_vars isn't behaving like I expect. The following outputs consumer twice also.

-
# Run with: ansible-playbook -i localhost, playbook.yml
- name: Register Groups
  hosts: localhost
  connection: local
  tasks:
    - name: Add the groups
      add_host:
        name: localhost
        ansible_connection: local
        groups: rest-api, msg-consumer

- name: Run this on each host
  hosts:
    - msg-consumer
    - rest-api
  tasks:
    - name: What's your run type
      debug: var=hostvars[groups[item][0]]['run_type']
      with_items: group_names
3
For now I'm going to place the variables within a dictionary object in group_vars/all and use with_items: group_names and the key the dict on those names. - Kyle James Walker
Update group_names is all group names, not the group names that triggered the group of tasks... - Kyle James Walker

3 Answers

1
votes

The easiest way to do this is to use aliases for the hostnames instead of the real hosts:

---
- name: Register Groups
  hosts: localhost
  connection: local
  tasks:
    - name: Add the rest-api alias for my app
      add_host:
        name: my-app-rest-api
        ansible_ssh_host: 127.0.0.1
        groups: rest-api

    - name: Add the msg-consumer alias for my app
      add_host:
        name: my-app-msg-consumer
        ansible_ssh_host: 127.0.0.1
        groups: msg-consumer


- name: Test Run Types
  hosts:
    - msg-consumer
    - rest-api
  tasks:
    - name: What's your run type
      debug: msg="Run Type of {{ ansible_ssh_host }} is {{ run_type }}"

now you can use your group_vars again:

group_vars/rest-api:

---
run_type: web

group_vars/msg-consumer:

---
run_type: consumer

and the output will be:

PLAY [Register Groups] ******************************************************** 

TASK: [Add the rest-api alias for my app] ************************************* 
ok: [localhost]

TASK: [Add the msg-consumer alias for my app] ********************************* 
ok: [localhost]

PLAY [Test Run Types] ********************************************************* 

TASK: [What's your run type] ************************************************** 
ok: [my-app-msg-consumer] => {
    "msg": "Run Type of 127.0.0.1 is consumer"
}
ok: [my-app-rest-api] => {
    "msg": "Run Type of 127.0.0.1 is web"
}
0
votes

For now this is the best I can come up with:

---
- name: Register Groups
  hosts: localhost
  connection: local
  tasks:
    - name: Add new host group
      add_host:
        name: 127.0.0.1
        ansible_connection: local
        groups: new-server
        run_types:
          - rest-api
          - msg-consumer
    - name: Add another new host group
      add_host:
        name: 127.0.0.2
        ansible_connection: local
        groups: new-server
        run_types:
          - nothing

- name: Test Run Types Server 1
  hosts:
    - new-server
  tasks:
    - name: What's your run type
      debug: var=item
      with_items: run_types

Note: The hosts must be different for this to work, otherwise it will override and use the last variable value used with add_host.

0
votes

See my answer under Ansible run task once per database-name.

Basically, there is no run_once_per_group, and the closest method I'm aware of is a true run_once that loops over groups. To make matters more cluttered, there is no group_vars dictionary variable.

---
- hosts: all
  tasks:
  - name: "do this once per group"
    delegate_to: localhost
    debug:
      msg: "do something on {{hostvars[groups[item.key].0]['somevar']}} for group named {{item}}"
    run_once: yes
    with_dict: groups
    when: item.key not in ['all', 'ungrouped']