Ansible将include_vars包含的变量合并到字典中。

5
在我的Ansible剧本中,我读取一个目录列表到一个列表中。然后,我想从这些目录中的每个目录读取一个名为“config.yml”的文件,并将它们的内容放入字典中,以便我可以通过该字典中的目录名称引用配置数据。 第一部分没有问题,但我无法使第二部分工作:
步骤1:加载目录:
- name: Include directories
  include_vars:
  file: /main-config.yml
  name: config

第二步,从目录中加载配置:
- name: load deploymentset configurations
  include_vars:
    file: /path/{{ item }}/config.yml
    name: "allconfs.{{ item }}"   ## << This is the problematic part 
  with_items:
    - "{{ config.dirs }}"

我尝试了不同的方法,例如"allconfs['{{ item }}'],但似乎都不起作用。Playbook已成功完成,但数据未出现在字典中。 我还尝试预先定义外部字典,但也没有起作用。

配置文件本身非常简单:

/main-config.yml:

dirs:
- dir1
- dir2
- dir3

/path/dir1/config.yml:

some_var: "some_val"
another_var: "another val"

我希望能够像这样访问config.yml文件的值:

{{ allconfs.dir1.some_var }}

更新尝试Konstantins的方法:

  - name: load deploymentset configurations
    include_vars:
      file: /repo/deploymentsets/{{ item }}/config.yml
      name: "default_config"
    with_items:
    - "{{ config.deploymentsets }}"
    register: default_configs


  - name: combine configs
    set_fact:
      default_configs: "{{ dict(default_configs.results | json_query('[].[item, ansible_facts.default_config]')) }}"

错误信息:

致命错误: [127.0.0.1]: 失败! => {"failed": true, "msg": "在({{ dict(default_configs.results | json_query('[].[item, ansible_facts.default_config]')) }}) 上出现了意外的模板类型错误: <lambda>()接受0个参数,但实际传入了1个"}


你能否提供/main-config.yml/path/{{ item }}/config.yml的示例? - kfreezy
请详细说明为什么要进行负评,因为这个问题很明确,包含所有相关的代码,并且不是重复的。 - feob
2个回答

5
这是我其中一个项目中的一段代码,具有类似的功能:
- name: Load config defaults
  include_vars:
    file: "{{ item }}.yml"
    name: "default_config"
  with_items: "{{ config_files }}"
  register: default_configs
  tags:
    - configuration

- name: Combine configs into one dict
  # Здесь мы делаем словарь вида
  # default_configs:
  #   config_name_1: { default_config_object }
  #   config_name_2: { default_config_object }
  #   config_name_3: { default_config_object }
  #   ...
  set_fact:
    default_configs: "{{ dict(default_configs.results | json_query('[].[item, ansible_facts.default_config]')) }}"
  tags:
    - configuration

default_config 是一个临时加载变量数据的虚拟变量。
关键在于使用 register: default_configs 以及 include_vars,并通过以下任务解析它并剥离不必要的字段。


看起来很有前途,但我收到了“在({{ dict(conf_reg.results | json_query('[].[item, ansible_facts.default_config]')) }})上发生了意外的模板类型错误:<lambda>()需要0个参数(给定了1个)”这个错误。你能展示一个配置文件的例子吗? - feob
这是任意的YAML文件。我看到你把default_configs替换成了conf_reg,如果你也替换了default_config占位符,请相应地更新JSON查询。 - Konstantin Suvorov
我已经改回您提供的名称,但仍然出现错误。我在上面发布了我的确切代码。 - feob
这是一个可工作的示例:https://gist.github.com/berlic/bedf6024ca9aa327ae15f65412c37668。你使用的Ansible版本是什么? - Konstantin Suvorov
事实上,通过升级 jinja2 库(仍为 2.7 版本),我已经成功解决了这个错误:pip install jinja2 --upgrade - feob

1
据我所知,不可能创建一个包含多个include_vars的单一字典。根据我的测试,它会为每个包含的目录创建单独的字典。以下是您可以做的替代方法。
从变量名称中删除allconfs。
- name: load deploymentset configurations
  include_vars:
    file: /path/{{ item }}/config.yml
    name: "{{ item }}"
  with_items:
    - "{{ config.dirs }}"

你可以直接访问变量,方式如下:
debug:
  msg: "{{ dir1.some_var }}"
with_items: "{{ config.dirs }}"

如果您需要循环遍历所包含目录中的所有变量,请使用以下方法(从Ansible:如何从另一个变量构造变量,然后获取其值中提取)。

debug:
  msg: "{{ hostvars[inventory_hostname][item].some_var }}"
with_items: "{{ config.dirs }}"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接