英文:
Ansible: How to update or change a value in a nested dictionary from a REST API call?
问题
在这个播放书中,我正在使用uri
模块进行调用,注册一个名为result
的变量。
result.json
看起来像这样:
{
"global_api_concurrency_limit": 199,
"client_api_rate_limit": 100,
"client_api_concurrency_limit": 40,
"connection_timeout": 30,
"redirect_host": "",
"protocol_versions": [
{"enabled": true, "name": "TLSv1.1"},
{"enabled": true, "name": "TLSv1.2"}
]
}
我通过result.json | type_debug
检查它,并显示它是一个字典。
我想要将属性更新为"enabled": false
,其中"name": "TLSv1.1"
。
请注意,JSON中的false
不用引号括起来。所以我的想法是要么创建一个新的字典,要么更新同一个字典。但我不知道如何只更新那个值。
我尝试了下面的任务,但显然没有起作用。
- name: 调用NSXT
vars:
api: "/api/v1/cluster/api-service"
ansible.builtin.uri:
url: "https://server01{{ api }}"
user: user1
password: pwd1
method: GET
force_basic_auth: true
validate_certs: false
headers:
Content-Type: application/json
register: result
- set_fact:
newdic: "{{ (newdic | d([])) | combine(new_item, recursive=True) }}"
with_dict: "{{ result.json }}"
vars:
new_item: {'enabled': false}
when: item.protocol_versions.name == 'TLSv1.1'
有没有什么建议来改进这个?(注意:我不想安装jmespath
进行JSON查询,因为公司有限制。)
我无法弄清楚如何只更新嵌套字典中的一个值?
英文:
I had search in a few forums including this one, but none of them seems to be able to provide the solution for me. In the playbook, I am doing a call via uri
module that registers a variable: result
.
result.json
looks like this
{
"global_api_concurrency_limit": 199,
"client_api_rate_limit": 100,
"client_api_concurrency_limit": 40,
"connection_timeout": 30,
"redirect_host": "",
"protocol_versions": [
{"enabled": true, "name": "TLSv1.1"},
{"enabled": true, "name": "TLSv1.2"}
]
}
I checked via result.json | type_debug
and says its a dictionary.
I want to update property to "enabled": false
where "name": "TLSv1.1"
.
Noting that false
is not quoted in the JSON. So my idea is to either create a new dict or update the same dict. But I am stuck how I can update only that value.
I attempted the below tasks, but it obviously didn't work.
- name: Call NSXT
vars:
api: "/api/v1/cluster/api-service"
ansible.builtin.uri:
url: "https://server01{{ api }}"
user: user1
password: pwd1
method: GET
force_basic_auth: true
validate_certs: false
headers:
Content-Type: application/json
register: result
- set_fact:
newdic: "{{ (newdic | d([])) | combine(new_item, recursive=True) }}"
with_dict: "{{ result.json }}"
vars:
new_item: {'enabled': false}
when: item.protocol_versions.name == 'TLSv1.1'
Any advise how to improve this? (Note: I don't want to install jmespath
for JSON queries, because of company restrictions)
I couldn't figure out how I can only update one value with that nested dictionary?
答案1
得分: 1
根据您的描述,我想知道是否您可以使用 update_fact 模块 - 更新当前设置的事实?它用于更新变量,其中文档中的一个 示例 似乎与您的情况类似。
根据您提供的示例数据,一个最小的示例 playbook
---
- hosts: localhost
become: false
gather_facts: false
tasks:
- include_vars:
file: result.json
name: result
- ansible.utils.update_fact:
updates:
- path: result.protocol_versions[0]
value: {"enabled": false, "name": "TLSv1.1"}
register: updated
- debug:
var: updated
将产生以下输出
TASK [debug] *************************
ok: [localhost] =>
updated:
changed: true
failed: false
result:
client_api_concurrency_limit: 40
client_api_rate_limit: 100
connection_timeout: 30
global_api_concurrency_limit: 199
protocol_versions:
- enabled: false
name: TLSv1.1
- enabled: true
name: TLSv1.2
redirect_host: ''
如果不清楚 result.protocol_versions
是否包含正确的版本,或者顺序不清楚,也可以定义配置的期望状态。
- ansible.utils.update_fact:
updates:
- path: result.protocol_versions
value: [{"enabled": false, "name": "TLSv1.1"}, {"enabled": true, "name": "TLSv1.2"}]
register: updated
请注意,即使使用 update_fact
模块 - 更新当前设置的事实
变量不会在原地修改,而是由模块返回。
这是预期的行为。
英文:
According your description I wonder if you could use the update_fact module – Update currently set facts? It is intended for updating variables and one of the documented Examples seems to be similar to yours.
Based on your provided sample data, a minimal example playbook
---
- hosts: localhost
become: false
gather_facts: false
tasks:
- include_vars:
file: result.json
name: result
- ansible.utils.update_fact:
updates:
- path: result.protocol_versions[0]
value: {"enabled": false, "name": "TLSv1.1"}
register: updated
- debug:
var: updated
will result into an output of
TASK [debug] *************************
ok: [localhost] =>
updated:
changed: true
failed: false
result:
client_api_concurrency_limit: 40
client_api_rate_limit: 100
connection_timeout: 30
global_api_concurrency_limit: 199
protocol_versions:
- enabled: false
name: TLSv1.1
- enabled: true
name: TLSv1.2
redirect_host: ''
If it is not clear if the result.protocol_versions
will contain the correct versions, of if the order is not clear, it is also possible to define the desired state of the configuration.
- ansible.utils.update_fact:
updates:
- path: result.protocol_versions
value: [{"enabled": false, "name": "TLSv1.1"}, {"enabled": true, "name": "TLSv1.2"}]
register: updated
Please take note that even if using update_fact
module – Update currently set facts
> Variables are not modified in place, instead they are returned by the module.
答案2
得分: 0
- ansible.utils.update_fact:
updates:
- path: "result.json.protocol_versions[{{item}}].enabled"
value: false
loop: "{{ range(result.json.protocol_versions|length) }}"
when: result.json.protocol_versions[{{item}}].name == "TLSv1.1"
register: updated
英文:
Looks like I found the answer, this will update just the row with name=TLSv1.1
- ansible.utils.update_fact:
updates:
- path: "result.json.protocol_versions[{{item}}].enabled"
value: false
loop: "{{ range(result.json.protocol_versions|length) }}"
when: result.json.protocol_versions[{{item}}].name == "TLSv1.1"
register: updated
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论