【问题标题】:Parsing Bash Array in Yaml在 Yaml 中解析 Bash 数组
【发布时间】:2021-04-27 04:51:58
【问题描述】:

在 ansible playbook 中,我必须读取一个包含以下数据的 yaml 文件:

john: stu001
bob: stu002
william: stu003

此数据是动态的,可以有多个学生的 ID。我想在我的 ansible 游戏中阅读这个 yaml,并且需要像这样的输出:

---
- name: Students Data
  hosts: localhost
  tasks:
  - include_vars:
        file: tmp/stuData.yml
        name: stuName
  - name: "Students Details"
    uri:
      url: "{{ some_api_server }}"
      return_content: yes
      body_format: json
      method: POST
      body:
         matchers:
           - name: john
             id: stu001
             age: NA
           - name: bob
             id: stu002
             age: NA
           - name: william
             id: stu003
             age: NA
         startsAt: "{{ st_time }}"
         endsAt: "{{ en_time }}"
         createdBy: abc@example.com

我已经尝试了以下代码:

---
- name: Students Data
  hosts: localhost
  tasks:
  - include_vars:
        file: tmp/stuData.yml
        stuName: stuName
  - name: "Students Details"
    uri:
      url: "{{ some_api_server }}"
      return_content: yes
      body_format: json
      method: POST
      body:
         matchers:
         {% for k,v in stuName.items() %}
           - name: {{ k }}
             id: {{ v }}
             age: "NA"   
         {% endfor %}
         startsAt: "{{ st_time }}"
         endsAt: "{{ en_time }}"
         createdBy: abc@example.com

这在匹配器之后给了我语法错误。谁能帮我写正确的代码。

【问题讨论】:

  • 你能描述一下应用animals变量后的yaml文件吗?
  • 对不起,我的代码有错误。现在我已经纠正了。那么你现在可以检查如何循环这个动物变量来动态创建这个匹配器集合。
  • YAML 本身没有变量,但您可以在 bash 级别处理此问题,方法是将您的 YAML 代码定义为 Here-Document 并使用 bash 变量。因此,在 bash 循环的每次迭代中,您都拥有该特定动物的 YAML 代码版本,并且可以将其写入文件。
  • 你能添加例子吗?

标签: bash ansible yaml


【解决方案1】:

创建一个写入哈希的简单脚本,例如

shell> cat /tmp/xyz.sh 
#!/bin/bash
declare -A animals=(["moo"]="cow" ["woof"]="dog")
for i in "${!animals[@]}"; do
    echo "$i: ${animals[$i]}"
done

给予

shell> /tmp/xyz.sh 
woof: dog
moo: cow

然后是任务

    - set_fact:
        xyz: "{{ lookup('pipe', '/tmp/xyz.sh')|from_yaml }}"

创建字典

  xyz:
    moo: cow
    woof: dog

现在您可以将数据格式化为任何结构,例如

    - set_fact:
        matchers: "{{ xyz|dict2items }}"

给出列表匹配器

  matchers:
  - key: woof
    value: dog
  - key: moo
    value: cow

您可以更改属性的名称,例如

    - set_fact:
        matchers: "{{ xyz|dict2items(key_name='name', value_name='value') }}"

给予

  matchers:
  - name: woof
    value: dog
  - name: moo
    value: cow

然后,您可以添加属性 name 并将其放入列表中,例如

    - set_fact:
        _list: "{{ [{'name': 'xyz', 'matchers': matchers}] }}"

提供您正在寻找的结构

  _list:
  - matchers:
    - key: woof
      value: dog
    - key: moo
      value: cow
    name: xyz

问:将此动物变量传递给 yaml 文件

A:使用复制,例如

    - copy:
        dest: /tmp/xyz.yml
        content: |
          - name: xyz
            matchers:
          {% for k,v in xyz.items() %}
              - name: {{ k }}
                value: {{ v }}
          {% endfor %}

给予

shell> cat /tmp/xyz.yml 
- name: xyz
  matchers:
    - name: woof
      value: dog
    - name: moo
      value: cow

,或者你可以使用创建的列表,例如

    - copy:
        dest: /tmp/xyz.yml
        content: "{{ _list|to_yaml }}"

给予

shell> cat /tmp/xyz.yml 
- matchers:
  - {key: woof, value: dog}
  - {key: moo, value: cow}
  name: xyz

,或者你可以通过过滤器to_nice_yaml改进格式,例如

    - copy:
        dest: /tmp/xyz.yml
        content: "{{ _list|to_nice_yaml }}"

给予

shell> cat /tmp/xyz.yml 
-   matchers:
    -   key: woof
        value: dog
    -   key: moo
        value: cow
    name: xyz

问:"代码的流程就像首先会执行 sh 文件,然后调用 play。"

A:几乎没有区别。读取文件而不是在 pipe 查找中运行命令,例如

shell> /tmp/xyz.sh > /tmp/xyz.txt
shell> cat /tmp/xyz.txt
woof: dog
moo: cow

然后是任务

    - set_fact:
        xyz: "{{ lookup('file', '/tmp/xyz.txt')|from_yaml }}"

创建相同的字典

  xyz:
    moo: cow
    woof: dog

【讨论】:

  • 非常感谢。我的代码流程就像首先执行 sh 文件,该文件将调用 play 这是一个 yaml 文件,然后该 yaml 文件将触发也是一个 yaml 文件的任务文件。所以我需要在任务文件中循环这个动物变量。
  • 几乎没有区别。将查找插件从 pipe 更改为 file 并从文件中读取数据。我添加了一个示例。
  • 我明白了,谢谢。如何查看sh文件中动物变量的长度?
  • 不客气。在 Ansible 中使用 length。在 sh 中,在 sh 中打开一个新问题并将其设为minimal reproducible example
  • 我已经用我尝试过的方法更新了我的问题,请您查看一下并告诉我我的任务文件出了什么问题?
【解决方案2】:

这是一种从 bash 中“直接”传递它的方法。我怀疑它真的有什么用,但搜索很有趣

$ ansible localhost -m debug -a var=animals \
    -e "{\"animals\":{$(for k in ${!animals[@]}; do echo \"$k\":\"${animals[$k]}\",; done)}}"
localhost | SUCCESS => {
    "animals": {
        "moo": "cow",
        "woof": "dog"
    }
}

请注意,您可能可以创建一个 bash 脚本或函数来简化该处理,但我自己没有尝试过,如果您想走这条路,我会让您这样做。

【讨论】:

猜你喜欢
  • 2015-06-20
  • 2015-05-14
  • 2021-06-05
  • 2019-07-23
  • 2015-08-17
  • 2018-05-11
  • 2021-06-12
  • 1970-01-01
  • 2012-07-16
相关资源
最近更新 更多