# using a dict as task parameters

**URL:** <https://forum.ansible.com/t/using-a-dict-as-task-parameters/24064>\
**Category:** Ansible Project\
**Created:** [March 26, 2017, 3:17pm UTC](https://forum.ansible.com/t/using-a-dict-as-task-parameters/24064 "2017-03-26T15:17:45Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![lmeyer](https://avatars.discourse-cdn.com/v4/letter/l/6f9a4e/32.png) [@lmeyer](https://forum.ansible.com/u/lmeyer)\
**Post date:** [March 26, 2017, 3:17pm UTC](https://forum.ansible.com/t/using-a-dict-as-task-parameters/24064/1 "2017-03-26T15:17:45Z")

</div>

Under Ansible 2.2.1 and python 2.7 I have a playbook for generically creating a docker container and then adding it as a host (using the docker connection plugin of course):

- name: Start specified container  
gather\_facts: no  
hosts: localhost  
connection: local  
vars:  
container\_name: openshift\_ansible\_test\_{{ scenario }}  
l\_vars: \>  
{{  
l\_host\_vars | default({}) | combine({  
“ansible\_connection”: “docker”,  
“name”: container\_name,  
“groups”: l\_groups if l\_groups else “OSEv3,masters,nodes”,  
})  
}}  
tasks:
- debug: var=l\_vars
- name: start container  
docker\_container:  
name: “{{ container\_name }}”  
image: “{{ image }}”  
command: sleep 1800  
recreate: yes  
when: False
- name: add host  
add\_host: “{{ l\_vars }}”

The idea is to be able to pass in l\_host\_vars with variable properties for add\_host. l\_vars gets populated as expected, so the debug looks like this:

ok: [localhost] =\> {  
“l\_vars”: {  
“ansible\_connection”: “docker”,  
“deployment\_type”: “origin”,  
“groups”: “OSEv3,masters,nodes,etcd”,  
“name”: “openshift\_ansible\_test\_preflight\_fail\_all”  
}  
}

However the add\_host task does not like it as parameters and there does not seem to be any variation that will get it to work:

creating host via ‘add\_host’: hostname=None  
ERROR! Unexpected Exception: unsupported operand type(s) for +: ‘NoneType’ and ‘str’  
the full traceback was:

Traceback (most recent call last):  
File “/bin/ansible-playbook”, line 103, in   
exit\_code = cli.run()  
File “/usr/lib/python2.7/site-packages/ansible/cli/playbook.py”, line 159, in run  
results = pbex.run()  
File “/usr/lib/python2.7/site-packages/ansible/executor/playbook\_executor.py”, line 154, in run  
result = self.\_tqm.run(play=play)  
File “/usr/lib/python2.7/site-packages/ansible/executor/task\_queue\_manager.py”, line 282, in run  
play\_return = strategy.run(iterator, play\_context)  
File “/usr/lib/python2.7/site-packages/ansible/plugins/strategy/linear.py”, line 278, in run  
results += self.\_wait\_on\_pending\_results(iterator)  
File “/usr/lib/python2.7/site-packages/ansible/plugins/strategy/ **init**.py”, line 577, in \_wait\_on\_pending\_results  
results = self.\_process\_pending\_results(iterator)  
File “/usr/lib/python2.7/site-packages/ansible/plugins/strategy/ **init**.py”, line 478, in \_process\_pending\_results  
self.\_add\_host(new\_host\_info, iterator)  
File “/usr/lib/python2.7/site-packages/ansible/plugins/strategy/ **init**.py”, line 598, in \_add\_host  
self.\_inventory.get\_host\_vars(new\_host)  
File “/usr/lib/python2.7/site-packages/ansible/inventory/ **init**.py”, line 771, in get\_host\_vars  
return self.\_get\_hostgroup\_vars(host=host, group=None, new\_pb\_basedir=new\_pb\_basedir, return\_results=return\_result  
s)  
File “/usr/lib/python2.7/site-packages/ansible/inventory/ **init**.py”, line 842, in \_get\_hostgroup\_vars  
elif group is None and any(map(lambda ext: host.name + ext in self.\_host\_vars\_files, C.YAML\_FILENAME\_EXTENSIONS)):  
File “/usr/lib/python2.7/site-packages/ansible/inventory/ **init**.py”, line 842, in   
elif group is None and any(map(lambda ext: host.name + ext in self.\_host\_vars\_files, C.YAML\_FILENAME\_EXTENSIONS)):  
TypeError: unsupported operand type(s) for +: ‘NoneType’ and ‘str’

Any idea how I can get this to do what I want? TIA

---

<div class="post-metadata">

**Author:** ![lmeyer](https://avatars.discourse-cdn.com/v4/letter/l/6f9a4e/32.png) [@lmeyer](https://forum.ansible.com/u/lmeyer)\
**Post date:** [March 27, 2017, 3:14pm UTC](https://forum.ansible.com/t/using-a-dict-as-task-parameters/24064/2 "2017-03-27T15:14:33Z")

</div>

To elaborate a bit on my use case, I’m trying to run integration tests on playbooks - that is, test the playbooks in various scenarios. For each test, I want to spin up a docker container (or several) and treat them as the hosts against which the playbook is being tested. And then I’d like to delete the docker containers.

Aside from the problem of parameterizing the creation of a “host”, I’m wondering how to delete the containers if the test fails. There doesn’t seem to be any way to recover from a playbook include failing. It has to be a playbook include because it’s a playbook being tested, and I’d like to pass it the inventory that’s been created. But then there’s no way on a play include to add handlers or failed\_when or register or any of the other goodies that are available for tasks. The only thing I could think of is to have something write out the inventory (how?) and feed it to a command task that runs the target playbook.

Or is this just a fundamental mismatch with the Ansible Way and I should be considering some other approach entirely?

---

<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:** [March 27, 2017, 4:34pm UTC](https://forum.ansible.com/t/using-a-dict-as-task-parameters/24064/3 "2017-03-27T16:34:53Z")

</div>

You need to specify each of them, but you can still use the variable in the add\_host.  
So I would think that this should work:

&nbsp;&nbsp;&nbsp;- name: add host  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add\_host:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ansible\_connection: "{{ l\_vars.l\_host\_vars.ansible\_connection }}"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name: "{{ l\_vars.l\_host\_vars.name }}"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;groups: "{{ l\_vars.l\_host\_vars.groups }}"

---

<div class="post-metadata">

**Author:** ![lmeyer](https://avatars.discourse-cdn.com/v4/letter/l/6f9a4e/32.png) [@lmeyer](https://forum.ansible.com/u/lmeyer)\
**Post date:** [March 27, 2017, 5:13pm UTC](https://forum.ansible.com/t/using-a-dict-as-task-parameters/24064/4 "2017-03-27T17:13:07Z")

</div>

That would work, but is there a way that would allow me to pass in arbitrary variables instead of just a known list?

---

<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:** [March 27, 2017, 5:46pm UTC](https://forum.ansible.com/t/using-a-dict-as-task-parameters/24064/5 "2017-03-27T17:46:50Z")

</div>

I don't think it's possible with add\_host, but you can use set\_fact

&nbsp;&nbsp;&nbsp;- set\_fact:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"{{ item.name }}": "{{ item.value }}"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delegate\_facts: true  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delegate\_to: testhost  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;with\_items:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- name: k1  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value: v1  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- name: k2  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value: v2

This will add k1=v1 and k2=v2 to the host testhost.

---

<div class="post-metadata">

**Author:** ![lmeyer](https://avatars.discourse-cdn.com/v4/letter/l/6f9a4e/32.png) [@lmeyer](https://forum.ansible.com/u/lmeyer)\
**Post date:** [March 27, 2017, 6:20pm UTC](https://forum.ansible.com/t/using-a-dict-as-task-parameters/24064/6 "2017-03-27T18:20:10Z")

</div>

Thanks, that seems to do what I want! I ended up with:

- name: adjust host facts.  
set\_fact:  
“{{ item.key }}”: “{{ item.value }}”  
delegate\_facts: True  
delegate\_to: “{{ container\_name }}”  
with\_dict: “{{ l\_host\_vars }}”

I should note that first I tried:

- name: adjust host facts.  
set\_fact: “{{ l\_host\_vars }}”  
delegate\_facts: True

delegate\_to: “{{ container\_name }}”

Which _seemed_ to work, but actually ended up setting the vars somewhere other than directly on the host (not sure what “\_raw\_params” is supposed to be), so behavior was not what I wanted. Setting the facts individually seems to be the only path that works.
