Literal scalar expands to a dictionary

107 views
Skip to first unread message

Vladimir Botka

unread,
Jan 5, 2022, 5:21:58 AM1/5/22
to Ansible Project
For example, given "val1: foo"

- set_fact:
_var1: |
{"key1": "{{ val1 }}"}
_var2: |
{"key1": "foo"}
- debug:
var: _var1|type_debug
- debug:
var: _var2|type_debug

gives

_var1|type_debug: dict
_var2|type_debug: AnsibleUnicode

*_var1* expands to a dictionary but *_var2* expands to a string. Is it
a feature or a bug?

Thank you,

--
Vladimir Botka

Matt Martz

unread,
Jan 5, 2022, 11:10:34 AM1/5/22
to ansible...@googlegroups.com
#1 from this response explains why this happens:


If the value contains a variable, it is processed through Templar.template
  a. Templar.template is powered by jinja2, and historically only has the ability to return strings
  b. Because jinja2 has historically only had the ability to template strings, we do some magic to try and convert strings that look like python data structures to python data structures
  c. The string now becomes a python dictionary

You can work around this, although it's a bit more complex:

    - set_fact:
        _var1: |
          {{ ('{"key1": "' ~ val1 ~ '"}') | string }}


There are likely some other variants on my example.


--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/20220105112142.22faded9%40gmail.com.


--
Matt Martz
@sivel
sivel.net

Vladimir Botka

unread,
Jan 5, 2022, 11:24:52 AM1/5/22
to Matt Martz, ansible...@googlegroups.com
On Wed, 5 Jan 2022 10:09:45 -0600
Matt Martz <ma...@sivel.net> wrote:

> > For example, given "val1: foo"
> >
> > - set_fact:
> > _var1: |
> > {"key1": "{{ val1 }}"}
> > _var2: |
> > {"key1": "foo"}
> > - debug:
> > var: _var1|type_debug
> > - debug:
> > var: _var2|type_debug
> >
> > gives
> >
> > _var1|type_debug: dict
> > _var2|type_debug: AnsibleUnicode
> >
> > *_var1* expands to a dictionary but *_var2* expands to a string. Is it
> > a feature or a bug?

> b. Because jinja2 has historically only had the ability to template
> strings, we do some magic to try and convert strings that look like python
> data structures to python data structures

Why don't you try this magic consistently both on jinja2 and
non-jinja2 expressions?

Matt Martz

unread,
Jan 5, 2022, 2:39:09 PM1/5/22
to Vladimir Botka, ansible...@googlegroups.com
I believe that was explained.  The "magic" as you call it, only affects jinja2 templating, because historically jinja2 could only ever generate strings, but the intention was often to generate python data types.

We don't do that for things that don't go through templating, because the author can define it explicitly as the type they want.

Vladimir Botka

unread,
Jan 5, 2022, 5:58:58 PM1/5/22
to ansible...@googlegroups.com, Matt Martz
On Wed, 5 Jan 2022 13:38:18 -0600
Matt Martz <ma...@sivel.net> wrote:

> > > > For example, given "val1: foo"
> > > >
> > > > - set_fact:
> > > > _var1: |
> > > > {"key1": "{{ val1 }}"}
> > > > _var2: |
> > > > {"key1": "foo"}
> > > > - debug:
> > > > var: _var1|type_debug
> > > > - debug:
> > > > var: _var2|type_debug
> > > >
> > > > gives
> > > >
> > > > _var1|type_debug: dict
> > > > _var2|type_debug: AnsibleUnicode
> > > >
> > > > *_var1* expands to a dictionary but *_var2* expands to a string. Is it
> > > > a feature or a bug?

> > > b. Because jinja2 has historically only had the ability to template
> > > strings, we do some magic to try and convert strings that look like
> > > python data structures to python data structures

> > Why don't you try this magic consistently both on jinja2 and
> > non-jinja2 expressions?

> I believe that was explained. The "magic" ..., only affects jinja2
> templating, because historically jinja2 could only ever generate
> strings, but the intention was often to generate python data types.
> We don't do that for things that don't go through templating,
> because the author can define it explicitly as the type they want.


Thank you. I try to understand the logic. In summary (up till now),

"The magic only affects jinja2 templating; to try and convert
strings that look like python data structures to python data
structures."

How do you decide what looks like python data structure? For example,
only the second string below is converted to dictionary, despite the
fact that both are valid YAML dictionaries

- set_fact:
_var3: '{"key1": {{ val1 }}}'
_var4: '{"key1": "{{ val1 }}"}'
- debug:
var: _var3|type_debug
- debug:
var: _var3|from_yaml|type_debug
- debug:
var: _var4|type_debug

gives

_var3|type_debug: str
_var3|from_yaml|type_debug: dict
_var4|type_debug: dict

--
Vladimir Botka
Reply all
Reply to author
Forward
0 new messages