run_once per group.

Hi,

I have groups of hosts that I copy files to, one those files are copied I call a webservice on the groups master; this webservice will call a deployment script.
The problem I’m having is that the webservice call will be made for every host but it only needs to be called once per group. The ‘run_once’ syntax doesn’t help me since if there are multiple groups it will only run once for everything.

Illustrated

group1:
host1
host2
host3

master1

group2:
host4
host5
host6

master2

  • task runs to populate host*
  • Webservice on groupX is called for each host
  • When limiting with "run_once"only one group’s webservice would be called

Ideally we would have something like ‘run_once_per_group’. The only solution I see at the moment is splitting out the webservice call in a separate playbook which only runs on the ‘masters’.
Any other ideas / approaches are welcome.

Thanks,
Nico

  • hosts: headnode
    tasks:

  • … # run once stuff goes here

  • hosts: webservers
    tasks:

  • … # stuff to do to everything

Alternatively:

when: inventory_hostname == groups[‘webservers’][0]

That works sort of, however it does become repetitive.

Also it doesn’t work very well when using --limit on the command-line, after all there needs to be association between webserver1,2,3 and master1

let me elaborate a bit further:

The backend groups have a variable set for the webservice to call, that webservice runs on one of the frontend boxes.

[backend:children]
backend-group1
backend-group2

[backend-group1]
be[1:3]

[frontend-group1]
fe1

[backend-group2]
be[4:6]

[frontend-group2]
fe2

The play runs on “backend”, copies the files to each member of the backend groups and as the last step calls the ‘webservice’ defined for that group.
However it will do so three times per group (once for each host).
When you use ‘run_once’ it will run it only once, which will work if you run the play for a single group, however when you run the play against all groups at once, it will only call the webservice once, but in the above setup it should have called two different webservices (backend-group2 has frontend-group2 defined and backend-group1 has frontend-group1 defined after all).

Splitting it out in a separate play and running it against ‘frontend’ directly doesn’t work since at that point I don’t know anymore which backend servers where touched (let’s say I’ve used --limit backend-group1 and the second play is defined to run on ‘frontend’. The only way this can work is if I would explicitly use --limit backend-group1,frontend-group1, but that kinda defeats the purpose of what I’m doing here).

The nicest solution I see would be having something like ‘run_once_per_group’.

I thought of a workaround but I can’t seem to get that to work either… :frowning:

This is a snippet:

  • name: test
    gather_facts: false
    hosts: backend
    tasks:

  • debug: msg=‘{{ last_frontend_host_seen|default(“”) }}’

  • set_fact:
    last_frontend_host_seen: “{{ frontend_host }}”

Basically, attemping to loop over all backend hosts and store the ‘frontend’ host (from which, if i can get this to work, I could assemble a list to pass in to the next task).
Sadly the output from this is that ‘last_frontend_host_seen’ always appears to be “” (the default that I set).

  • set_fact:

I’m still kinda stuck here, the only way that I’ve found working is what Michael posted earlier. However that solution doesn’t work when I use it with ‘–limit’.
IMHO run_once_per_group would be an awesome solution, one reasonable alternative would be as per my previous post, a variable that does not get reset between hosts.

If someone has a better solution or alternative, I’m open for ideas… Anything to get this to work!

Thanks :slight_smile: