# Complex iteration problems

**URL:** <https://forum.ansible.com/t/complex-iteration-problems/18540>\
**Category:** Ansible Project\
**Created:** [June 18, 2015, 1:29pm UTC](https://forum.ansible.com/t/complex-iteration-problems/18540 "2015-06-18T13:29:15Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ashley\_Penney](https://avatars.discourse-cdn.com/v4/letter/a/48db29/32.png) [@Ashley\_Penney](https://forum.ansible.com/u/Ashley_Penney)\
**Post date:** [June 18, 2015, 1:29pm UTC](https://forum.ansible.com/t/complex-iteration-problems/18540/1 "2015-06-18T13:29:15Z")

</div>

Hi,

We’ve run into an issue (and a pattern really) using ansible that we’ve been unable to solve and I’m hoping the list can teach us the “ansible way”.

The background is that we want to create a number of monitors automatically, based on certain information. The solution we have today is a variable:

monitor\_exchanges:

- name: exchange1  
demand\_partners:
- ‘dp1’
- ‘dp2’

And the consumer:

- name: Create datadog monitors  
datadog\_monitor:  
state: “present”  
type: “query alert”  
name: ‘{{item.0.name}}-{{item.1}} over delivery’  
query: “avg({{monitor\_interval}}):100\*(avg:requests.outbound.transmitted.count{sp\_name:{{item.0.name}}, dp\_name:{{item.1}}} - avg:demand\_partner.rps{sp\_name:{{item.0.name}}, dp\_name:{{item.1}}})/avg:demand\_partner.rps{sp\_name:{{item.0.name}}, dp\_name:{{item.1}}} \> {{monitor\_threshold}}”  
message: “test”  
api\_key: “{{datadog\_api\_key}}”  
app\_key: “{{datadog\_app\_key}}”  
with\_subelements:
- monitor\_exchanges
- demand\_partners  
when: monitor\_exchanges is defined

This then creates, for each exchange a monitor per demand partner. That part is fairly easy and works fine but we wanted to externalize the ‘query’/‘name’/‘message’ part of the above thing, so that we’d have something more like:

- name: Create monitors  
datadog\_monitor:  
state: “present”  
type: “query alert”  
query: {{item.something.query}}  
name: {{item.something.query}}  
message: {{item.something.query}}

We kept trying to do this with two datastructures, the one from above and then  
something like “monitors” that would be a list of hashes containing each monitor to create. I couldn’t come up with the right combination of iteration to make it work however, because I really needed to iterate over two separate things in different ways, I couldn’t just list the two structures, I needed to do something more like:

with\_nested:

- with\_subelements:
- monitor\_exchanges
- demand\_partners
- monitors

Is there another way I can model this that makes sense? I really just want to iterate over a list of monitors and then for each monitor iterate over the `monitor_exchanges` list to pull all the appropriate data.

---

<div class="post-metadata">

**Author:** ![Christian\_Thiemann](https://avatars.discourse-cdn.com/v4/letter/c/f04885/32.png) [@Christian\_Thiemann](https://forum.ansible.com/u/Christian_Thiemann)\
**Post date:** [June 18, 2015, 4:18pm UTC](https://forum.ansible.com/t/complex-iteration-problems/18540/2 "2015-06-18T16:18:21Z")

</div>

The fundamental problem is that Ansible doesn’t allow nested loops – even though Ansible looks like a procedural language (it’s executing commands/modules in order and it can loop over things), it really isn’t. The only “simulation” of a for/while loop is the with\_foobar stuff, which calls a lookup plugin that must return a simple list to iterate over. You could write your own lookup plugin that does a combination of the subelements and nested plugins, but if you want to stay in the “Ansible realm”, then here’s a solution that I used to solve a similar problem:

Define a helper variable that does the work of with\_subelements:

`  
monitor\_exchange\_demand\_partners: |  
{%- set result = -%}  
{%- for exchange in monitor\_exchanges|default() -%}  
{%- do result.extend(exchange.demand\_partners|default() -%}  
{%- endfor -%}  
{{ result|unique }}

`

That exploits the fact that Ansible variables are Jinja templates, and that if a template evaluates into a string representation of a list or dict it will be converted to that list/dict. You’ll have to add this to your ansible.cfg (Ansible variables in combination with Jinja look like a functional language, but Jinja lacks all the important tools of functional programming, so we’ll use an extension that turns Jinja into a procedural language instead):

`  
[defaults]  
jinja2\_extensions = jinja2.ext.do

`

Then you can use a simple with\_nested:

`

- datadog\_monitor: …  
with\_nested:
- monitor\_exchange\_demand\_partners
- monitors

`

---

<div class="post-metadata">

**Author:** ![Brian\_Coca](https://avatars.discourse-cdn.com/v4/letter/b/6de8d8/32.png) [@Brian\_Coca](https://forum.ansible.com/u/Brian_Coca)\
**Post date:** [June 18, 2015, 5:04pm UTC](https://forum.ansible.com/t/complex-iteration-problems/18540/3 "2015-06-18T17:04:35Z")

</div>

this won't work  
with\_nested:  
&nbsp;&nbsp;- with\_subelements:  
&nbsp;&nbsp;&nbsp;&nbsp;- monitor\_exchanges  
&nbsp;&nbsp;&nbsp;&nbsp;- demand\_partners  
&nbsp;&nbsp;- monitors

but this will:  
with\_nested:  
&nbsp;&nbsp;- "{{lookup('subelements', [monitor\_exchanges, demand\_partners]}""  
&nbsp;&nbsp;- monitors

I'm not sure that will get you what you want, but it should correctly  
combine the lookups now

---

<div class="post-metadata">

**Author:** ![Johnny\_Everson](https://avatars.discourse-cdn.com/v4/letter/j/3da27b/32.png) [@Johnny\_Everson](https://forum.ansible.com/u/Johnny_Everson)\
**Post date:** [June 18, 2015, 6:33pm UTC](https://forum.ansible.com/t/complex-iteration-problems/18540/4 "2015-06-18T18:33:45Z")

</div>

Hi Brian,

I am trying to implement your suggestion, I am getting:

“ERROR! an unexpected type error occurred. Error was sequence item 0: expected string, tuple found” (I fixed the obvious typo in your code)

Does this ring a bell?

---

<div class="post-metadata">

**Author:** ![Brian\_Coca](https://avatars.discourse-cdn.com/v4/letter/b/6de8d8/32.png) [@Brian\_Coca](https://forum.ansible.com/u/Brian_Coca)\
**Post date:** [June 18, 2015, 7:12pm UTC](https://forum.ansible.com/t/complex-iteration-problems/18540/5 "2015-06-18T19:12:29Z")

</div>

are you using current devel?

---

<div class="post-metadata">

**Author:** ![Johnny\_Everson](https://avatars.discourse-cdn.com/v4/letter/j/3da27b/32.png) [@Johnny\_Everson](https://forum.ansible.com/u/Johnny_Everson)\
**Post date:** [June 18, 2015, 7:14pm UTC](https://forum.ansible.com/t/complex-iteration-problems/18540/6 "2015-06-18T19:14:35Z")

</div>

yes, on devel, last synced on Jun 16.

---

<div class="post-metadata">

**Author:** ![Brian\_Coca](https://avatars.discourse-cdn.com/v4/letter/b/6de8d8/32.png) [@Brian\_Coca](https://forum.ansible.com/u/Brian_Coca)\
**Post date:** [June 18, 2015, 7:35pm UTC](https://forum.ansible.com/t/complex-iteration-problems/18540/7 "2015-06-18T19:35:50Z")

</div>

some of the lookups are not working correctly with devel, that woudl  
be the error messasge you get
