在Ansible中解析JSON响应并为字典动态追加新项
如何在Ansible中将OpenStack Flavor ID关联到对应服务器字典?
原Playbook代码
- name: Create new instances hosts: localhost gather_facts: false vars: new_instances: test_server1: datacenter: "paris" type: "A1" test_server2: datacenter: "london" type: "B1" test_server3: datacenter: "frankfurt" type: "C1" tasks: - name: Retrieve Openstack Flavor info openstack.cloud.compute_flavor_info: auth: auth_url: <secret> username: <secret> password: <secret> project_id: <secret> name: "{{ item.value.type }}" region_name: "{{ item.value.datacenter }}" with_dict: "{{ new_instances }}" register: flavor_output - debug: msg: "{{ flavor_output }}"
执行Playbook后的响应
ok: [localhost] => { "msg": { "changed": false, "msg": "All items completed", "results": [ { "ansible_loop_var": "item", "changed": false, "failed": false, "flavors": [ { "description": null, "disk": 50, "ephemeral": 0, "id": "DptkedSp2f3YhZmLTYLFBf3t", "is_disabled": false, "is_public": true, "name": "A1", "original_name": null, "ram": 7000, "rxtx_factor": 1.0, "swap": "", "vcpus": 2 } ], "item": { "key": "test_server1", "value": { "datacenter": "paris", "type": "A1" } } }, { "ansible_loop_var": "item", "changed": false, "failed": false, "flavors": [ { "description": null, "disk": 50, "ephemeral": 0, "id": "W2YcNHm9ZHMfzcP3T3WPjsmm", "is_disabled": false, "is_public": true, "name": "B1", "original_name": null, "ram": 7000, "rxtx_factor": 1.0, "swap": "", "vcpus": 2 } ], "item": { "key": "test_server2", "value": { "datacenter": "london", "type": "B1" } } }, { "ansible_loop_var": "item", "changed": false, "failed": false, "flavors": [ { "description": null, "disk": 100, "ephemeral": 0, "id": "drTdyFXRCKsxLy6kjJwKuZmR", "is_disabled": false, "is_public": true, "name": "C1", "original_name": null, "ram": 15000, "rxtx_factor": 1.0, "swap": "", "vcpus": 4 } ], "item": { "key": "test_server3", "value": { "datacenter": "frankfurt", "type": "C1" } } } ], "skipped": false } }
当前尝试的方法及问题
使用json_query提取Flavor ID:
- debug: msg: "{{ flavor_output | json_query('results[*].flavors[*].id') }}"
返回结果仅包含ID列表,无法关联到具体服务器:
ok: [localhost] => { "msg": [ [ "DptkedSp2f3YhZmLTYLFBf3t" ], [ "W2YcNHm9ZHMfzcP3T3WPjsmm" ], [ "drTdyFXRCKsxLy6kjJwKuZmR" ] ] }
最终目标
将每台服务器对应的Flavor ID追加到new_instances字典中,最终格式如下:
new_instances: test_server1: datacenter: "paris" type: "A1" flavor_id: "DptkedSp2f3YhZmLTYLFBf3t" test_server2: datacenter: "london" type: "B1" flavor_id: "W2YcNHm9ZHMfzcP3T3WPjsmm" test_server3: datacenter: "frankfurt" type: "C1" flavor_id: "drTdyFXRCKsxLy6kjJwKuZmR"
解决方案
通过set_fact结合循环和字典合并实现需求:
1. 提取服务器与Flavor ID的映射关系
- name: Extract flavor IDs with server names set_fact: flavor_id_map: >- {{ flavor_id_map | default({}) | combine({ item.item.key: item.flavors.0.id }) }} loop: "{{ flavor_output.results }}"
2. 将Flavor ID追加到原服务器字典
- name: Update new_instances with flavor IDs set_fact: new_instances: >- {{ new_instances | combine({ item.key: item.value | combine({ 'flavor_id': flavor_id_map[item.key] }) }) }} loop: "{{ new_instances | dict2items }}"
3. 验证最终结果
- name: Show updated new_instances debug: var: new_instances
完整Playbook示例
- name: Create new instances hosts: localhost gather_facts: false vars: new_instances: test_server1: datacenter: "paris" type: "A1" test_server2: datacenter: "london" type: "B1" test_server3: datacenter: "frankfurt" type: "C1" tasks: - name: Retrieve Openstack Flavor info openstack.cloud.compute_flavor_info: auth: auth_url: <secret> username: <secret> password: <secret> project_id: <secret> name: "{{ item.value.type }}" region_name: "{{ item.value.datacenter }}" with_dict: "{{ new_instances }}" register: flavor_output - name: Extract flavor IDs with server names set_fact: flavor_id_map: >- {{ flavor_id_map | default({}) | combine({ item.item.key: item.flavors.0.id }) }} loop: "{{ flavor_output.results }}" - name: Update new_instances with flavor IDs set_fact: new_instances: >- {{ new_instances | combine({ item.key: item.value | combine({ 'flavor_id': flavor_id_map[item.key] }) }) }} loop: "{{ new_instances | dict2items }}" - name: Show updated new_instances debug: var: new_instances
说明
flavor_id_map:循环flavor_output.results,将服务器名称与对应Flavor ID组合成映射字典,其中item.flavors.0.id是因为返回的flavors是单元素列表,直接取第一个元素的ID。- 字典合并:使用
dict2items将原new_instances转为列表格式,循环每个服务器条目,通过combine将flavor_id键值对追加到对应服务器的子字典中,再合并回原字典结构。
内容的提问来源于stack exchange,提问作者Tony
相关产品推荐
相关产品推荐

