Reputation: 41
I am trying to read a YML file from a remote node in Ansible and make modifications and update it.
When I use "from_yaml" Jinja filter, I notice that the keys are sorted and when I update the file on remote, it will cause issues.
Is there a way to set Sort_Keys=False on the from_yaml filter?
Original file:
key1:
key5:
key3: value3
key2:
key5: value4
key6:
key7: value5
After applying "from_yaml" filter (the keys are sorted):
key1:
key2:
key3: value3
key5:
key5: value4
key6:
key7: value5
Upvotes: 1
Views: 1041
Reputation: 68044
YAML standard says that there is no order of keys in a dictionary. Python3 recently(I don't remember the version. Probably 3.6 or 3.7. You can find it in the release notes.) introduced ordered keys in dictionaries. This is what you see as a result of the filter from_yaml. You'll see the dictionary also ordered without any filter when Ansible uses recent Python3. For example,
- hosts: localhost
vars:
key1:
key5:
key3: value3
key2:
key5: value4
key6:
key7: value5
tasks:
- debug:
var: key1
gives (abridged)
key1:
key2:
key5: value4
key5:
key3: value3
key6:
key7: value5
But, Jinja, even when using Python3.8, doesn't sort the dictionaries (I don't know why). For example,
- debug:
msg: |
{% for k,v in key1.items() %}
{{ k }}: {{ v }}
{% endfor %}
gives (abridged)
msg: |-
key5: {'key3': 'value3'}
key2: {'key5': 'value4'}
key6: {'key7': 'value5'}
To answer your question, unfortunately, there is no such option as Sort_Keys=False
. Moreover, in YAML, there is no guarantee in what order the keys of a dictionary are stored. If you want to be sure that you write a dictionary in a specific order you have to keep the list of the keys. For example,
- debug:
msg: |
{% for k in list_of_keys %}
{{ k }}: {{ key1[k] }}
{% endfor %}
vars:
list_of_keys: [key5, key2, key6]
Upvotes: 2
Reputation: 1524
The imported data is organized in the data structure of a dict. In contrast to an array (or list), in which elements are ordered in their position and addressed via an index, the values of a dict are addressed via the respective key. However, you have no possibility to define or influence the order. Ansible always outputs a data structure of a Dict sorted by the keys.
The example you gave is wrong. Because the data structure is not changed even if the output is sorted by keys. key1.key5.key3
still returns the value value3
. But in your example "After applying "from_yaml" filter" this value does not exist anymore, in your case value3
is now under key1.key2.key3
. Your output does not match the output Ansible gives when the from_yaml
filter is applied to said input.
Data file mydata.txt
:
key1:
key5:
key3: value3
key2:
key5: value4
key6:
key7: value5
Ansible Task:
- debug:
msg: "{{ lookup('file', 'mydata.txt') | from_yaml }}"
Output:
TASK [debug] *****************************
ok: [localhost] => {
"msg": {
"key1": {
"key2": {
"key5": "value4"
},
"key5": {
"key3": "value3"
},
"key6": {
"key7": "value5"
}
}
}
}
Upvotes: 1