Ansible变量访问失败:报错'dict object' has no attribute 'globalname'
Ansible加载目录变量报错:'dict object' has no attribute 'globalname'
问题场景
执行的Ansible剧本:
--- - hosts: localhost gather_facts: no vars: var_folder_path: /home/play tasks: - name: Include all yaml files in directories include_vars: dir: "{{ var_folder_path }}/vars" extensions: - 'yaml' - name: "Print Variable Name" shell: echo "{{ item }}" loop: - "{{ global.globalname.property.Name }}" - "{{ S3.secret }}"
/home/play/vars下的变量文件:
example_1.yaml
global: globalname: property: cipher: DEFAULT client: type: dynamic Name: test-run
example_2.yaml
gcp: keyname: sample-run S3: secret: run Resources: false celery: resources: limits: cpu: 5
执行报错:
fatal: [localhost]: FAILED! => {"msg": "'dict object' has no attribute 'globalname'"}
问题原因
使用include_vars的dir参数加载目录下的变量文件时,默认行为是将每个文件的内容封装到一个以文件名(不含扩展名)命名的字典变量中,而非直接将文件内的顶级键导入当前play的命名空间。
具体来说:
example_1.yaml的内容会被存入example_1变量,结构为example_1: {global: {...}}example_2.yaml的内容会被存入example_2变量,结构为example_2: {gcp: {...}, S3: {...}}
直接访问global.globalname会报错,因为当前命名空间中不存在顶级的global变量,你误把封装后的字典结构当成了直接导入的顶级键。
解决方案
有两种方式可以解决这个问题:
方案1:修改变量访问路径,适配默认封装规则
通过文件名对应的变量来访问内部的键:
- name: "Print Variable Name" shell: echo "{{ item }}" loop: - "{{ example_1.global.globalname.property.Name }}" - "{{ example_2.S3.secret }}"
方案2:启用flat: yes参数,直接合并所有顶级键到命名空间
在include_vars任务中添加flat: yes参数,Ansible会跳过按文件名封装的步骤,直接将所有变量文件中的顶级键合并到当前play的命名空间,你就可以按原方式访问变量:
- name: Include all yaml files in directories include_vars: dir: "{{ var_folder_path }}/vars" extensions: - 'yaml' flat: yes
注意:如果多个变量文件中有同名的顶级键,后面加载的文件会覆盖前面的定义。
内容的提问来源于stack exchange,提问作者Eva
相关产品推荐
相关产品推荐

