Ansible中使用列表和字典的嵌套循环

时间:2019-11-13 11:44:34

标签: python loops ansible conditional-statements

我有两种类型的输入数据。 冷杉是一个字符串列表:

- '1.1.1.1'
- '2.2.2.2'

第二是字典列表。

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

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

在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

3 个答案:

答案 0 :(得分:0)

在YAML字典中具有两个相同的键是一个错误。换句话说,您不能像这样两次使用 rename {OurApi => OurAPI}/Startup.cs (100%) rename {OurApi => OurAPI}/packages.config (100%) rename {OurApi => OurAPI}/web.Debug.config (100%) rename {OurApi => OurAPI}/web.Release.config (100%) rename {OurApi => OurAPI}/web.config (100%) :它应该会产生一个错误,否则,将忽略最后一个错误。在大多数情况下,Ansible不直接支持嵌套循环。

您似乎想生成包含在词典列表中的地址列表。也就是说,给定:

with_list

您要生成新列表:

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

答案 1 :(得分:0)

下面的戏

  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'}

  tasks:
    - set_fact:
        sel_list: "{{ sel_list|default([]) +
                      my_dict|
                      selectattr('addr', 'in', my_list)|
                      list }}"
    - debug:
        var: sel_list

给予

"sel_list": [
    {
        "addr": "1.1.1.1", 
        "name": "obj1"
    }
]

答案 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'} "
    },