# with\_items combined with when to set variables and then break

**URL:** <https://forum.ansible.com/t/with-items-combined-with-when-to-set-variables-and-then-break/28222>\
**Category:** Ansible Project\
**Created:** [August 1, 2018, 10:41am UTC](https://forum.ansible.com/t/with-items-combined-with-when-to-set-variables-and-then-break/28222 "2018-08-01T10:41:12Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Sabrina\_Lautier](https://avatars.discourse-cdn.com/v4/letter/s/c2a13f/32.png) [@Sabrina\_Lautier](https://forum.ansible.com/u/Sabrina_Lautier)\
**Post date:** [August 1, 2018, 10:41am UTC](https://forum.ansible.com/t/with-items-combined-with-when-to-set-variables-and-then-break/28222/1 "2018-08-01T10:41:12Z")

</div>

Hi everyone,

I have already read several post about this but haven’t found the answer.  
Basically I would like to set some variables when a condition is met while looping over a list of dictionaries, and then stop the loop and keep the variables to use them afterwards.

This code shows when the condition is met (prints ok) but the loop keeps iterating and the content of the variables is lost :

`

- name: Check if the customer already exists in the Ops db  
set\_fact:  
customer\_found: true  
customer\_id: item[‘id’]  
customer\_name: item[‘customer\_details’][‘name’]  
customer\_size: item[‘customer\_details’][‘size’]  
when: item[‘customer\_details’][‘country’] == (tenant\_country\_code\_2l | trim) and item[‘customer\_details’][‘icn’] == tenant\_icn\_7d  
with\_items: “{{ customers\_data }}”  
`

This is the output:

`  
TASK [… : Check if the customer already exists in the DB]  
ok: [runner\_ansible] =\> (item={u’id’: u’0’, u’customer\_details’: {u’country’: u’DE’, u’size’: u’small’, u’icn’: u’1234569’, u’name’: u’CustomerTenant019’}})  
skipping: [runner\_ansible] =\> (item={u’id’: u’1’, u’customer\_details’: {u’country’: u’FR’, u’size’: u’small’, u’icn’: u’999999’, u’name’: u’ODM team’}})

TASK [… : Print the customer id]  
ok: [runner\_ansible] =\> {}

MSG:

Customer id = item[‘id’]

`

The variable customer\_id seems not to be assigned as ‘item[‘id’]’ is printed.

I’ve got the feeling there should be a better way to achieve this with ansible, and anyway, this code does not work.

Any help will be much appreciated.

Best,  
Sabrina

---

<div class="post-metadata">

**Author:** ![Kai\_Stian\_Olstad](https://avatars.discourse-cdn.com/v4/letter/k/e19adc/32.png) [@Kai\_Stian\_Olstad](https://forum.ansible.com/u/Kai_Stian_Olstad)\
**Post date:** [August 1, 2018, 11:37am UTC](https://forum.ansible.com/t/with-items-combined-with-when-to-set-variables-and-then-break/28222/2 "2018-08-01T11:37:53Z")

</div>

> Hi everyone,
> 
> I have already read several post about this but haven't found the answer.  
> Basically I would like to set some variables when a condition is met while  
> looping over a list of dictionaries, and then stop the loop and keep the  
> variables to use them afterwards.
> 
> This code shows when the condition is met (prints ok) but the loop keeps  
> iterating and the content of the variables is lost :  
> - name: Check if the customer already exists in the Ops db  
> &nbsp;&nbsp;set\_fact:  
> &nbsp;&nbsp;&nbsp;&nbsp;customer\_found: true  
> &nbsp;&nbsp;&nbsp;&nbsp;customer\_id: item['id']  
> &nbsp;&nbsp;&nbsp;&nbsp;customer\_name: item['customer\_details']['name']  
> &nbsp;&nbsp;&nbsp;&nbsp;customer\_size: item['customer\_details']['size']  
> &nbsp;&nbsp;when: item['customer\_details']['country'] == (tenant\_country\_code\_2l \> trim) and item['customer\_details']['icn'] == tenant\_icn\_7d  
> &nbsp;&nbsp;with\_items: "{{ customers\_data }}"

Variables in Ansible need to be enclosed in {{ }} unless you already are in Jinga template like in when:  
But you items in set\_facts need {{ }}

&nbsp;&nbsp;&nbsp;customer\_id: "{{ item['id'] }}"

Do that to all of them.

It will still loop over all the items, there are no way to stop that with with\_items.  
And if more than one record match the last one will stick in the variables.

> This is the output:  
> TASK [.. : Check if the customer already exists in the DB]  
> ok: [runner\_ansible] =\> (item={u'id': u'0', u'customer\_details': {u'country'  
> : u'DE', u'size': u'small', u'icn': u'1234569', u'name': u  
> 'CustomerTenant019'}})  
> skipping: [runner\_ansible] =\> (item={u'id': u'1', u'customer\_details': {u  
> 'country': u'FR', u'size': u'small', u'icn': u'999999', u'name': u'ODM team'  
> }})
> 
> TASK [.. : Print the customer id]  
> ok: [runner\_ansible] =\> {}
> 
> MSG:
> 
> Customer id = item['id']

Here you see that the variables got the value item['id'] and not the content of the variable when {{}} if forgotten.

> The variable customer\_id seems not to be assigned as 'item['id']' is  
> printed.
> 
> I've got the feeling there should be a better way to achieve this with  
> ansible, and anyway, this code does not work.

You could do something like this.

&nbsp;&nbsp;&nbsp;- set\_fact:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;customer: "{{ (customers\_data | selectattr('customer\_details.country', 'equalto', tenant\_country\_code\_2l

> trim) | selectattr('customer\_details.icn', 'equalto', tenant\_icn\_7d) |

first | default(False) ) }}"

