我有一本使用两个var文件的Ansible剧本;一个用于一般属性,其他用于我特定属性。但是,两个文件中都有一些属性共享相同的根YAML根结构(aws.ec2
),但是当我运行剧本时,似乎这些属性不会合并到一棵树中,但是最后列出的文件会覆盖前一个文件对于使用aws.ec2
的任何道具。
剧本
- name: Play 1. Create AWS Environment
hosts: localhost
vars_files:
- var_files/aws_management_vars.yml
- var_files/aws_general_vars.yml
aws_management_vars.yml
aws:
ec2:
node:
name: "Management Node"
instance_type: "t2.micro"
...
aws_general_vars.yml
aws:
region: us-west-1
ec2:
env: mih-env
vpc_id: vpc-abc12345
...
运行剧本时,如果我按此顺序有vars文件,它会抱怨找不到aws.ec2.node
。
"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'node'
如果我调换订单,它会抱怨找不到aws.region
。
"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'region'
这是vars_files
的限制吗?还有什么我可以使用的东西,它们可以解析yml文件并合并具有相同结构的属性?我知道我可以重命名文件中的结构,但是如果可能的话,我希望它保持这种方式。
Ansible v2.7.8
答案 0 :(得分:0)
Q:“这是vars_files的限制吗?我可以使用哪些方法来解析yml文件并合并具有相同结构的属性?”
A:是的。这是vars_files
的限制。 控制变量的合并方式是可能的。参见DEFAULT_HASH_BEHAVIOUR。但这不推荐。引用:“ 通常,除非您认为您绝对需要此设置,否则我们建议您不要使用此设置。”
有一个简单的解决方案。使用include_vars
,将包含的数据放入字典,然后combine
。设置recursive=True
以合并键。例如
- include_vars:
file: var_files/aws_management_vars.yml
name: management
- include_vars:
file: var_files/aws_general_vars.yml
name: general
- set_fact:
my_vars: "{{ management|combine(general, recursive=True) }}"
- debug:
var: my_vars.aws
给予
my_vars.aws:
ec2:
env: mih-env
node:
instance_type: t2.micro
name: Management Node
vpc_id: vpc-abc12345
region: us-west-1
Q:“ include_vars抱怨无法在剧本级别使用它。我需要将其添加到剧本中正在运行的所有任务的顶部吗?”
A:是的。 include_vars
是一项任务。将其放在任务的顶部。参见Variable precedence。 include_vars
(优先级18)将覆盖任务,块和角色的变量(17,16,15)。将其放在任务的顶部时,include_vars
和vars_files
之间几乎没有区别(优先级14)。因此,请使用include_role代替roles(如果有)。