ansible中使用list和dict的嵌套循环

问题描述 投票:0回答:3

我在ansible中有两种类型的输入数据。 首先是字符串列表:

- '1.1.1.1'
- '2.2.2.2'

第二个是字典列表。

- {'name': 'obj1', 'addr': '1.1.1.1'}
- {'name': 'objx', 'addr': 'x.x.x.x'}

我事先不知道第一个列表的项目是否在第二个列表的地址字段中。因此我必须执行评估,为此我必须使用嵌套循环。我需要循环遍历第一个列表并循环遍历第二个列表,然后执行条件检查第一个列表的 item 是否等于第二个列表的 item.addr 。但是我不知道如何在 ansible 条件下区分第一个列表的项目和第二个列表的项目。

在Python中我会通过使用以下表达式来实现类似的事情:

for add in my_list: 
    for obj in my_list2: 
        if add == obj['addr']: 
            new_list.append([obj])

在ansible中应该是这样的:

- set_fact:
    new_list: "{{ new_list }} + [ {'name': '{{ item_second_list.name }}', 'address': '{{ item_second_list.addr }}'} ]"
  when: item_first_list == item_second_list.addr
  with_list: first_list
  with_list: second_list
python loops ansible conditional-statements
3个回答
2
投票

鉴于数据

  my_list:
    - 1.1.1.1
    - 2.2.2.2
  my_dict:
    - {name: obj1, addr: 1.1.1.1}
    - {name: objx, addr: x.x.x.x}

以下任务

    - set_fact:
        sel_list: "{{ my_dict | selectattr('addr', 'in', my_list) }}"

给你想要的

  sel_list:
  - addr: 1.1.1.1
    name: obj1

用于测试的完整剧本示例

- hosts: localhost

  vars:

    my_list:
      - 1.1.1.1
      - 2.2.2.2
    my_dict:
      - {name: obj1, addr: 1.1.1.1}
      - {name: objx, addr: x.x.x.x}

    sel_list: "{{ my_dict | selectattr('addr', 'in', my_list) }}"

  tasks:

    - debug:
        var: sel_list

    - set_fact:
        sel_list: "{{ my_dict | selectattr('addr', 'in', my_list) }}"
    - debug:
        var: sel_list

1
投票

YAML 字典中存在两个相同的键是错误的。 换句话说,你不能像这样使用

with_list
两次:它应该 生成错误,否则,除了最后一个之外的所有内容都将被忽略。在大多数情况下,Ansible 不直接支持嵌套循环。

看起来您想要生成一个包含在字典列表中的地址列表。也就是说,给定:

list1:
  - 1.1.1.1
  - 2.2.2.2
  - 3.3.3.3

list2:
  - {'name': 'obj1', 'addr': '1.1.1.1'}
  - {'name': 'objx', 'addr': '2.2.2.2'}

您想要生成一个新列表:

list3:
  - 1.1.1.1
  - 2.2.2.2

我们可以在没有嵌套列表的情况下做到这一点,方法是询问

list2
中的所有地址,然后仅选择那些
in list1
:

---
- hosts: localhost
  gather_facts: false
  vars:
    list1:
      - 1.1.1.1
      - 2.2.2.2
      - 3.3.3.3

    list2:
      - name: obj1
        addr: 1.1.1.1
      - name: obj2
        addr: 2.2.2.2

  tasks:
    - set_fact:
        list3: "{{ (list3|default([])) + [item.addr] }}"
      when: item.addr in list1
      loop: "{{ list2 }}"

    - debug:
        var: list3

这将输出:

[...]

TASK [debug] *************************************************************************
ok: [localhost] => {
    "list3": [
        "1.1.1.1",
        "2.2.2.2"
    ]
}


-1
投票

您可以尝试使用with_nested。

下面是一个例子..(不是工作代码,仅供参考)

  vars:
     first_list:
     - '1.1.1.1'
     - '2.2.2.2'
    second_list:
     - {'name': 'obj1', 'addr': '1.1.1.1'}
     - {'name': 'objx', 'addr': '2.3.4.5'}
- set_fact:
    new_list: " {{new_list|default([])}} + {{ item.1}} "
  when: item.0 == item.1.addr
  with_nested:
    - "{{first_list}}"
    - "{{second_list}}"

参考:https://docs.ansible.com/ansible/latest/plugins/lookup/nested.html

输出:

ok: [localhost] => (item=[u'1.1.1.1', {u'name': u'obj1', u'addr': u'1.1.1.1'}]) => {
    "ansible_facts": {
        "new_list": " [] + {u'name': u'obj1', u'addr': u'1.1.1.1'} "
    },
© www.soinside.com 2019 - 2024. All rights reserved.