Ansible任务:从动态属性名中提取列表值的方法
问题描述
我定义了如下Ansible变量:
vars: services: - uncommon_name1: common_field: "somevalue_of_name1" common_field2: "somevalue2" - uncommon_name2: common_field: "somevalue_of_name2" common_field2: "somevalue2"
我需要提取列表中每个对象的common_field值,预期输出如下:
ok: [services] => (item="somevalue_of_name1") ok: [services] => (item="somevalue_of_name2")
我尝试了几种写法(也用with_items替代过loop),但都报错:
- 写法1:
- debug: msg: "{{ item.value.common_field}}" loop: "{{services}}"
报错:
The task includes an option with an undefined variable. The error was: 'list object' has no attribute 'value'
- 写法2:
- debug: msg: "{{ item.value.common_field}}" loop: "{{ services.keys() }}"
报错:
The task includes an option with an undefined variable. The error was: 'list object' has no attribute 'keys'
- 写法3:
- debug: msg: "{{ item[0].common_field}}" loop: "{{ services }}"
报错:
The task includes an option with an undefined variable. The error was: 'list object' has no attribute 'common_field'
当我执行如下任务时:
- debug: msg: "{{ item}}" loop: "{{ services }}"
得到输出:
ok: [service] => (item={'uncommon_name1': {'common_field' :'somevalue_of_name1', 'common_field2':'somevalue2'}} ok: [service] => (item={'uncommon_name2': {'common_field' :'somevalue_of_name2', 'common_field2':'somevalue2'}}
请问在属性名不固定的情况下,如何提取common_field的值?
环境信息:
ansible [core 2.11.6] python version = 3.10.0 (default, Oct 13 2021, 06:45:00) [Clang 13.0.0 (clang-1300.0.29.3)] jinja version = 3.0.2 libyaml = True
解决方案
因为services列表中的每个元素是单键字典(每个item只有一个不固定名称的键),可以通过以下方式提取common_field:
方法1:直接取值(最简洁)
利用Jinja2的字典方法,先获取字典的所有值(每个item仅一个值),取第一个元素后访问common_field:
- debug: msg: "{{ (item.values() | first).common_field }}" loop: "{{ services }}"
方法2:结合loop_control拆分变量
如果需要更清晰的变量命名,可通过loop_control和临时变量实现:
- debug: msg: "{{ service_data.common_field }}" loop: "{{ services }}" loop_control: loop_var: service_item vars: service_data: "{{ service_item.values() | first }}"
错误原因说明
- 写法1错误:
item是原生字典,不是Ansibledict2items过滤后带key/value属性的对象,因此没有value属性。 - 写法2错误:
services是列表类型,列表没有keys()方法,只有字典才有该方法。 - 写法3错误:
item是字典,不是列表,无法用item[0]索引,需先转换为值列表再索引。
内容的提问来源于stack exchange,提问作者janithcooray
相关产品推荐
相关产品推荐

