# Iterating with\_items: $groups\['dbclients'\]

**URL:** <https://forum.ansible.com/t/iterating-with-items-groups-dbclients/12509>\
**Category:** Ansible Project\
**Created:** [March 15, 2013, 4:17pm UTC](https://forum.ansible.com/t/iterating-with-items-groups-dbclients/12509 "2013-03-15T16:17:10Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![crucialfelix](https://avatars.discourse-cdn.com/v4/letter/c/f475e1/32.png) [@crucialfelix](https://forum.ansible.com/u/crucialfelix)\
**Post date:** [March 15, 2013, 4:17pm UTC](https://forum.ansible.com/t/iterating-with-items-groups-dbclients/12509/1 "2013-03-15T16:17:10Z")

</div>

Hi all,

Thanks so much for ansible ! I’m nearly deployed.

This should be splendidly simple but for some reason nothing I have tried is working:

- name: open psql ports to trusted servers  
with\_items: $groups[‘dbclients’]  
action: command ufw allow from ${item[‘ip’]} to any port $psql\_port  
tags: postgresx

where

[dbclients:children]  
webservers

[webservers]  
basicbox ansible\_ssh\_host=1.2.3.4 ip=1.2.3.4

I’m sure this is a common pattern that people want to do.

failed: [db] =\> (item={‘newservers’: , ‘all’: [‘db’, ‘nsweb’, ‘nsbeta’, ‘nsmailings’, ‘nsmain’, ‘basicbox’], ‘tasks’: , ‘webservers’: [‘basicbox’], ‘mailer’: , ‘ungrouped’: , ‘rabbitclients’: [‘basicbox’], ‘dbclients’: [‘basicbox’], ‘dbservers’: [‘db’], ‘nestseekers’: [‘db’, ‘nsweb’, ‘nsbeta’, ‘nsmailings’, ‘nsmain’, ‘basicbox’], ‘oldboxes’: [‘nsbeta’, ‘nsmain’, ‘nsmailings’, ‘nsweb’]}[‘dbclients’]) =\> {“changed”: true, “cmd”: [“ufw”, “allow”, “from”, “{newservers:”, “,”, “all:”, “[db,”, “nsweb,”, “nsbeta,”, “nsmailings,”, “nsmain,”, “basicbox],”, “tasks:”, “,”, “webservers:”, “[basicbox],”, “mailer:”, “,”, “ungrouped:”, “,”, “rabbitclients:”, “[basicbox],”, “dbclients:”, “[basicbox],”, “dbservers:”, “[db],”, “nestseekers:”, “[db,”, “nsweb,”, “nsbeta,”, “nsmailings,”, “nsmain,”, “basicbox],”, “oldboxes:”, “[nsbeta,”, “nsmain,”, “nsmailings,”, “nsweb]}[dbclients][ip]”, “to”, “any”, “port”, “$psql\_port”], “delta”: “0:00:00.077861”, “end”: “2013-03-15 11:40:11.326913”, “item”: “{‘newservers’: , ‘all’: [‘db’, ‘nsweb’, ‘nsbeta’, ‘nsmailings’, ‘nsmain’, ‘basicbox’], ‘tasks’: , ‘webservers’: [‘basicbox’], ‘mailer’: , ‘ungrouped’: , ‘rabbitclients’: [‘basicbox’], ‘dbclients’: [‘basicbox’], ‘dbservers’: [‘db’], ‘nestseekers’: [‘db’, ‘nsweb’, ‘nsbeta’, ‘nsmailings’, ‘nsmain’, ‘basicbox’], ‘oldboxes’: [‘nsbeta’, ‘nsmain’, ‘nsmailings’, ‘nsweb’]}[‘dbclients’]”, “rc”: 1, “start”: “2013-03-15 11:40:11.249052”}

Another guess:

- name: open psql ports to trusted servers  
with\_items: $groups[‘dbclients’]  
action: command ufw allow from $hostvars[$item][‘ip’] to any port $psql\_port  
tags: postgresx

failed: [db] =\> (item={‘newservers’: , ‘all’: [‘db’, ‘nsweb’, ‘nsmailings’, ‘nsmain’, ‘nsbeta’, ‘basicbox’], ‘tasks’: , ‘webservers’: [‘basicbox’], ‘mailer’: , ‘ungrouped’: , ‘rabbitclients’: [‘basicbox’], ‘dbclients’: [‘basicbox’], ‘dbservers’: [‘db’], ‘nestseekers’: [‘db’, ‘nsweb’, ‘nsmailings’, ‘nsmain’, ‘nsbeta’, ‘basicbox’], ‘oldboxes’: [‘nsweb’, ‘nsmain’, ‘nsmailings’, ‘nsbeta’]}[‘dbclients’]) =\> {“changed”: true, “cmd”: [“ufw”, “allow”, “from”, “{db:”, “{}}[{newservers:”, “,”, “all:”, “[db,”, “nsweb,”, “nsmailings,”, “nsmain,”, “nsbeta,”, “basicbox],”, “tasks:”, “,”, “webservers:”, “[basicbox],”, “mailer:”, “,”, “ungrouped:”, “,”, “rabbitclients:”, “[basicbox],”, “dbclients:”, “[basicbox],”, “dbservers:”, “[db],”, “nestseekers:”, “[db,”, “nsweb,”, “nsmailings,”, “nsmain,”, “nsbeta,”, “basicbox],”, “oldboxes:”, “[nsweb,”, “nsmain,”, “nsmailings,”, “nsbeta]}[dbclients]][ip]”, “to”, “any”, “port”, “$psql\_port”], “delta”: “0:00:00.077508”, “end”: “2013-03-15 12:14:44.236852”, “item”: “{‘newservers’: , ‘all’: [‘db’, ‘nsweb’, ‘nsmailings’, ‘nsmain’, ‘nsbeta’, ‘basicbox’], ‘tasks’: , ‘webservers’: [‘basicbox’], ‘mailer’: , ‘ungrouped’: , ‘rabbitclients’: [‘basicbox’], ‘dbclients’: [‘basicbox’], ‘dbservers’: [‘db’], ‘nestseekers’: [‘db’, ‘nsweb’, ‘nsmailings’, ‘nsmain’, ‘nsbeta’, ‘basicbox’], ‘oldboxes’: [‘nsweb’, ‘nsmain’, ‘nsmailings’, ‘nsbeta’]}[‘dbclients’]”, “rc”: 1, “start”: “2013-03-15 12:14:44.159344”}  
stderr: Invalid syntax  
stdout:  
Usage: ufw COMMAND

etc.

I’ve looked at [http://ansible.cc/docs/playbooks2.html#magic-variables-and-how-to-access-information-about-other-hosts](http://ansible.cc/docs/playbooks2.html#magic-variables-and-how-to-access-information-about-other-hosts) but still can’t figure out how this should be done.

thanks !

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan2](https://avatars.discourse-cdn.com/v4/letter/m/da6949/32.png) [@Michael\_DeHaan2](https://forum.ansible.com/u/Michael_DeHaan2)\
**Post date:** [March 15, 2013, 6:13pm UTC](https://forum.ansible.com/t/iterating-with-items-groups-dbclients/12509/2 "2013-03-15T18:13:10Z")

</div>

- name: open psql ports to trusted servers  
&nbsp;&nbsp;with\_items: $groups['dbclients']  
&nbsp;&nbsp;action: command ufw allow from ${item['ip']} to any port $psql\_port  
&nbsp;&nbsp;tags: postgresx

First fix:

with\_items: ${groups.dbclients}

Second fix should be:

${hostvars.{$item}.ansible\_eth0.ipv4.address}

The reason being is there's no fact named 'ip', and $groups.dbclients  
is a list of all hostnames in the group, not the facts for each host  
in each group.

---

<div class="post-metadata">

**Author:** ![crucialfelix](https://avatars.discourse-cdn.com/v4/letter/c/f475e1/32.png) [@crucialfelix](https://forum.ansible.com/u/crucialfelix)\
**Post date:** [March 15, 2013, 7:28pm UTC](https://forum.ansible.com/t/iterating-with-items-groups-dbclients/12509/3 "2013-03-15T19:28:06Z")

</div>

thanks

actually I was not trying to access facts, but host variables.

there is a variable for that host as I showed here:

[webservers]  
basicbox ansible\_ssh\_host=1.2.3.4 ip=1.2.3.4

AFAIK the facts are only available if you have connected to that server.

the IP address is already known to me and its a long slow path to go gather facts from other servers when I’m just trying to write a conf file

so with\_items: ${groups.dbclients}  
will iterate $item as the hostname (string) ?

${hostvars.{$item}.ip}

should work ?

or maybe

${hostvars.{$item}.ansible\_ssh\_host}

?

here is another case I wanted to access variables of other hosts:

servers:

- ip: 16.7.12.143  
down: “”  
weight: 1

I would think that it is so common that this would be useful:

with\_hosts: groupname  
action: action: command ufw allow from ${host.ip} to any port $psql\_port

which would iterate over the hosts with all of their variables, each one built with relevant group\_vars etc

thanks again,

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan2](https://avatars.discourse-cdn.com/v4/letter/m/da6949/32.png) [@Michael\_DeHaan2](https://forum.ansible.com/u/Michael_DeHaan2)\
**Post date:** [March 15, 2013, 7:36pm UTC](https://forum.ansible.com/t/iterating-with-items-groups-dbclients/12509/4 "2013-03-15T19:36:12Z")

</div>

host variables and facts are both available in hostvars.

Making a with\_hosts\_in\_group: $foo

is quite doable!

---

<div class="post-metadata">

**Author:** ![crucialfelix](https://avatars.discourse-cdn.com/v4/letter/c/f475e1/32.png) [@crucialfelix](https://forum.ansible.com/u/crucialfelix)\
**Post date:** [March 15, 2013, 9:52pm UTC](https://forum.ansible.com/t/iterating-with-items-groups-dbclients/12509/5 "2013-03-15T21:52:46Z")

</div>

hmm. not working:

- name: open amqp rabbit port  
with\_items: ${groups.rabbitclients}  
action: command ufw allow from ${hostvars.{$item}.ansible\_eth0.ipv4.address} to any port amqp  
tags: rabbitx

failed: [tasks] =\> (item=tasks) =\> {“changed”: true, “cmd”: [“ufw”, “allow”, “from”, “${hostvars.{$item}.ansible\_eth0.ipv4.address}”, “to”, “any”, “port”, “amqp”], “delta”: “0:00:00.071405”, “end”: “2013-03-15 21:48:14.862130”, “item”: “tasks”, “rc”: 1, “start”: “2013-03-15 21:48:14.790725”}  
stderr: ERROR: Bad source address

you see its got the $ stuff in there, it really is passing that through. I’ve also noticed that missing variables become blank “” whereas I would welcome a big fat error on the ansible side.

I don’t think missing variables or $wgsi vs $wsgi should be allowed, they should result in exceptions.

here is me trying to use simple variables (no facts):

- name: open amqp rabbit port  
with\_items: ${groups.rabbitclients}  
action: command ufw allow from ${hostvars.{$item}.ip} to any port amqp  
tags: rabbitx

failed: [tasks] =\> (item=tasks) =\> {“changed”: true, “cmd”: [“ufw”, “allow”, “from”, “${hostvars.{$item}.ip}”, “to”, “any”, “port”, “amqp”], “delta”: “0:00:00.073316”, “end”: “2013-03-15 21:44:45.579267”, “item”: “tasks”, “rc”: 1, “start”: “2013-03-15 21:44:45.505951”}  
stderr: ERROR: Bad source address

ansible 1.1

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan2](https://avatars.discourse-cdn.com/v4/letter/m/da6949/32.png) [@Michael\_DeHaan2](https://forum.ansible.com/u/Michael_DeHaan2)\
**Post date:** [March 17, 2013, 1:28pm UTC](https://forum.ansible.com/t/iterating-with-items-groups-dbclients/12509/6 "2013-03-17T13:28:30Z")

</div>

BTW, the reason we don't make every "$foo" become an error is because  
you may wish to pass a literal "$foo".

This keeps Ansible users from having to escape everything.

You can print out a template that includes {{ hostvars | to\_nice\_yaml  
}} (assuming recent YAML) to see what facts you have available.

---

<div class="post-metadata">

**Author:** ![crucialfelix](https://avatars.discourse-cdn.com/v4/letter/c/f475e1/32.png) [@crucialfelix](https://forum.ansible.com/u/crucialfelix)\
**Post date:** [March 19, 2013, 5:06pm UTC](https://forum.ansible.com/t/iterating-with-items-groups-dbclients/12509/7 "2013-03-19T17:06:36Z")

</div>

I guess I’d have to disagree with the decision to allow unmatched variables to be passed on.  
I think its a syntax error and should fail.

I have never once found a reason to pass a literal $ and I’ll be quite happy to escape it when I do have one.

Once again today’s problem is from that:

root@tasks:~# rabbitmqctl list\_users  
Listing users …  
${rabbitmq\_user}   
guest [administrator]  
…done.

Its sending the literal ${rabbitmq\_user} and creating a user by that name.  
This makes debugging very difficult.

I cannot imagine a programming language that interprets undefined variables as literal strings.

---

<div class="post-metadata">

**Author:** ![crucialfelix](https://avatars.discourse-cdn.com/v4/letter/c/f475e1/32.png) [@crucialfelix](https://forum.ansible.com/u/crucialfelix)\
**Post date:** [March 20, 2013, 9:09am UTC](https://forum.ansible.com/t/iterating-with-items-groups-dbclients/12509/8 "2013-03-20T09:09:42Z")

</div>

Thanks, but I don’t think that has anything to do with the issue.

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan2](https://avatars.discourse-cdn.com/v4/letter/m/da6949/32.png) [@Michael\_DeHaan2](https://forum.ansible.com/u/Michael_DeHaan2)\
**Post date:** [March 20, 2013, 12:45pm UTC](https://forum.ansible.com/t/iterating-with-items-groups-dbclients/12509/9 "2013-03-20T12:45:47Z")

</div>

I think a warning when a "${" is still around is not a bad idea,  
though you may also be using shell with "$HOME" or something else.

I'll have to think a bit about the logic in which case we should /not/ warn.

Any ideas on other possible gotchas?

---

<div class="post-metadata">

**Author:** ![crucialfelix](https://avatars.discourse-cdn.com/v4/letter/c/f475e1/32.png) [@crucialfelix](https://forum.ansible.com/u/crucialfelix)\
**Post date:** [March 20, 2013, 1:02pm UTC](https://forum.ansible.com/t/iterating-with-items-groups-dbclients/12509/10 "2013-03-20T13:02:04Z")

</div>

I got gotchad again this morning. its been the number 1 cause of lost time so far.

thing like forgetting to include vars\_files: in a play  
and then the passwords are empty.

any minor typo results in a mysterious effect on a server where things all of a sudden can’t talk to each other.  
debugging and tracing it back takes a long time.

the other usability issue I’ve found so far is when an interactive dialog happens during a command I have to just wait and eventually realize that its not just being slow.

eg. if I mistype my sudo password  
or a command is waiting for me to hit (yes/no)

Other than that, great project ! Keeps it simple and solid.

I glanced through last year’s effort to get puppet to work and I have no idea what all those damned files do.

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan2](https://avatars.discourse-cdn.com/v4/letter/m/da6949/32.png) [@Michael\_DeHaan2](https://forum.ansible.com/u/Michael_DeHaan2)\
**Post date:** [March 20, 2013, 1:21pm UTC](https://forum.ansible.com/t/iterating-with-items-groups-dbclients/12509/11 "2013-03-20T13:21:36Z")

</div>

Great, I've opened a ticket so we don't forget about this:

[https://github.com/ansible/ansible/issues/2465](https://github.com/ansible/ansible/issues/2465)

As for things being interactive, I believe you are going to have to  
handle that, as we have to initialize a pty for when you are using  
sudo.

---

<div class="post-metadata">

**Author:** ![crucialfelix](https://avatars.discourse-cdn.com/v4/letter/c/f475e1/32.png) [@crucialfelix](https://forum.ansible.com/u/crucialfelix)\
**Post date:** [March 26, 2013, 11:59am UTC](https://forum.ansible.com/t/iterating-with-items-groups-dbclients/12509/12 "2013-03-26T11:59:03Z")

</div>

the working answer for my question is this:

gather\_facts: yes

- name: open psql ports to trusted servers  
with\_items: ${groups.dbclients}  
action: command ufw allow from ${hostvars.${item}.sip} to any port $psql\_port  
tags: postgresy

where ${groups.dbclients} returns a list of the names

and ${hostvars.${item}.sip} is the correct syntax for accessing the sip variable (not fact)

and most importantly: if you set gather\_facts: no then the variables are not accessible either.

that was quite non-obvious until I looked at the source code

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan2](https://avatars.discourse-cdn.com/v4/letter/m/da6949/32.png) [@Michael\_DeHaan2](https://forum.ansible.com/u/Michael_DeHaan2)\
**Post date:** [March 26, 2013, 12:51pm UTC](https://forum.ansible.com/t/iterating-with-items-groups-dbclients/12509/13 "2013-03-26T12:51:35Z")

</div>

There is a section in the docs that describes this for templates.

I'll comment on your ticket that we should also indicate how to do  
this there for mainstream playbooks.
