I do some tests with json file and I have seen that I don't understand its behaviour, is it normal or a bug?
My json file:
{
"interfaces": {
"GigabitEthernet0/0": {
"duplex_code": "auto",
"port_speed": "a-100",
"status": "connected",
"type": "10/100/1000BaseTX",
"vlan": "1"
}
}
}
Tasks:
- name: load the Json data to a Variable as a Fact
command: cat "{{ _jsonfile }}"
vars:
_jsonfile: 'file.json'
register: output
- name: output is string
debug: msg="output is string"
when: output is string
- name: output.stdout is string
debug: msg="output.stdout is string"
when: output.stdout is string
- set_fact:
out: "{{ output.stdout }}"
- name: out is string
debug: msg="out is string"
when: out is string
As you could see, I load a JSON with a cat
command and check if the registered output an output.stdout
are strings.
The result:
TASK [**output is string**] *********************************************
Friday 29 October 2021 15:15:35 0000 (0:00:00.347) 0:00:00.412 ********
**skipping**: [localhost]
TASK [**output.stdout is string**] *****************************************************************
Friday 29 October 2021 15:15:36 0000 (0:00:00.028) 0:00:00.440 ********
ok: [localhost] =>
**msg: output.stdout is string**
TASK [set_fact] **************************************************************************
Friday 29 October 2021 15:15:36 0000 (0:00:00.029) 0:00:00.470 ********
ok: [localhost]
TASK [**out is string**] *********************************************************************
Friday 29 October 2021 15:15:36 0000 (0:00:00.031) 0:00:00.502 ********
**skipping: [localhost]**
output.stdout
is a string, it's normal, but when I trap output.stdout
in another variable, named out
,
this variable is not a string, but a dictionary that I can iterate out.interfaces
, so, I'd like to understand that.
Is it normal that the type of a variable changes with new affectation?
CodePudding user response:
Yes, that's actually very common ansible behavior, auto-coercing things to dict
or list
— it thinks that's "helping" you.
To stop that behavior, you can just make the first character not one of the JSON-y ones, and it'll leave it a string, or usually explicitly sending the pipeline through | string
works, too, if the leading whitespace is important to some downstream task:
- set_fact:
out: " {{ output.stdout }}"
- set_fact:
out: "{{ output.stdout | string }}"
Just watch out, because — just like the presence of jinja2 moustaches — ansible applies those coercion rules anytime it can, so one must be especially careful as text travels through the various evaluation pipelines