If the customer doesn't exist customer = False, it it exist you will have customer.id, customer.customer\_details.country and so on.  
The syntax customer.id is the same as customer['id'], reason I use the former is to avoid escaping the quotes hell.

And to use it you could do something like this

&nbsp;&nbsp;&nbsp;- debug: msg="Customer exist"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when: customer.id is defined

&nbsp;&nbsp;&nbsp;- debug: msg="Customer doesn't exist"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when: customer.id is not defined

---

<div class="post-metadata">

**Author:** ![Sabrina\_Lautier](https://avatars.discourse-cdn.com/v4/letter/s/c2a13f/32.png) [@Sabrina\_Lautier](https://forum.ansible.com/u/Sabrina_Lautier)\
**Post date:** [August 1, 2018, 11:49am UTC](https://forum.ansible.com/t/with-items-combined-with-when-to-set-variables-and-then-break/28222/3 "2018-08-01T11:49:15Z")

</div>

Thanks a lot Kai, I didn’t know about this and didn’t think about this (I stupidly lost few hours):

> But you items in set\_facts need {{ }}  
> customer\_id: “{{ item[‘id’] }}”

It works fine now :).

Best,  
Sabrina

---

<div class="post-metadata">

**Author:** ![Sabrina\_Lautier](https://avatars.discourse-cdn.com/v4/letter/s/c2a13f/32.png) [@Sabrina\_Lautier](https://forum.ansible.com/u/Sabrina_Lautier)\
**Post date:** [September 10, 2018, 2:54pm UTC](https://forum.ansible.com/t/with-items-combined-with-when-to-set-variables-and-then-break/28222/4 "2018-09-10T14:54:12Z")

</div>

_\> It will still loop over all the items, there are no way to stop that with with\_items._

_\> And if more than one record match the last one will stick in the variables._

Yes, thanks, that’s exactly what I want.  
In my case, there should be only one match, if there are 2, this means there’s a duplicate entry, which is not normal and should be reported.  
If there a way to know the number of matches?

I can see 2 hits in the log:  
`

ok: [runner\_ansible] =\> (item={‘id’: ‘xxx’, ‘customer\_details’: {}}) =\> {  
  
ok: [runner\_ansible] =\> (item={‘id’: ‘yyy’, ‘customer\_details’: {}}) =\> {

`  
Does a variable store the number of hits?
