Ansible:具有相同 yaml 结构的多个 vars_files 不合并
Ansible: multiple vars_files with same yaml structure do not merge
我有一个使用两个 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
...
当我 运行 我的 playbook 时,如果我在此处的顺序中有 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
Q: "Is this a limitation of vars_files? What can I use that will parse the yml files and merge properties that have the same structure?"
答:是的。这是 vars_files
的限制。可以控制变量如何合并。参见 DEFAULT_HASH_BEHAVIOUR。但不推荐。引用:“我们通常建议不要使用此设置,除非您认为绝对需要它。”
有一个简单的解决方案。使用 include_vars
, put the included data into dictionaries, and 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 complained that it cannot be used at playbook level. Would I need to add this to the top of all tasks being run in a playbook?"
答:是的。 include_vars
是一个任务。把它放在任务的顶部。见 Variable precedence. include_vars
(precedence 18.) will overwrite task's, block's and roles' vars (17,16,15). When putting it into the top of the tasks, then there is practically no difference between include_vars
and vars_files
(precedence 14). As a consequence, use include_role instead of roles 如果有的话。
我有一个使用两个 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
...
当我 运行 我的 playbook 时,如果我在此处的顺序中有 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
Q: "Is this a limitation of vars_files? What can I use that will parse the yml files and merge properties that have the same structure?"
答:是的。这是 vars_files
的限制。可以控制变量如何合并。参见 DEFAULT_HASH_BEHAVIOUR。但不推荐。引用:“我们通常建议不要使用此设置,除非您认为绝对需要它。”
有一个简单的解决方案。使用 include_vars
, put the included data into dictionaries, and 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 complained that it cannot be used at playbook level. Would I need to add this to the top of all tasks being run in a playbook?"
答:是的。 include_vars
是一个任务。把它放在任务的顶部。见 Variable precedence. include_vars
(precedence 18.) will overwrite task's, block's and roles' vars (17,16,15). When putting it into the top of the tasks, then there is practically no difference between include_vars
and vars_files
(precedence 14). As a consequence, use include_role instead of roles 如果有的话。