Loop over the items of a list defined as a host variable for each host in a specific group

In a task, I am trying to figure out how I can loop over the items of a
list that is defined as a host variable for each host in a specific
group. This must be very common, but I can't think of a solution. I
suppose what I need is some kind of nested loops. An outer loop to loop
over the hosts in the group and an inner loop to loop over the items in
the list variable for each host in the outer loop. Is there a syntax for
this?

in hosts file:
    [somegroup]
    host1.example.org
    host2.example.org

in host1.example.org host_vars files:
    mylist:
        - item1
        - item2
        - item3

in host2.example.org host_vars files:
    mylist:
        - item4
        - item5

I’m not sure what you are trying to do here so I can’t offer too much advice. It also depends on what you are planning on doing with those variables I suspect.

You might want to look at this http://docs.ansible.com/playbooks_variables.html#magic-variables-and-how-to-access-information-about-other-hosts

Normally I only need to iterate over a list of variables for the current host. But there are examples of accessing variables for groups of hosts on that page.

Adam

Given the example I wrote in my previous post, what I want is simply to have the task run for each item in “mylist” for each host in “somegroup”. Thus, have the task run for 5 times: for item1, item2, item3, item4 and item5. I already know about these ‘magic’ vars. The difficulty is not on how to get the data, but on how to construct the loop so that I get the iteration I want.

“In a task, I am trying to figure out how I can loop over the items of a
list that is defined as a host variable for each host in a specific
group.”

If the variable is “listvar”

with_items: listvar

What you suggest is the simplest form of a loop. It does not handle the “for each host in a specific group” part. What I want is that the task must run for all the items in each list for each host in a specific group. Particularly, I would need a mechanism, so that the outer loop loops over hosts and the inner loop uses the host in the current step in the outer loop to get the needed host variable. In general, this is a common case of a nested loop with the inner loop using the value of the current step in the outer loop. Unfortunately, it seems that Ansible does not support this. The current implementation of “with_nested” loop expects its terms to be static lists all evaluated before the execution of the loop. It does not support the second list to be created dynamically for each step in the outer loop. So, I am considering to teach “with_nested” lookup to understand expressions with “item[0]” in the second term as expressions that should be reevaluated to a list for each item in the first term. For example, the loop I need could be simply written like this: with_nested: - groups[“somegroup”] - hostvars[item[0]].listvar Would you accept a patch for that?

"It does not handle the “for each host in a specific group” part. "

with_items: groups.monitoring

" So, I am considering to teach “with_nested” lookup to understand expressions with “item[0]” in the second term as expressions that should be reevaluated to a list for each item in the first term"

Ansible is not meant to be a programming language, when syntax gets so complicated that it appears to become one, I feel a playbook is strongly going in the wrong direction.

It is usually useful to step back and think about the underlying use case, and there’s a clean way to model it without trying to “program in YAML”

I find this problem mostly comes from users coming from Chef, but not always.

So, as such, I feel this is a bit of a slippery slope. Rather than initially discussing the patch, let’s understand what’s the real world thing you are trying to configure, at a high level, and we can likely offer up some suggestions.

My use case: I want a task to run for all network interfaces for each host in a specific group. Each host has a “network_interfaces” list variable. I cannot be convinced that this is something that one should not be able to describe in a playbook. Nevertheless, I have just patched the “with_nested” lookup to support item[0] in the nested loop list. I am doing some tests and I will soon send a pull request for it.

That is not really a use case but a description. What are you trying to do with these network interfaces? Add them to a list? Build a dhcp configuration file?

Adam

This feels like something that can be done with a group or inventory variable for me, and the basic host looping that is already in Ansible, coupled with a “with_items”.

“My use case: I want a task to run for all network interfaces for each host in a specific group. Each host has a “network_interfaces” list variable”

  • hosts: all_my_servers
    tasks:
  • example_module: some_arguments {{ item }}
    with_items: network_interfaces

If you need to delegate this command to different hosts than the one you are currently looping over (unlikely – but possible) let me know – but perhaps I’m missing something.

"I want is simply to have the task run for each item in "mylist" for each host in "somegroup"."

Ansible loops through your groups and hosts and executes tasks against them. Therefore there is no need to manage an outer loop, Ansible does it for you and is central to how Ansible works.

"Thus, have the task run for 5 times: for item1, item2, item3, item4 and item5."

This inner loop is as simple as with_items as already suggested.

Does that help or did I confuse you more?

Actually I think that he is trying to configure something for a group of hosts rather than configure something on a group of hosts. For example lets assume that you have a DHCP server and you want to configure static ip addresses for each of your servers. You could run through each host grabbing all of the MAC addresses and IP addresses from each server but you would only be configuring them on one server.

I am not saying that that is the case and I am curious as to what the case is, but that is an example of what I think we are being asked for here.

“Actually I think that he is trying to configure something for a group of hosts rather than configure something on a group of hosts.”

Still:

  • hosts: whichever

  • local_action: shell echo one host name name is {{ item }}
    with_items: groups.monitoring

Case: From a specific host, run a command (e.g. ping) for all interfaces for each host in a specific group. I have just sent a pull request () which would allow that. The commit message includes an example which should make it clear to everyone.

Replied, didn’t find the description very clear – if you can update the formatting of this ticket to where the YAML is readable that would be helpful.