你如何在另一个with_items任务中调用已注册的输出?

huangapple go评论69阅读模式
英文:

How can I call with_items task registered output in another with_items task?

问题

  tasks:
  - name: 查找ARN
    shell: aws acm list-certificates --output text --certificate-statuses ISSUED | grep {{ apache[item].domain }} | awk '{print $2}'
    args:
      executable: /bin/bash
    with_items:
	- "clientA"
	- "clientB"
	- "clientC"
	register: sslarn
  - debug: msg={{ item.stdout_lines }}
    with_items:
    - "{{ sslarn.results[item.index].stdout_lines }}"
  - name: 重新生成字典组装文件
    template:
      src: /file/path/to/templates/update-dictionary-template.j2
      dest: /file/path/to/dictionary/files/{{ item }}.yml
      mode: 0644
    with_items:
	- "clientA"
	- "clientB"
	- "clientC"
  - name: 组装字典
    assemble:
      ignore_hidden: yes
      src: /file/path/to/dictionary/files/
      dest: /file/path/to/dictionary/dictionary.yml
英文:

I'm trying to create a playbook that will lookup the AWS ARN for an SSL certificate for each of our clients and then use the results with a template to update a custom dictionary.

  tasks:
  - name: Find ARN
    shell: aws acm list-certificates --output text --certificate-statuses ISSUED | grep {{ apache[item].domain }} | awk '{print $2}'
    args:
      executable: /bin/bash
    with_items:
	- "clientA"
	- "clientB"
	- "clientC"
	register: sslarn
  - debug: msg={{ item.stdout_lines }}
    with_items:
    - "{{ sslarn.results }}"
  - name: Remake the dictionary assemble files
    template:
      src: /file/path/to/templates/update-dictionary-template.j2
      dest: /file/path/to/dictionary/files/{{ item }}.yml
      mode: 0644
    with_items:
	- "clientA"
	- "clientB"
	- "clientC"
  - name: Assemble the dictionary
    assemble:
      ignore_hidden: yes
      src: /file/path/to/dictionary/files/
      dest: /file/path/to/dictionary/dictionary.yml

I'm able to find the ARN without any issues in the first task. However, when I try to use debug to figure out how to call the ARN per client for the template task I'm unable to figure out how to only get the ARN for the specific client out of the registered results.

答案1

得分: 1

以下是您要翻译的部分:

无论在迭代中使用哪个模块,列表 results 的项始终包括属性 item。使用方便的模式 dict(keys|zip(values)) 并创建一个字典,其中 keys 是属性 items 的列表,values 是列表 results。如果您注册了变量 sslarn,请声明该字典

sslarn_dict: "{{ dict(sslarn.results|map(attribute='item')|
                        zip(sslarn.results)) }}"

例如,给定以下客户端

clients: [clientA, clientB, clientC]

,仅在本地主机上运行,以下迭代

    - command: "echo certificate-statuses {{ item }}"
      loop: "{{ clients }}"
      register: sslarn

给出

<sup>

  sslarn_dict:
    clientA:
      ansible_facts: {discovered_interpreter_python: /usr/bin/python3}
      ansible_loop_var: item
      changed: true
      cmd: [echo, certificate-statuses, clientA]
      delta: &#39;0:00:00.003085&#39;
      end: &#39;2023-07-11 06:55:46.144448&#39;
      failed: false
      invocation:
        module_args: {_raw_params: echo certificate-statuses clientA, _uses_shell: false,
          argv: null, chdir: null, creates: null, executable: null, removes: null, stdin: null,
          stdin_add_newline: true, strip_empty_ends: true}
      item: clientA
      msg: &#39;&#39;
      rc: 0
      start: &#39;2023-07-11 06:55:46.141363&#39;
      stderr: &#39;&#39;
      stderr_lines: []
      stdout: certificate-statuses clientA
      stdout_lines: [certificate-statuses clientA]
    clientB:
      ansible_loop_var: item
      changed: true
      cmd: [echo, certificate-statuses, clientB]
      delta: &#39;0:00:00.003012&#39;
      end: &#39;2023-07-11 06:55:46.367788&#39;
      failed: false
      invocation:
        module_args: {_raw_params: echo certificate-statuses clientB, _uses_shell: false,
          argv: null, chdir: null, creates: null, executable: null, removes: null, stdin: null,
          stdin_add_newline: true, strip_empty_ends: true}
      item: clientB
      msg: &#39;&#39;
      rc: 0
      start: &#39;2023-07-11 06:55:46.364776&#39;
      stderr: &#39;&#39;
      stderr_lines: []
      stdout: certificate-statuses clientB
      stdout_lines: [certificate-statuses clientB]
    clientC:
      ansible_loop_var: item
      changed: true
      cmd: [echo, certificate-statuses, clientC]
      delta: &#39;0:00:00.003018&#39;
      end: &#39;2023-07-11 06:55:46.584018&#39;
      failed: false
      invocation:
        module_args: {_raw_params: echo certificate-statuses clientC, _uses_shell: false,
          argv: null, chdir: null, creates: null, executable: null, removes: null, stdin: null,
          stdin_add_newline: true, strip_empty_ends: true}
      item: clientC
      msg: &#39;&#39;
      rc: 0
      start: &#39;2023-07-11 06:55:46.581000&#39;
      stderr: &#39;&#39;
      stderr_lines: []
      stdout: certificate-statuses clientC
      stdout_lines: [certificate-statuses clientC]

