首页 > 解决方案 > 将 ansible jinja2 for 循环转换为列表

问题描述

我目前在 Ansible 中遇到 jinja2 for 循环的问题。我想提取titleAnsible 可用的任何 Windows 更新。

我试图用这个来取回结果:

- win_updates:
    category_names: "{{ win_update_categories }}"
    state: searched
  register: available_updates

- debug: msg="{{ available_updates }}"

- debug:
    msg: "{{ item['title'] }}"
  with_items: " {{ available_updates['updates'] }}"

我得到了这个:

"msg": "available_updates = {'updates': {'74f56410-a048-4c27-91de-5f09600944c7': {'categories': ['Definition Updates', 'Microsoft Defender Antivirus'], 'title': 'Update for Microsoft Defender Antivirus antimalware platform - KB4052623 (Version 4.18.2107.4)', 'id': '74f56410-a048-4c27-91de-5f09600944c7', 'installed': False, 'kb': ['4052623']}, '7b31e2cf-c6b0-434e-9420-97c6fe756573': {'categories': ['Security Updates', 'Windows Server 2019'], 'title': '2021-08 Cumulative Update for Windows Server 2019 for x64-based Systems (KB5005030)', 'id': '7b31e2cf-c6b0-434e-9420-97c6fe756573', 'installed': False, 'kb': ['5005030']}}, 'found_update_count': 2, 'changed': False, 'reboot_required': False, 'installed_update_count': 0, 'filtered_updates': {}, 'failed': False}"
ok: [172.16.1.1] => (item=74f56410-a048-4c27-91de-5f09600944c7) => {
    "msg": "<built-in method title of AnsibleUnsafeText object at 0x7f1f9a4bec80>"
}
ok: [172.16.1.1] => (item=7b31e2cf-c6b0-434e-9420-97c6fe756573) => {
    "msg": "<built-in method title of AnsibleUnsafeText object at 0x7f1f9a4bef90>"
}

如您所见,它title是编码的或类似的东西。

所以,我做了一些搜索,发现这个解决方案使用 jinja2 和 for 循环来取回更新的标题。

- win_updates:
    category_names: "{{ win_update_categories }}"
    state: searched
  register: available_updates

- set_fact:
     available_updates_title: >-
       "{% for update in available_updates.updates.values() %}
          {{ update.title }}
        {% endfor %}"

- debug:
    msg: "{{ available_updates_title }}"

我得到了这个:

"msg": "  Update for Microsoft Defender Antivirus antimalware platform - KB4052623 (Version 4.18.2107.4)\n  2021-08 Cumulative Update for Windows Server 2019 for x64-based Systems (KB5005030)\n"

它工作正常,但我想创建一个可用于每个服务器的标题列表,同时jinja2 for loop创建一行标题。

所以我的问题是如何将输出转换为jinja2可以使用 Ansible 对其进行迭代的列表?

任何帮助,将不胜感激!提前致谢

标签: for-loopansiblejinja2

解决方案


很抱歉我对您的数据不存在的评论。同时,对您的 var 进行简单的库存调试,无需任何额外的字符,即

- debug:
   var: available_updates

会给出一个更容易阅读的结果,并从一开始就消除了可能的混淆:

ok: [localhost] => {
    "available_updates": {
        "changed": false,
        "failed": false,
        "filtered_updates": {},
        "found_update_count": 2,
        "installed_update_count": 0,
        "reboot_required": false,
        "updates": {
            "74f56410-a048-4c27-91de-5f09600944c7": {
                "categories": [
                    "Definition Updates",
                    "Microsoft Defender Antivirus"
                ],
                "id": "74f56410-a048-4c27-91de-5f09600944c7",
                "installed": false,
                "kb": [
                    "4052623"
                ],
                "title": "Update for Microsoft Defender Antivirus antimalware platform - KB4052623 (Version 4.18.2107.4)"
            },
            "7b31e2cf-c6b0-434e-9420-97c6fe756573": {
                "categories": [
                    "Security Updates",
                    "Windows Server 2019"
                ],
                "id": "7b31e2cf-c6b0-434e-9420-97c6fe756573",
                "installed": false,
                "kb": [
                    "5005030"
                ],
                "title": "2021-08 Cumulative Update for Windows Server 2019 for x64-based Systems (KB5005030)"
            }
        }
    }
}

现在很明显,这available_updates.updates是一个 dict,其中键是id您的更新,相应的值包含有关每个更新的所有详细信息。

在第一个评论中提取更新的一般 oneliner 想法title仍然很好,除了我们需要在应用映射过滤器来提取属性之前将 dict 转换为列表。这可以使用.values()dict 上的方法(如您的示例中已经存在的那样)或使用dict2items过滤器来完成。以下剧本演示了两种可能的方法

---
- name: Extract list of elements from dict
  hosts: localhost
  gather_facts: false

  vars:
    # Your orig var on a single line for legigility
    available_updates: {'updates':{'74f56410-a048-4c27-91de-5f09600944c7':{'categories':['Definition Updates','Microsoft Defender Antivirus'],'title':'Update for Microsoft Defender Antivirus antimalware platform - KB4052623 (Version 4.18.2107.4)','id':'74f56410-a048-4c27-91de-5f09600944c7','installed':False,'kb':['4052623']},'7b31e2cf-c6b0-434e-9420-97c6fe756573':{'categories':['Security Updates','Windows Server 2019'],'title':'2021-08 Cumulative Update for Windows Server 2019 for x64-based Systems (KB5005030)','id':'7b31e2cf-c6b0-434e-9420-97c6fe756573','installed':False,'kb':['5005030']}},'found_update_count':2,'changed':False,'reboot_required':False,'installed_update_count':0,'filtered_updates':{},'failed':False}
    # Equivalent var definitions
    title_list_using_values_method: >-
      {{ available_updates.updates.values() | map(attribute='title') }}
    title_list_using_dict2items_filter: >-
      {{ available_updates.updates | dict2items | map(attribute='value.title') }}

  tasks:
    - name: "Show the original var (use -v to display)"
      debug:
        var: available_updates
        verbosity: 1

    - name: "Show result with both definitions"
      debug:
        var: "title_list_using_{{ flavor }}"
      loop:
        - values_method
        - dict2items_filter
      loop_control:
        loop_var: flavor

并给出:

PLAY [Extract list of elements from dict] *****************************************************************************

TASK [Show the original var (use -v to display)] *****************************************************************************
skipping: [localhost]

TASK [Show result with both definitions] *****************************************************************************
ok: [localhost] => (item=values_method) => {
    "ansible_loop_var": "flavor",
    "flavor": "values_method",
    "title_list_using_values_method": [
        "Update for Microsoft Defender Antivirus antimalware platform - KB4052623 (Version 4.18.2107.4)",
        "2021-08 Cumulative Update for Windows Server 2019 for x64-based Systems (KB5005030)"
    ]
}
ok: [localhost] => (item=dict2items_filter) => {
    "ansible_loop_var": "flavor",
    "flavor": "dict2items_filter",
    "title_list_using_dict2items_filter": [
        "Update for Microsoft Defender Antivirus antimalware platform - KB4052623 (Version 4.18.2107.4)",
        "2021-08 Cumulative Update for Windows Server 2019 for x64-based Systems (KB5005030)"
    ]
}

PLAY RECAP *****************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

推荐阅读