Reputation: 6459
In my ansible I need to make a rest call to get a rather large json object (which comes in as a dict). Then I need to modify a few fields in the json and repost it to update the status of the components I want to change.
I already have the rest response and I'm trying to figure out how to cleanly modify numerous values. My current attempt looks like this (simplified a little):
- name: update locations for remote processor
set_fact:
request: "{{ response.json | combine(item)}}"
loop:
- { 'component': { 'targetUri': "{{remoteProcessorUri}}"
- { 'component': { 'targetUris': "{{remoteProcessorUri}}"
...
Unfortunately while this does change the request, it replaces the larger component dict with an dict that only contains targetUri, all the other content that was in component was erased where as I want to keep it and only modify targetUri.
I tried a variant where my loop had a location and a value field for each item, but I can't get the location field syntax right to be able to replace response.json with item.location.
So how can I create this to make it easy, and readable, to make various changes across my dict without changing anything other then the specific subfields I call out?
Upvotes: 0
Views: 1247
Reputation: 6459
Turns out I had it almost correct. All I needed was to add the recursive=true option to the combine filter. so...
- name: update locations for remote processor
set_fact:
request: "{{ response.json | combine(item, recursive=True)}}"
loop:
- { 'component': { 'targetUri': "{{remoteProcessorUri}}"
- { 'component': { 'targetUris': "{{remoteProcessorUri}}"
...
Upvotes: 1
Reputation: 33158
Dictionaries are "live" in ansible/jinja2, in that you can modify them in-place using most of the python dict methods, with the only caveat that you have to echo the whole structure back out in a set_fact:
to "save" the changes
tasks:
- set_fact:
example1:
{
"some": {
"key": {
"ansible_python": {
"executable": "/usr/local/opt/[email protected]/bin/python3.9",
"has_sslcontext": true,
"type": "cpython",
"version": {
"major": 3,
"micro": 5,
"minor": 9,
"releaselevel": "final",
"serial": 0
},
"version_info": [
3,
9,
5,
"final",
0
]
}
}
}
}
- set_fact:
example1: >-
{%- set _ = example1.some.key.ansible_python.version.update({
"a_new_key": "yup",
"mojor": 9999,
}) -%}
{{ example1 }}
- debug:
var: example1.some.key.ansible_python.version
produces
ok: [localhost] => {
"example1.some.key.ansible_python.version": {
"a_new_key": "yup",
"major": 3,
"micro": 5,
"minor": 9,
"mojor": 9999,
"releaselevel": "final",
"serial": 0
}
}
That {% set _ = ... %}
business is because the jinja2 versions bundled with ansible don't seem to support the do
operator from jinja2, so the only way to get a method with side-effects is to have it be on the right side of an assignment operator, and just throw away the result
Upvotes: 0