</sup>

<hr>

现在,您可以在模板中使用字典。例如,

shell&gt; cat update-dictionary-template.j2
{{ item }}: {{ sslarn_dict[item][&#39;stdout&#39;] }}
    - template:
        src: update-dictionary-template.j2
        dest: /tmp/files/{{ item }}.yml
      loop: &quot;{{ clients }}&quot;

将创建文件

shell&gt; tree /tmp/files/
/tmp/files/
├── clientA.yml
├── clientB.yml
└── clientC.yml
shell&gt; cat /tmp/files/clientA.yml 
clientA: certificate-statuses clientA
shell&gt; cat /tmp/files/clientB.yml 
clientB: certificate-statuses clientB
shell&gt; cat /tmp/files/clientC.yml 
clientC: certificate-statuses clientC

您可以组装文件 /tmp/dictionary.yml

    - assemble:
        src: /tmp/files
        dest: /tmp/dictionary.yml

给出

shell&gt; cat /tmp/dictionary.yml 
clientA: certificate-statuses clientA
clientB: certificate-statuses clientB
clientC: certificate-statuses clientC

但是,您可以在不组装中间文件的情况下获得相同的内容。以下模板提供了相同的结果

    - debug:
        msg: |
          {% for client in clients %}
          {{ client }}: {{ sslarn_dict[client][&#39;stdout&#39;] }}
          {% endfor %}          

但是,最简单的方法是仅从选定的属性创建字典

  client_stdout: &quot;{{ sslarn.results|
                     items2dict(key_name=&#39;item&#39;, value_name=&#39;stdout&#39;) }}&quot;

给出

  client_stdout:
    clientA: certificate-statuses clientA
    clientB: certificate-statuses clientB
    clientC: certificate-statuses clientC

然后,模板很简单

    - debug:
        msg: |
                    {{ client_stdout }}

给出

  msg:
    clientA: certificate-statuses clientA
    clientB: certificate-statuses clientB
    clientC: certificate-statuses clientC

<hr>

<sup>

完整测试的示例剧本

- hosts: localhost

  vars:

    clients: [clientA, clientB, clientC]
    sslarn_dict: &quot;{{ dict(sslarn.results|

<details>
<summary>英文:</summary>

Whatever module is used in an iteration the items of the list *results* always comprise the attribute *item*. Use the handy pattern `dict(keys|zip(values))` and create a dictionary where the *keys* is the list of the attribute *items* and *values* is the list *results*. If you register the variable *sslarn* declare the dictionary

```yaml
  sslarn_dict: &quot;{{ dict(sslarn.results|map(attribute=&#39;item&#39;)|
                        zip(sslarn.results)) }}&quot;

For example, given the clients

  clients: [clientA, clientB, clientC]

, running on the localhost only, the below iteration

    - command: &quot;echo certificate-statuses {{ item }}&quot;
      loop: &quot;{{ clients }}&quot;
      register: sslarn

gives

<sup>

  sslarn_dict:
    clientA:
      ansible_facts: {discovered_interpreter_python: /usr/bin/python3}
      ansible_loop_var: item
      changed: true
      cmd: [echo, certificate-statuses, clientA]
      delta: &#39;0:00:00.003085&#39;
      end: &#39;2023-07-11 06:55:46.144448&#39;
      failed: false
      invocation:
        module_args: {_raw_params: echo certificate-statuses clientA, _uses_shell: false,
          argv: null, chdir: null, creates: null, executable: null, removes: null, stdin: null,
          stdin_add_newline: true, strip_empty_ends: true}
      item: clientA
      msg: &#39;&#39;
      rc: 0
      start: &#39;2023-07-11 06:55:46.141363&#39;
      stderr: &#39;&#39;
      stderr_lines: []
      stdout: certificate-statuses clientA
      stdout_lines: [certificate-statuses clientA]
    clientB:
      ansible_loop_var: item
      changed: true
      cmd: [echo, certificate-statuses, clientB]
      delta: &#39;0:00:00.003012&#39;
      end: &#39;2023-07-11 06:55:46.367788&#39;
      failed: false
      invocation:
        module_args: {_raw_params: echo certificate-statuses clientB, _uses_shell: false,
          argv: null, chdir: null, creates: null, executable: null, removes: null, stdin: null,
          stdin_add_newline: true, strip_empty_ends: true}
      item: clientB
      msg: &#39;&#39;
      rc: 0
      start: &#39;2023-07-11 06:55:46.364776&#39;
      stderr: &#39;&#39;
      stderr_lines: []
      stdout: certificate-statuses clientB
      stdout_lines: [certificate-statuses clientB]
    clientC:
      ansible_loop_var: item
      changed: true
      cmd: [echo, certificate-statuses, clientC]
      delta: &#39;0:00:00.003018&#39;
      end: &#39;2023-07-11 06:55:46.584018&#39;
      failed: false
      invocation:
        module_args: {_raw_params: echo certificate-statuses clientC, _uses_shell: false,
          argv: null, chdir: null, creates: null, executable: null, removes: null, stdin: null,
          stdin_add_newline: true, strip_empty_ends: true}
      item: clientC
      msg: &#39;&#39;
      rc: 0
      start: &#39;2023-07-11 06:55:46.581000&#39;
      stderr: &#39;&#39;
      stderr_lines: []
      stdout: certificate-statuses clientC
      stdout_lines: [certificate-statuses clientC]

</sup>

<hr>

Now, you can use the dictionary in a template. For example,

shell&gt; cat update-dictionary-template.j2
{{ item }}: {{ sslarn_dict[item][&#39;stdout&#39;] }}
    - template:
        src: update-dictionary-template.j2
        dest: /tmp/files/{{ item }}.yml
      loop: &quot;{{ clients }}&quot;

will create files

shell&gt; tree /tmp/files/
/tmp/files/
├── clientA.yml
├── clientB.yml
└── clientC.yml
shell&gt; cat /tmp/files/clientA.yml 
clientA: certificate-statuses clientA
shell&gt; cat /tmp/files/clientB.yml 
clientB: certificate-statuses clientB
shell&gt; cat /tmp/files/clientC.yml 
clientC: certificate-statuses clientC

You can assemble the file /tmp/dictionary.yml

    - assemble:
        src: /tmp/files
        dest: /tmp/dictionary.yml

gives

shell&gt; cat /tmp/dictionary.yml 
clientA: certificate-statuses clientA
clientB: certificate-statuses clientB
clientC: certificate-statuses clientC

However, you can get the same content without assembling the intermediate files. The template below gives the same result

    - debug:
        msg: |
          {% for client in clients %}
          {{ client }}: {{ sslarn_dict[client][&#39;stdout&#39;] }}
          {% endfor %}          

But, the easiest way is to create a dictionary from selected attributes only

  client_stdout: &quot;{{ sslarn.results|
                     items2dict(key_name=&#39;item&#39;, value_name=&#39;stdout&#39;) }}&quot;

gives

  client_stdout:
    clientA: certificate-statuses clientA
    clientB: certificate-statuses clientB
    clientC: certificate-statuses clientC

Then, the template is trivial

    - debug:
        msg: |
                    {{ client_stdout }}

gives

  msg:
    clientA: certificate-statuses clientA
    clientB: certificate-statuses clientB
    clientC: certificate-statuses clientC

<hr>

<sup>

Example of a complete playbook for testing

- hosts: localhost

  vars:

    clients: [clientA, clientB, clientC]
    sslarn_dict: &quot;{{ dict(sslarn.results|map(attribute=&#39;item&#39;)|
                          zip(sslarn.results)) }}&quot;
    client_stdout: &quot;{{ sslarn.results|
                       items2dict(key_name=&#39;item&#39;, value_name=&#39;stdout&#39;) }}&quot;

  tasks:

    - command: &quot;echo certificate-statuses {{ item }}&quot;
      loop: &quot;{{ clients }}&quot;
      register: sslarn
    - debug:
        var: sslarn_dict|to_yaml

    - template:
        src: update-dictionary-template.j2
        dest: /tmp/files/{{ item }}.yml
      loop: &quot;{{ clients }}&quot;

    - assemble:
        src: /tmp/files
        dest: /tmp/dictionary.yml

    - debug:
        msg: |
          {% for client in clients %}
          {{ client }}: {{ sslarn_dict[client][&#39;stdout&#39;] }}
          {% endfor %}          

    - debug:
        var: client_stdout

    - debug:
        msg: |
                    {{ client_stdout }}

</sup>

huangapple
  • 本文由 发表于 2023年7月11日 08:43:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76658082.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定