Ansible 从文件中获取类似字典的值到剧本或循环

问题描述

我正在寻找一种在遍历循环时从文本、yaml 或 json 文件获取值的方法

我的代码正在运行,因为我正在使用 loop 迭代哈希列表,但问题是当我有多个条目要迭代时,这就是我想将所有这些值放入一个文件的原因然后在任务/剧本中调用它们,而不是在剧本中写一堆行。

请提出建议或帮助通过它..

以下是工作代码

---
- hosts: localhost
  gather_facts: no

  vars:
    config: "{{ playbook_dir }}/{{ config_file }}"
    contents: "{{lookup('file',config)}}"
    server_profile_template: 'Test_apc_SY 480 Gen10 2 NVMe Application Template 20190601 V1.0'
    server_hardware: "SY 480 Gen9 1"
    template_name: []
    server_list: []

  tasks:
    - name: Create server profile
      oneview_server_profile:
        config: "{{ config }}"
        data:
          serverProfileTemplateName: "{{ server_profile_template }}"
          serverHardwareName: "{{ item.Bay }}"
          name: "{{ item.Profilename }}"
        params:
          force: True
      loop:
        - { Bay: "ENT0005,bay 11",Profilename: "test_profile01" }
        - { Bay: "ENT0005,bay 12",Profilename: "test_profile02" }

      delegate_to: localhost
      register: result

    - debug: msg= "{{ result }}"
    - debug: msg= "{{ result.msg }}"

...

目的:

$ cat bayfile.yml
---

-  'Bay: "ENT0005,Profilename: "test_profile01"'
-  'Bay: "ENT0005,Profilename: "test_profile02"'

...

我尝试了什么:

loop: "{{ lookup('file','{{ bayfile.yml }}') }}"

但上面不起作用。

解决方法

您的方向是正确的,但有几个问题:

数据文件中有错误的 YAML 语法。

在您的示例中,您显示:

-  'Bay: "ENT0005,bay 11",Profilename: "test_profile01"'
-  'Bay: "ENT0005,bay 12",Profilename: "test_profile02"'

这是一个字符串列表(因为每个列表项都用单引号括起来)。如果您想重现您在剧本中显示的数据,您需要一个字典列表。你可能想要这个:

- Bay: "ENT0005,bay 11"
  Profilename: "test_profile01"

- Bay: "ENT0005,bay 12"
  Profilename: "test_profile02"

以下是相同的,只是使用了稍微不同的语法:

- {Bay: "ENT0005,Profilename: "test_profile01"}
- {Bay: "ENT0005,Profilename: "test_profile02"}

嵌套的 jinja2 模板标记

您从不嵌套 {{...}} 标记;你只需要最外层的集合……里面的所有东西都已经在 J​​inja 模板上下文中了。而不是:

loop: "{{ lookup('file','{{ bayfile.yml }}') }}"

你会写:

loop: "{{ lookup('file','bayfile.yml') }}"

将数据转换为 YAML

最后,当您像这样使用 file 查找时,结果只是一个字符串(文件的内容)。您想将其反序列化为 Ansible 数据结构,因此您需要 from_yaml 过滤器:

loop: "{{ lookup('file','bayfile.yml')  | from_yaml }}"

综合起来,我们得到了这样的结果:

- hosts: localhost
  gather_facts: false

  tasks:
    - name: Create server profile
      debug:
        msg:
          - "{{ item.Bay }}"
          - "{{ item.Profilename }}"
      loop: "{{ lookup('file','bayfile.yml') | from_yaml }}"

使用 include_vars

请注意,您可以在剧本中使用 file 任务,而不是使用 from_yaml 查找和 include_vars 过滤器。您首先需要重新格式化您的数据文件,使其成为字典而不是列表,如下所示:

oneview_servers:
  - Bay: "ENT0005,bay 11"
    Profilename: "test_profile01"

  - Bay: "ENT0005,bay 12"
    Profilename: "test_profile02"

然后你可以像这样写你的剧本:

- hosts: localhost
  gather_facts: false

  tasks:
    - name: Read data
      include_vars:
        file: bayfile.yml
        name: data

    - name: Create server profile
      debug:
        msg:
          - "{{ item.Bay }}"
          - "{{ item.Profilename }}"
      loop: "{{ data.oneview_servers }}"