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 如果有的话。