# Question about passing a list to a module

**URL:** <https://forum.ansible.com/t/question-about-passing-a-list-to-a-module/12369>\
**Category:** Ansible Project\
**Tags:** ubuntu\
**Created:** [February 16, 2013, 8:58pm UTC](https://forum.ansible.com/t/question-about-passing-a-list-to-a-module/12369 "2013-02-16T20:58:23Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Steve1](https://avatars.discourse-cdn.com/v4/letter/s/3da27b/32.png) [@Steve1](https://forum.ansible.com/u/Steve1)\
**Post date:** [February 16, 2013, 8:58pm UTC](https://forum.ansible.com/t/question-about-passing-a-list-to-a-module/12369/1 "2013-02-16T20:58:23Z")

</div>

I’d like to enhance the ec2 module to support creating/attaching volumes.

Updating it was rather simple, but I am having trouble passing volumes to it, due to the way vars get parsed (i think).

In the playbook, I want to do something like

> vars:
> 
> - volumes:
> - { device: “/dev/sdf”, size: 1 }
> - { device: “/dev/sdg”, size: 1 }
> - { device: “/dev/sdh”, size: 1, otherattrib: value }  
> tasks:
> - local\_action: ec2 keypair=“test” group=“test” instance\_type=“t1.micro” image=“ami-3d4ff254” wait=true **volumes=$volumes**

But that fails with:

> File “/home/ubuntu/ansible/lib/ansible/utils/template.py”, line 222, in varReplace  
> replacement = “,”.join(replacement)  
> TypeError: sequence item 0: expected string, dict found

So I hacked lib/ansible/utils/template.py:

> if expand\_lists and isinstance(replacement, (list, tuple)):  
> if isinstance(replacement, (list)):  
> parts =   
> for item in replacement:  
> if item is dict:  
> pass  
> else:  
> parts.append(item)  
> replacement = parts. **str** ()  
> else:  
> replacement = “,”.join(replacement)

Which was enough to let me move on… but I still am dealing with a string instead of a list of dictionaries like I was hoping for. So I wound up using ast.literal\_eval.

**So my question is, is there a way to pass a variable (which is a list) without it getting converted to a string?**

New ec2 module code:

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@Michael\_DeHaan](https://forum.ansible.com/u/Michael_DeHaan)\
**Post date:** [February 16, 2013, 9:13pm UTC](https://forum.ansible.com/t/question-about-passing-a-list-to-a-module/12369/2 "2013-02-16T21:13:13Z")

</div>

> I'd like to enhance the ec2 module to support creating/attaching volumes.

You may be interested to see the ec2vol module I just pushed today  
from Lester Wade!

> Updating it was rather simple, but I am having trouble passing volumes to  
> it, due to the way vars get parsed (i think).
> 
> In the playbook, I want to do something like
> 
> > &nbsp;&nbsp;vars:  
> > &nbsp;&nbsp;- volumes:  
> > &nbsp;&nbsp;&nbsp;&nbsp;- { device: "/dev/sdf", size: 1 }  
> > &nbsp;&nbsp;&nbsp;&nbsp;- { device: "/dev/sdg", size: 1 }  
> > &nbsp;&nbsp;&nbsp;&nbsp;- { device: "/dev/sdh", size: 1, otherattrib: value }  
> > &nbsp;&nbsp;tasks:  
> > &nbsp;&nbsp;- local\_action: ec2 keypair="test" group="test" instance\_type="t1.micro"  
> > image="ami-3d4ff254" wait=true volumes=$volumes
> 
> But that fails with:
> 
> > &nbsp;&nbsp;File "/home/ubuntu/ansible/lib/ansible/utils/template.py", line 222, in  
> > varReplace  
> > &nbsp;&nbsp;&nbsp;&nbsp;replacement = ",".join(replacement)  
> > TypeError: sequence item 0: expected string, dict found

Us exposing tracebacks and not errors for humans isn't cool, but it's  
true it didn't expect a list there. In general you can't do that.

What you want is:

- location\_action: foo arg=$item  
&nbsp;&nbsp;with\_items: $listvar

And yes, that will call your module multiple times.

You can't pass complex variables to modules -- that's coming super  
soon now (this weekend) - although even then the module has to be  
coded to do something with that data.

> So I hacked lib/ansible/utils/template.py:
> 
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if expand\_lists and isinstance(replacement, (list, tuple)):  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if isinstance(replacement, (list)):  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parts =   
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for item in replacement:  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if item is dict:  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pass  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parts.append(item)  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;replacement = parts.\_\_str\_\_()  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;replacement = ",".join(replacement)
> 
> Which was enough to let me move on... but I still am dealing with a string  
> instead of a list of dictionaries like I was hoping for. So I wound up using  
> ast.literal\_eval.
> 
> So my question is, is there a way to pass a variable (which is a list)  
> without it getting converted to a string?

with\_items is what you want.

---

<div class="post-metadata">

**Author:** ![Steve1](https://avatars.discourse-cdn.com/v4/letter/s/3da27b/32.png) [@Steve1](https://forum.ansible.com/u/Steve1)\
**Post date:** [February 16, 2013, 11:05pm UTC](https://forum.ansible.com/t/question-about-passing-a-list-to-a-module/12369/3 "2013-02-16T23:05:06Z")

</div>

Of course I started coding right before your merges… that’s life.

The ec2\_vol module will work, though not as I had intended. I will now be provisioning the volumes in my setup playbook, instead of my provisioning playbook.

To provision, I have different values for instances and volumes based on whether this is dev, staging or prod, but it is basically something like:

vars:

- instances:
- { name: db1, type: db, instance: $instance\_type, image: $image\_type }
- { name: db2, type: db, instance: $instance\_type, image: $image\_type }
- { name: dbx, type: db, instance: $instance\_type, image: $image\_type }
- volumes:
- { device: “/dev/sdf”, size: 1 }
- { device: “/dev/sdg”, size: 1 }
- { device: “/dev/sdh”, size: 1, otherattrib: value }

tasks:

- local\_action: ec2 …  
register: instres  
with\_items: ${instances}

- local\_action: wait\_for host=${item.public\_dns\_name} port=22 delay=20 timeout=300  
with\_items: ${instres.results[0].instances}

So to use ec2\_vol here wouldn’t work since I would need to loop over 2 lists, which I don’t think is possible.

- local\_action: ec2\_vol …  
with\_items: ${instres.results[0].instances}

with\_items: ${volumes}

won’t work.

I was trying not to introduce yet another module. Namespaces/subdirectories will be really nice.

Complex variables sounds awesome. Can’t wait to look.
