# passing data to roles via parameters without accidentally flattening it

**URL:** <https://forum.ansible.com/t/passing-data-to-roles-via-parameters-without-accidentally-flattening-it/13423>\
**Category:** Ansible Project\
**Created:** [September 5, 2013, 10:57pm UTC](https://forum.ansible.com/t/passing-data-to-roles-via-parameters-without-accidentally-flattening-it/13423 "2013-09-05T22:57:49Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Nick](https://avatars.discourse-cdn.com/v4/letter/n/f9ae1b/32.png) [@Nick](https://forum.ansible.com/u/Nick)\
**Post date:** [September 5, 2013, 10:57pm UTC](https://forum.ansible.com/t/passing-data-to-roles-via-parameters-without-accidentally-flattening-it/13423/1 "2013-09-05T22:57:49Z")

</div>

Hello,

I’ve been having some problems passing parameters to roles. Essentially the data in my parameter is getting flattened into a string using {{}} interpolation, but not with ${} interpolation. Is there a recommended way to pass parameters like this? I want top be able to define lists of dictionaries. pass them to roles, and have the roles loop over them.

A toy example - given a playbook like this which passes a list parameter ‘databases’ to a role called ‘mysql’:

`---`  
`- name: test roles`  
`hosts: all`  
`user: root`  
`roles:`  
`- role: mysql`  
`databases:`  
```- ‘{{my.`mysql`.database}}’`

The mysql role consists only of this tasks/main.yml file:

`---`  
`- debug: msg="database is '{{databases[0].name}}'"`

`- debug: msg="database is '{{item}}'"`  
`with_items: '{{databases}}'`

I am defining my.mysql.database variable in host\_vars/all:

`my:`  
`mysql:`  
`database:`  
`name: fred`

I get an error implying that the parameter’s data has been flattened into a string, as follows:

`TASK: [debug msg="database is '{{databases[0].name}}'"] *********************** `  
`fatal: [lamian.noodlefactory.co.uk] => One or more undefined variables: 'unicode object' has no attribute 'name'`

Removing the quotes is no good, it gets a YAML syntax error.

`ERROR: Syntax Error while loading YAML script, test-roles.yml`  
`Note: The error may actually appear before this position: line 8, column 12`

`databases:`  
`- {{my.drupal.database}}`  
`^`

But what does work is using the old dollar syntax, ${my.mysql.database}, with no quotes:

`TASK: [debug msg="database is '{{databases[0].name}}'"] *********************** `  
`ok: [lamian.noodlefactory.co.uk] => {"item": "", "msg": "database is 'fred'"}`

`TASK: [debug msg="database is ''"] ******************************************** `  
`ok: [lamian.noodlefactory.co.uk] => (item={'name': 'fred'}) => {"item": {"name": "fred"}, "msg": "database is '{'name': 'fred'}'"}`

However, I gather that syntax is discouraged these days. Is there a way of avoiding it in this case?

Cheers,

Nick

---

<div class="post-metadata">

**Author:** ![Nick](https://avatars.discourse-cdn.com/v4/letter/n/f9ae1b/32.png) [@Nick](https://forum.ansible.com/u/Nick)\
**Post date:** [September 5, 2013, 11:04pm UTC](https://forum.ansible.com/t/passing-data-to-roles-via-parameters-without-accidentally-flattening-it/13423/2 "2013-09-05T23:04:55Z")

</div>

Whoops. This should actually read {{my.mysql.database}} to be consistent with my  
example. But the point stands.

---

<div class="post-metadata">

**Author:** ![Nathan\_Howell](https://avatars.discourse-cdn.com/v4/letter/n/65b543/32.png) [@Nathan\_Howell](https://forum.ansible.com/u/Nathan_Howell)\
**Post date:** [September 5, 2013, 11:08pm UTC](https://forum.ansible.com/t/passing-data-to-roles-via-parameters-without-accidentally-flattening-it/13423/3 "2013-09-05T23:08:45Z")

</div>

Good timing on this post. This looks like the same issue I’ve been dealing with today. Does it work if you load the variables using vars\_files instead of in host\_vars?

Nathan

---

<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:** [September 6, 2013, 12:33pm UTC](https://forum.ansible.com/t/passing-data-to-roles-via-parameters-without-accidentally-flattening-it/13423/4 "2013-09-06T12:33:06Z")

</div>

`If you are referencing variables inside other datastructures this is the one case where you still have to do $foo.`

`We're currently exploring how to eliminate this.`

---

<div class="post-metadata">

**Author:** ![C\_Morgan\_Hamill](https://avatars.discourse-cdn.com/v4/letter/c/ebca7d/32.png) [@C\_Morgan\_Hamill](https://forum.ansible.com/u/C_Morgan_Hamill)\
**Post date:** [September 6, 2013, 12:52pm UTC](https://forum.ansible.com/t/passing-data-to-roles-via-parameters-without-accidentally-flattening-it/13423/5 "2013-09-06T12:52:58Z")

</div>

Excerpts from Michael DeHaan's message of 2013-09-06 08:33:06 -0400:

> If you are referencing variables inside other datastructures this is the  
> one case where you still have to do $foo.

Having run into this also, I have a couple cents regarding it and some  
other difficulties I've run into with variables also.

I think it's a really \*nice\* feature that jinja2-style variables in  
playbooks work almost identically to real jinja2 templates. That is to  
say, the current functionality can be reasoned about as though your  
playbooks are simply being run through jinja2 as templates. The fact  
that '{{ foo.fanciness|whatever\_magic\_you\_want is defined }}' \*always\*  
evaluates to a string is, in my opinion, awesome.

If you can avoid tromping on that, it would be awesome. That said, the  
complex-arguments-to-modules use case and the references use case are  
really compelling, and I'd love a solution there too.

Perhaps related to the references use case is that the following still  
works in, say, a vars file:

&nbsp;&nbsp;&nbsp;&nbsp;foo:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bar: hello  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nar: ${foo.hello}/noway/howdy

But this doesn't:

&nbsp;&nbsp;&nbsp;&nbsp;foo:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bar: hello  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nar: "{{ foo.hello }}/noway/howdy"

While it's reasonable that it doesn't work, considering the  
self-reference, it's also really nice to be able to do sometimes, and  
allows the use of hash tables as role variable namespaces instead of the  
'role\_' prefix that some folks are using.

---

<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:** [September 6, 2013, 12:57pm UTC](https://forum.ansible.com/t/passing-data-to-roles-via-parameters-without-accidentally-flattening-it/13423/6 "2013-09-06T12:57:07Z")

</div>

role variable namespaces are pretty unnecessary in 1.3 due to the way you are always guaranteed to get the value from the role in that current role.

---

<div class="post-metadata">

**Author:** ![C\_Morgan\_Hamill](https://avatars.discourse-cdn.com/v4/letter/c/ebca7d/32.png) [@C\_Morgan\_Hamill](https://forum.ansible.com/u/C_Morgan_Hamill)\
**Post date:** [September 6, 2013, 1:08pm UTC](https://forum.ansible.com/t/passing-data-to-roles-via-parameters-without-accidentally-flattening-it/13423/7 "2013-09-06T13:08:39Z")

</div>

Excerpts from Michael DeHaan's message of 2013-09-06 08:57:07 -0400:

> role variable namespaces are pretty unnecessary in 1.3 due to the way you  
> are always guaranteed to get the value from the role in that current role.

Oh jeez, I completely missed that implication of the feature!

Thanks!

---

<div class="post-metadata">

**Author:** ![Serge\_van\_Ginderacht](https://avatars.discourse-cdn.com/v4/letter/s/b782af/32.png) [@Serge\_van\_Ginderacht](https://forum.ansible.com/u/Serge_van_Ginderacht)\
**Post date:** [September 6, 2013, 1:16pm UTC](https://forum.ansible.com/t/passing-data-to-roles-via-parameters-without-accidentally-flattening-it/13423/8 "2013-09-06T13:16:05Z")

</div>

​The problem here is you need to quote it:​

---

<div class="post-metadata">

**Author:** ![Nick](https://avatars.discourse-cdn.com/v4/letter/n/f9ae1b/32.png) [@Nick](https://forum.ansible.com/u/Nick)\
**Post date:** [September 9, 2013, 8:37pm UTC](https://forum.ansible.com/t/passing-data-to-roles-via-parameters-without-accidentally-flattening-it/13423/9 "2013-09-09T20:37:10Z")

</div>

I confess I've not tried this, since Michael says the dollar is required.

N

---

<div class="post-metadata">

**Author:** ![Nick](https://avatars.discourse-cdn.com/v4/letter/n/f9ae1b/32.png) [@Nick](https://forum.ansible.com/u/Nick)\
**Post date:** [September 9, 2013, 8:52pm UTC](https://forum.ansible.com/t/passing-data-to-roles-via-parameters-without-accidentally-flattening-it/13423/10 "2013-09-09T20:52:23Z")

</div>

Hi,

---

<div class="post-metadata">

**Author:** ![Nick](https://avatars.discourse-cdn.com/v4/letter/n/f9ae1b/32.png) [@Nick](https://forum.ansible.com/u/Nick)\
**Post date:** [September 13, 2013, 10:59am UTC](https://forum.ansible.com/t/passing-data-to-roles-via-parameters-without-accidentally-flattening-it/13423/11 "2013-09-13T10:59:00Z")

</div>

Hi,

I've been converting more of my older playbooks to the new brace expansion syntax, I've found another case where dollar expansion succeeds to do something which braces don't: variable names with leading numerals. In my case a variable was called 'something.3rd\_party\_rpms', and converting to the new syntax made a working playbook fail.

I'm not clear if this is a bug, rather I suspect it's a consequence of Jinja2's Pythonesque syntax, which I think disallows leading numeral identifiers for variable names. However, documentation on this would benefit those of us converting from the older syntax. If someone who knows can confirm whether or not these cases are how it is meant to be, given a spare moment I may provide a documentation patch.

In addition I notice that error\_on\_undefined\_vars does not spot these defined-but-unexpanded vars with leading numerals.

And as I mention elsewhere, checking this shows another surprising difference, which is that undefined dollar expansions don't seem to be caught at all when error\_on\_undefined\_vars = True.

Here's a test playbook:

---# test.yml  
- name: test moustache vs dollar expansion  
&nbsp;&nbsp;&nbsp;hosts: all  
&nbsp;&nbsp;&nbsp;user: root

&nbsp;&nbsp;&nbsp;vars:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foo1: /foo1  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foo:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bar: /foo/bar  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3bar: /foo/3bar

&nbsp;&nbsp;&nbsp;tasks:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- name: what is foo1?  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;action: debug msg="{{foo1}} ${foo1}"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# prints "/foo1 /foo1"

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- name: what is foo.bar?  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;action: debug msg="{{foo.bar}} ${foo.bar}"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# prints "/foo/bar /foo/bar"

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- name: what is foo.3bar?  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;action: debug msg="{{foo.3bar}} ${foo.3bar}"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# prints "{{foo.3bar}} /foo/bar",  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# even if error\_on\_undefined\_vars = True!

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- name: what is foo.nonesuch?  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;action: debug msg="${foo.nonesuch}"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# prints "${foo.nonesuch}",  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# even if error\_on\_undefined\_vars = True!

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- name: what is foo.nonesuch?  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;action: debug msg="{{foo.nonesuch}}"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# this does trigger an error if error\_on\_undefined\_vars = True!

Run like this:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ansible-playbook -l localhost -c local -v test.yml

Gives:

GATHERING FACTS

---

<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:** [September 13, 2013, 1:26pm UTC](https://forum.ansible.com/t/passing-data-to-roles-via-parameters-without-accidentally-flattening-it/13423/12 "2013-09-13T13:26:35Z")

</div>

You should never define a variable name with a leading numeral, as it’s not a valid Python variable name.

---

<div class="post-metadata">

**Author:** ![Brian\_Coca1](https://avatars.discourse-cdn.com/v4/letter/b/278dde/32.png) [@Brian\_Coca1](https://forum.ansible.com/u/Brian_Coca1)\
**Post date:** [September 13, 2013, 2:18pm UTC](https://forum.ansible.com/t/passing-data-to-roles-via-parameters-without-accidentally-flattening-it/13423/13 "2013-09-13T14:18:27Z")

</div>

most of us never try this as most programming languages don’t like variables that way.

---

<div class="post-metadata">

**Author:** ![Nick](https://avatars.discourse-cdn.com/v4/letter/n/f9ae1b/32.png) [@Nick](https://forum.ansible.com/u/Nick)\
**Post date:** [September 13, 2013, 4:08pm UTC](https://forum.ansible.com/t/passing-data-to-roles-via-parameters-without-accidentally-flattening-it/13423/14 "2013-09-13T16:08:12Z")

</div>

Just to clarify: is the following referencing variables inside other datastructures?

--- # vars.yml  
foo:  
&nbsp;&nbsp;&nbsp;base: /some/path  
path: '{{ foo.base }}/filename'

(Works as expected to set path to "/some/path/filename")

How about this?

--- # vars.yml  
foo:  
&nbsp;&nbsp;&nbsp;base: /some/path  
&nbsp;&nbsp;&nbsp;path: '{{ foo.base }}/filename'

(Ansible gives an error: "recursive loop detected in template string: {{foo.base}}/filename".)

How about this?

--- # vars.yml  
foo:  
&nbsp;&nbsp;&nbsp;base: /some/path  
&nbsp;&nbsp;&nbsp;path: '${foo.base}/filename'

(Works as expected to set path to "/some/path/filename")

My point is, when dollar variables are no longer supported in Ansible, will we be unable to express the second case?

N

---

<div class="post-metadata">

**Author:** ![Nick](https://avatars.discourse-cdn.com/v4/letter/n/f9ae1b/32.png) [@Nick](https://forum.ansible.com/u/Nick)\
**Post date:** [September 13, 2013, 4:11pm UTC](https://forum.ansible.com/t/passing-data-to-roles-via-parameters-without-accidentally-flattening-it/13423/15 "2013-09-13T16:11:19Z")

</div>

I do know that about Python variables. I also know that these are valid YAML identifiers, and valid Python dictionary keys too.

So it's not clear-cut which rules apply to Ansible vars, which behave a lot like keys in a nested dictionary. Ansible's docs should say but don't seem to - or perhaps I just haven't found that bit.

I'm suggesting Ansible should:

&nbsp;&nbsp;- Document what is allowed, and what is advised, in terms of variable names, especially when the rules change (as in this case).

&nbsp;&nbsp;- Warn the user when he or she breaks the rules / advice (currently, whether I find out is hapazard).

&nbsp;&nbsp;- Implement error\_on\_undefined\_vars checks universally, or document the exceptions (currently the loophole with leading numerals, and dollar vars in general)

These do seem pretty uncontroversial points, I hope. But want to know if you agree, or these are not going to change because of a specific policy, so that I can do the right thing.

Cheers,

N

---

<div class="post-metadata">

**Author:** ![Fred\_Badel](https://avatars.discourse-cdn.com/v4/letter/f/f07891/32.png) [@Fred\_Badel](https://forum.ansible.com/u/Fred_Badel)\
**Post date:** [September 13, 2013, 7:53pm UTC](https://forum.ansible.com/t/passing-data-to-roles-via-parameters-without-accidentally-flattening-it/13423/16 "2013-09-13T19:53:44Z")

</div>

Hi,

I am not sur this is related… but the symptoms are the same.

I have a variable set this way:

asadmin\_cmd: "/path/to/glassfish/bin/asadmin --user admin --passwordfile /path/to/passwordfile"

in my playbook I am trying the following:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- name: disable X-Powered-By  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;shell: "{{ asadmin\_cmd }}" set server.network-config.protocols.protocol.http-listener-1.http.xpowered-by=false

which return the following error message:

ERROR: Syntax Error while loading YAML script, ….

If I try :

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- name: disable X-Powered-By  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;shell: ${asadmin\_cmd} set server.network-config.protocols.protocol.http-listener-1.http.xpowered-by=false

everything runs smoothly.

Fred

---

<div class="post-metadata">

**Author:** ![Nick](https://avatars.discourse-cdn.com/v4/letter/n/f9ae1b/32.png) [@Nick](https://forum.ansible.com/u/Nick)\
**Post date:** [September 13, 2013, 8:27pm UTC](https://forum.ansible.com/t/passing-data-to-roles-via-parameters-without-accidentally-flattening-it/13423/17 "2013-09-13T20:27:13Z")

</div>

The error looks like it from the YAML parser, implying Ansible hasn't even had a  
chance of interpreting the data yet.

I believe it's the quotes. If I paste your definitions into a test playbook and  
put quotes around "${ asadmin\_cmd }" I get the same sort of YAML error. YAML  
apparently wants the quotes to enclose the whole value, and not just a portion.  
Quoting the whole value works:

shell: "{{ asadmin\_cmd }} set server.network-config.protocols.protocol.http-listener-1.http.xpowered-by=false"

N

---

<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:** [September 13, 2013, 11:07pm UTC](https://forum.ansible.com/t/passing-data-to-roles-via-parameters-without-accidentally-flattening-it/13423/18 "2013-09-13T23:07:48Z")

</div>

Yep, this is just a parser issue.

If you start a line with a quote, you have to make sure that quote applies to the whole line.

I agree this is a little confusing.

In previous thread we discussed including some built-in YAML parser error detection that would better explain this, and how to fix it, and on what line numbers the errors were so you didn’t see a traceback.

Something I hope we can add in the next release or two.

---

<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:** [September 13, 2013, 11:12pm UTC](https://forum.ansible.com/t/passing-data-to-roles-via-parameters-without-accidentally-flattening-it/13423/19 "2013-09-13T23:12:07Z")

</div>

I should mention what you are doing appears to be because you’re trying to namespace variables.

In Ansible 1.3,you no longer have to, because it’s guaranteed any variable you have defined in a role comes will be used in that role.

Thus it’s easier to just define everything flat if you want.

I agree we should document that variables shouldn’t contain dashes.

I’m not sure what you mean about error\_on\_undefined not picking up everything, but I certaintly believe that it’s possible that it’s not 100% yet, patches or examples would be great – please file specific tickets in github about what error\_on\_undefined is not picking up so we don’t miss this.

---

<div class="post-metadata">

**Author:** ![Fred\_Badel](https://avatars.discourse-cdn.com/v4/letter/f/f07891/32.png) [@Fred\_Badel](https://forum.ansible.com/u/Fred_Badel)\
**Post date:** [September 14, 2013, 2:07pm UTC](https://forum.ansible.com/t/passing-data-to-roles-via-parameters-without-accidentally-flattening-it/13423/20 "2013-09-14T14:07:00Z")

</div>

Hi Nick, Mike,

Thank you for the tip, quoting the all line does indeed suppress the error message.  
I suspected I was missing some subtleties here 🙂

I was referring to the [http://www.ansibleworks.com/docs/YAMLSyntax.html#gotchas](http://www.ansibleworks.com/docs/YAMLSyntax.html#gotchas) page which explain that a value after a colon that start with { needs to be quoted … but did not get that the all line was concerned.

Thanks again for your help.

fred

[Next page](https://forum.ansible.com/t/passing-data-to-roles-via-parameters-without-accidentally-flattening-it/13423.md?page=2)
