在Ansible中将子元素用于API调用

时间:2019-05-21 11:23:42

标签: ansible

我正在尝试在同一任务中使用不同的URI和不同的JSON进行API调用。

这些是我的变量:

api_templates:
  - name                    : 
     - 'template1'
     - 'template2'
    url                     :
      - 'http://localhost:80/template1'
      - 'http://localhost:80/template2'
    file                    :
      - '../files/template1.json'
      - '../files/template2.json'

我正在使用以下代码:

- name: Inserting templates
  uri:
    url: "{{ item.0.url }}"
    method: PUT
    body: "{{ lookup('file', '{{ item.1 }}') }}"
    body_format: json
  with_subelements:
     - "{{ api_templates }}"
     - file

但是它不能正常工作。

我需要任务的第一次迭代使用模板1,第一个URL并使用第一个文件等来执行API调用。

2 个答案:

答案 0 :(得分:0)

听起来像您希望您的任务使用这些数据集循环两次:

  • (template1, http://localhost:80/template1, ../files/template1.json)
  • (template2, http://localhost:80/template2, ../files/template2.json)

您不想要子元素,而是希望并行遍历三个列表。这意味着您想要with_together(旧方法)或loopzip过滤器(新方法),如下所示:

首先,我建议重组您的数据。现在,api_templates是一项(列表)的列表。我们可以通过删除多余的层次结构来简化事情:

api_templates:
  name                    : 
   - 'template1'
   - 'template2'
  url                     :
    - 'http://localhost:80/template1'
    - 'http://localhost:80/template2'
  file                    :
    - '../files/template1.json'
    - '../files/template2.json'

然后,我们可以像这样循环遍历您的三个列表(nameurlfile):

- debug:
    msg: "name: {{ item.0 }}, url: {{ item.1 }}, file: {{ item.2 }}"
  loop: "{{ api_templates.name|zip(api_templates.url, api_templates.file) | list }}"

或以您的任务为例:

- name: Inserting templates
  uri:
    url: "{{ item.1 }}"
    method: PUT
    body: "{{ lookup('file', '{{ item.2 }}') }}"
    body_format: json
  loop: "{{ api_templates.name|zip(api_templates.url, api_templates.file) | list }}"

由于您似乎忽略了name列表,因此可以从该loop表达式中删除一个术语:

loop: "{{ api_templates.url | zip(api_templates.file) | list }}"

如果api_templates真的列表,例如:

api_templates:
  - name                    : 
     - 'template1'
     - 'template2'
    url                     :
      - 'http://localhost:80/template1'
      - 'http://localhost:80/template2'
    file                    :
      - '../files/template1.json'
      - '../files/template2.json'
  - name                    : 
     - 'template3'
     - 'template4'
    url                     :
      - 'http://localhost:80/template3'
      - 'http://localhost:80/template4'
    file                    :
      - '../files/template3.json'
      - '../files/template4.json'

...那么事情就有点复杂了,因为您需要一个 嵌套循环可做您想要的。 Ansible不直接支持嵌套 循环,但是您可以通过include机制来伪造它。例如,移动 将“插入模板”任务插入名为process_template.yml的文件中, 看起来像这样:

- name: Inserting templates
  uri:
    url: "{{ item.0 }}"
    method: PUT
    body: "{{ lookup('file', '{{ item.1 }}') }}"
    body_format: json
  loop: "{{ template.url | zip(template.file) | list }}"

然后在您的playbook.yml中,将其命名为:

- include_tasks: process_template.yml
  loop: "{{ api_templates }}"
  loop_control:
    loop_var: template

答案 1 :(得分:0)

简单的解决方案是循环 include_tasks 。下面的游戏

- include_tasks: uri-put.yml
  loop: "{{ api_templates }}"
  loop_control:
    loop_var: uri

包含随附的文件

> cat uri-put.yml
- debug: msg="{{ item.0 }} {{ item.1 }} {{ item.2 }}"
  with_together:
    - "{{ uri.name }}"
    - "{{ uri.url }}"
    - "{{ uri.file }}"

给予(猫味精):

"msg": "template1 http://localhost:80/template1 ../files/template1.json"
"msg": "template2 http://localhost:80/template2 ../files/template2.json"