【问题标题】:Ansible Loops with Lists带有列表的 Ansible 循环
【发布时间】:2021-01-05 13:47:57
【问题描述】:

我正在寻找一些帮助来解析 ansible 角色/剧本中的嵌套列表日期。

Below is what I am trying to acheive
For each policyID in variable file
    get name, srcint, dstint, action in each policyid
    get all srcaddr from varfile ( example it may have 5 entries)
    get all dstaddr from varfile ( example it may have 2 entries)
    get all service from varfile  ( example it may have 1 or 5 entries)
If there are 5 policy IDs, then 5 policies with above details will be created
folder structure
├── ansible.cfg
├── host_vars
│   ├── FWUKDC001
│   │   └── var.yml
│   └── [template]
│       └── var.yml
├── main.yml
└── roles
    └── policy
        └── tasks
            ├── address.yml
            ├── main.yml
            ├── policy.yml
            └── service.yml


我的变量文件:

   policy:
      - policyid:
          - name: "Internal->Internet1"
            action: "accept"
            srcintf: "Internal"
            dstintf: "Internet"
            srcaddr:  # policy[0].srcaddr
              - name: "n_10.0.10.0_24"  # policy[0].srcaddr[0].name
              - name: "n_10.0.20.0_24"  # policy[0].srcaddr[1].name
            dstaddr:
              - name: "n_8.8.8.8_32"
              - name: "n_7.8.8.8_32"
            service:
              - name: "TCP_8080"
              - name: "TCP_8081"
      - policyid:
         -  name: "Internal->Internet2"
            action: "accept"
            srcintf: "Internal"
            dstintf: "DMZ"
            srcaddr:
              - name: "n_10.0.10.0_24"
              - name: "n_10.0.20.0_24"
            dstaddr:
              - name: "n_172.16.0.0_24"
            service:
              - name: "TCP_8080"
              - name: "TCP_8081"

我的角色文件:

- name: Firewall Policy
  fortios_firewall_policy:
   state: "{{ operation }}"
   firewall_policy:
    policyid: "0"
    schedule: "always"
    nat: "disable"
    name: "{{item.0.name}}"
    action: "{{item.0.action}}"
    srcintf:
     - name: "{{item.0.srcintf}}"
    dstintf:
     - name: "{{item.0.dstintf}}"
    srcaddr:
     - name: "{{item.1.value}}"
    dstaddr:
     - name: "{{item.2.value}}"
    service:
     - name: "{{item.3.value}}"

  with_nested:
    - "{{ policy }}"
    - "{{ policy.srcaddr }}"
    - "{{ policy.dstaddr }}"
    - "{{ policy.service }}"

我正在尝试从 YAML 文件中获取变量的值并在角色文件中使用它,但无法在它周围找到好的文档。 不确定sub_elements 是否会完成这项工作或正常循环,或者with_elements。 帮助将不胜感激

【问题讨论】:

  • 您能描述一下预期的结果以及与它有什么不同吗?你的 var 文件在哪里?你是如何尝试在你的剧本/角色中使用它的?您究竟想如何循环这些变量?如果您尝试过某事,您得到的错误是什么?照原样,您基本上是在要求我们猜测您到底想做什么。关于“好的文档”,首先 => Using variables, loops。我也建议你阅读How to ask

标签: loops ansible nested


【解决方案1】:

我认为您正在尝试使用srcaddr × dstaddr × service 的笛卡尔积来生成一系列策略操作。我们可以使用set_fact 模块为每个包含适当数据的策略添加一个值,然后在后续循环中使用subelements 过滤器来实际呈现策略任务。

在下面的示例中,我将所有内容都包装在 debug 模块中(因为我没有任何方法来测试您对 fortios_firewall_policy 模块的使用),但输出应该确认(或不确认)这会产生正确的结果。

- hosts: localhost
  gather_facts: false
  vars:
    policy:
      - policyid: "0"  # policy[0].policyid
        name: "Internal->Internet1"
        action: "accept"
        srcintf: "Internal"
        dstintf: "Internet"
        srcaddr:  # policy[0].srcaddr
          - name: "n_10.0.10.0_24"  # policy[0].srcaddr[0].name
          - name: "n_10.0.20.0_24"  # policy[0].srcaddr[1].name
        dstaddr:
          - name: "n_8.8.8.8_32"
          - name: "n_7.8.8.8_32"
        service:
          - name: "TCP_8080"
          - name: "TCP_8081"
      - policyid: "1"
        name: "Internal->Internet2"
        action: "accept"
        srcintf: "Internal"
        dstintf: "DMZ"
        srcaddr:
          - name: "n_10.0.10.0_24"
          - name: "n_10.0.20.0_24"
        dstaddr:
          - name: "n_172.16.0.0_24"
        service:
          - name: "TCP_8080"
          - name: "TCP_8081"
  tasks:
    # Here we're adding a "values" key to each entry in your "policy" list that
    # contains the cross product of srcaddr, dstaddr, and service.
    - set_fact:
        targets: >-
          {{
            targets + [
              item | combine({
                'policy': item,
                'values': item.srcaddr|product(item.dstaddr, item.service)|list
              })
            ]
          }}
      loop: "{{ policy }}"
      vars:
        targets: []

    # Now we can use the "values" key we created in the previous task with
    # the "subelements" filter:
    - debug:
        msg:
          - name: Firewall Policy
            fortios_firewall_policy:
              state: "foo"
              firewall_policy:
              policyid: "{{ item.0.policyid }}"
              schedule: "always"
              nat: "disable"
              name: "{{item.0.name}}"
              action: "{{item.0.action}}"
              srcintf:
                - name: "{{item.0.srcintf}}"
              dstintf:
                - name: "{{item.0.dstintf}}"
              srcaddr:
                - name: "{{item.1.0.name}}"
              dstaddr:
                - name: "{{item.1.1.name}}"
              service:
                - name: "{{item.1.2.name}}"
      loop: "{{ targets|subelements('values') }}"
      loop_control:
        label: "{{ item.0.name }}-{{ item.1 }}"

这将生成为输出:


PLAY [localhost] ******************************************************************************

TASK [set_fact] *******************************************************************************
ok: [localhost] => (item={'policyid': '0', 'name': 'Internal->Internet1', 'action': 'accept', 'srcintf': 'Internal', 'dstintf': 'Internet', 'srcaddr': [{'name': 'n_10.0.10.0_24'}, {'name': 'n_10.0.20.0_24'}], 'dstaddr': [{'name': 'n_8.8.8.8_32'}, {'name': 'n_7.8.8.8_32'}], 'service': [{'name': 'TCP_8080'}, {'name': 'TCP_8081'}]})
ok: [localhost] => (item={'policyid': '1', 'name': 'Internal->Internet2', 'action': 'accept', 'srcintf': 'Internal', 'dstintf': 'DMZ', 'srcaddr': [{'name': 'n_10.0.10.0_24'}, {'name': 'n_10.0.20.0_24'}], 'dstaddr': [{'name': 'n_172.16.0.0_24'}], 'service': [{'name': 'TCP_8080'}, {'name': 'TCP_8081'}]})

TASK [debug] **********************************************************************************
ok: [localhost] => (item=Internal->Internet1-[{'name': 'n_10.0.10.0_24'}, {'name': 'n_8.8.8.8_32'}, {'name': 'TCP_8080'}]) => {
    "msg": [
        {
            "fortios_firewall_policy": {
                "action": "accept",
                "dstaddr": [
                    {
                        "name": "n_8.8.8.8_32"
                    }
                ],
                "dstintf": [
                    {
                        "name": "Internet"
                    }
                ],
                "firewall_policy": null,
                "name": "Internal->Internet1",
                "nat": "disable",
                "policyid": "0",
                "schedule": "always",
                "service": [
                    {
                        "name": "TCP_8080"
                    }
                ],
                "srcaddr": [
                    {
                        "name": "n_10.0.10.0_24"
                    }
                ],
                "srcintf": [
                    {
                        "name": "Internal"
                    }
                ],
                "state": "foo"
            },
            "name": "Firewall Policy"
        }
    ]
}
ok: [localhost] => (item=Internal->Internet1-[{'name': 'n_10.0.10.0_24'}, {'name': 'n_8.8.8.8_32'}, {'name': 'TCP_8081'}]) => {
    "msg": [
        {
            "fortios_firewall_policy": {
                "action": "accept",
                "dstaddr": [
                    {
                        "name": "n_8.8.8.8_32"
                    }
                ],
                "dstintf": [
                    {
                        "name": "Internet"
                    }
                ],
                "firewall_policy": null,
                "name": "Internal->Internet1",
                "nat": "disable",
                "policyid": "0",
                "schedule": "always",
                "service": [
                    {
                        "name": "TCP_8081"
                    }
                ],
                "srcaddr": [
                    {
                        "name": "n_10.0.10.0_24"
                    }
                ],
                "srcintf": [
                    {
                        "name": "Internal"
                    }
                ],
                "state": "foo"
            },
            "name": "Firewall Policy"
        }
    ]
}
ok: [localhost] => (item=Internal->Internet1-[{'name': 'n_10.0.10.0_24'}, {'name': 'n_7.8.8.8_32'}, {'name': 'TCP_8080'}]) => {
    "msg": [
        {
            "fortios_firewall_policy": {
                "action": "accept",
                "dstaddr": [
                    {
                        "name": "n_7.8.8.8_32"
                    }
                ],
                "dstintf": [
                    {
                        "name": "Internet"
                    }
                ],
                "firewall_policy": null,
                "name": "Internal->Internet1",
                "nat": "disable",
                "policyid": "0",
                "schedule": "always",
                "service": [
                    {
                        "name": "TCP_8080"
                    }
                ],
                "srcaddr": [
                    {
                        "name": "n_10.0.10.0_24"
                    }
                ],
                "srcintf": [
                    {
                        "name": "Internal"
                    }
                ],
                "state": "foo"
            },
            "name": "Firewall Policy"
        }
    ]
}
ok: [localhost] => (item=Internal->Internet1-[{'name': 'n_10.0.10.0_24'}, {'name': 'n_7.8.8.8_32'}, {'name': 'TCP_8081'}]) => {
    "msg": [
        {
            "fortios_firewall_policy": {
                "action": "accept",
                "dstaddr": [
                    {
                        "name": "n_7.8.8.8_32"
                    }
                ],
                "dstintf": [
                    {
                        "name": "Internet"
                    }
                ],
                "firewall_policy": null,
                "name": "Internal->Internet1",
                "nat": "disable",
                "policyid": "0",
                "schedule": "always",
                "service": [
                    {
                        "name": "TCP_8081"
                    }
                ],
                "srcaddr": [
                    {
                        "name": "n_10.0.10.0_24"
                    }
                ],
                "srcintf": [
                    {
                        "name": "Internal"
                    }
                ],
                "state": "foo"
            },
            "name": "Firewall Policy"
        }
    ]
}
ok: [localhost] => (item=Internal->Internet1-[{'name': 'n_10.0.20.0_24'}, {'name': 'n_8.8.8.8_32'}, {'name': 'TCP_8080'}]) => {
    "msg": [
        {
            "fortios_firewall_policy": {
                "action": "accept",
                "dstaddr": [
                    {
                        "name": "n_8.8.8.8_32"
                    }
                ],
                "dstintf": [
                    {
                        "name": "Internet"
                    }
                ],
                "firewall_policy": null,
                "name": "Internal->Internet1",
                "nat": "disable",
                "policyid": "0",
                "schedule": "always",
                "service": [
                    {
                        "name": "TCP_8080"
                    }
                ],
                "srcaddr": [
                    {
                        "name": "n_10.0.20.0_24"
                    }
                ],
                "srcintf": [
                    {
                        "name": "Internal"
                    }
                ],
                "state": "foo"
            },
            "name": "Firewall Policy"
        }
    ]
}
ok: [localhost] => (item=Internal->Internet1-[{'name': 'n_10.0.20.0_24'}, {'name': 'n_8.8.8.8_32'}, {'name': 'TCP_8081'}]) => {
    "msg": [
        {
            "fortios_firewall_policy": {
                "action": "accept",
                "dstaddr": [
                    {
                        "name": "n_8.8.8.8_32"
                    }
                ],
                "dstintf": [
                    {
                        "name": "Internet"
                    }
                ],
                "firewall_policy": null,
                "name": "Internal->Internet1",
                "nat": "disable",
                "policyid": "0",
                "schedule": "always",
                "service": [
                    {
                        "name": "TCP_8081"
                    }
                ],
                "srcaddr": [
                    {
                        "name": "n_10.0.20.0_24"
                    }
                ],
                "srcintf": [
                    {
                        "name": "Internal"
                    }
                ],
                "state": "foo"
            },
            "name": "Firewall Policy"
        }
    ]
}
ok: [localhost] => (item=Internal->Internet1-[{'name': 'n_10.0.20.0_24'}, {'name': 'n_7.8.8.8_32'}, {'name': 'TCP_8080'}]) => {
    "msg": [
        {
            "fortios_firewall_policy": {
                "action": "accept",
                "dstaddr": [
                    {
                        "name": "n_7.8.8.8_32"
                    }
                ],
                "dstintf": [
                    {
                        "name": "Internet"
                    }
                ],
                "firewall_policy": null,
                "name": "Internal->Internet1",
                "nat": "disable",
                "policyid": "0",
                "schedule": "always",
                "service": [
                    {
                        "name": "TCP_8080"
                    }
                ],
                "srcaddr": [
                    {
                        "name": "n_10.0.20.0_24"
                    }
                ],
                "srcintf": [
                    {
                        "name": "Internal"
                    }
                ],
                "state": "foo"
            },
            "name": "Firewall Policy"
        }
    ]
}
ok: [localhost] => (item=Internal->Internet1-[{'name': 'n_10.0.20.0_24'}, {'name': 'n_7.8.8.8_32'}, {'name': 'TCP_8081'}]) => {
    "msg": [
        {
            "fortios_firewall_policy": {
                "action": "accept",
                "dstaddr": [
                    {
                        "name": "n_7.8.8.8_32"
                    }
                ],
                "dstintf": [
                    {
                        "name": "Internet"
                    }
                ],
                "firewall_policy": null,
                "name": "Internal->Internet1",
                "nat": "disable",
                "policyid": "0",
                "schedule": "always",
                "service": [
                    {
                        "name": "TCP_8081"
                    }
                ],
                "srcaddr": [
                    {
                        "name": "n_10.0.20.0_24"
                    }
                ],
                "srcintf": [
                    {
                        "name": "Internal"
                    }
                ],
                "state": "foo"
            },
            "name": "Firewall Policy"
        }
    ]
}
ok: [localhost] => (item=Internal->Internet2-[{'name': 'n_10.0.10.0_24'}, {'name': 'n_172.16.0.0_24'}, {'name': 'TCP_8080'}]) => {
    "msg": [
        {
            "fortios_firewall_policy": {
                "action": "accept",
                "dstaddr": [
                    {
                        "name": "n_172.16.0.0_24"
                    }
                ],
                "dstintf": [
                    {
                        "name": "DMZ"
                    }
                ],
                "firewall_policy": null,
                "name": "Internal->Internet2",
                "nat": "disable",
                "policyid": "1",
                "schedule": "always",
                "service": [
                    {
                        "name": "TCP_8080"
                    }
                ],
                "srcaddr": [
                    {
                        "name": "n_10.0.10.0_24"
                    }
                ],
                "srcintf": [
                    {
                        "name": "Internal"
                    }
                ],
                "state": "foo"
            },
            "name": "Firewall Policy"
        }
    ]
}
ok: [localhost] => (item=Internal->Internet2-[{'name': 'n_10.0.10.0_24'}, {'name': 'n_172.16.0.0_24'}, {'name': 'TCP_8081'}]) => {
    "msg": [
        {
            "fortios_firewall_policy": {
                "action": "accept",
                "dstaddr": [
                    {
                        "name": "n_172.16.0.0_24"
                    }
                ],
                "dstintf": [
                    {
                        "name": "DMZ"
                    }
                ],
                "firewall_policy": null,
                "name": "Internal->Internet2",
                "nat": "disable",
                "policyid": "1",
                "schedule": "always",
                "service": [
                    {
                        "name": "TCP_8081"
                    }
                ],
                "srcaddr": [
                    {
                        "name": "n_10.0.10.0_24"
                    }
                ],
                "srcintf": [
                    {
                        "name": "Internal"
                    }
                ],
                "state": "foo"
            },
            "name": "Firewall Policy"
        }
    ]
}
ok: [localhost] => (item=Internal->Internet2-[{'name': 'n_10.0.20.0_24'}, {'name': 'n_172.16.0.0_24'}, {'name': 'TCP_8080'}]) => {
    "msg": [
        {
            "fortios_firewall_policy": {
                "action": "accept",
                "dstaddr": [
                    {
                        "name": "n_172.16.0.0_24"
                    }
                ],
                "dstintf": [
                    {
                        "name": "DMZ"
                    }
                ],
                "firewall_policy": null,
                "name": "Internal->Internet2",
                "nat": "disable",
                "policyid": "1",
                "schedule": "always",
                "service": [
                    {
                        "name": "TCP_8080"
                    }
                ],
                "srcaddr": [
                    {
                        "name": "n_10.0.20.0_24"
                    }
                ],
                "srcintf": [
                    {
                        "name": "Internal"
                    }
                ],
                "state": "foo"
            },
            "name": "Firewall Policy"
        }
    ]
}
ok: [localhost] => (item=Internal->Internet2-[{'name': 'n_10.0.20.0_24'}, {'name': 'n_172.16.0.0_24'}, {'name': 'TCP_8081'}]) => {
    "msg": [
        {
            "fortios_firewall_policy": {
                "action": "accept",
                "dstaddr": [
                    {
                        "name": "n_172.16.0.0_24"
                    }
                ],
                "dstintf": [
                    {
                        "name": "DMZ"
                    }
                ],
                "firewall_policy": null,
                "name": "Internal->Internet2",
                "nat": "disable",
                "policyid": "1",
                "schedule": "always",
                "service": [
                    {
                        "name": "TCP_8081"
                    }
                ],
                "srcaddr": [
                    {
                        "name": "n_10.0.20.0_24"
                    }
                ],
                "srcintf": [
                    {
                        "name": "Internal"
                    }
                ],
                "state": "foo"
            },
            "name": "Firewall Policy"
        }
    ]
}

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

【讨论】:

  • 谢谢 Larsks,让我测试一下,
  • 嗨 Larsks,我将以下代码粘贴到我的角色文件中,但出现找不到 policyid 的错误
  • 我发布的示例按书面方式运行。你可以看到完整的运行here。如果您遇到错误,要么您没有完全运行我在此处发布的代码,要么正在发生某种奇怪的版本偏差。您使用的是哪个版本的 Ansible?
  • 嗨 Larsks,似乎有一些格式问题,经过几次尝试和调整缩进后有点高兴。我有两个问题,似乎循环运行了 8 次,但我只想每个策略运行一次(本例中的策略 ID 为 0 和 1)。当我将 var 保存在同一个文件中时,没有问题,但是当我将 var 移动到 var 文件时,出现错误。运行了 8 个循环,我收到错误消息:'str object' has no attribute 'name'\n\n,可能它正在尝试获取某些错误键的名称
  • 也许按照@Zeitounator 的要求更新您的问题,因为不清楚您希望如何将策略变量(例如srcaddr)中的多个值映射到fortios_firewall_policy 模块的单个调用中.您在问题中显示的示例不是很具体。
【解决方案2】:

您的嵌套列表有点乏味。一个简单的例子是

例如如果你的 YAML 数据文件看起来像这样

dstaddr:
      - name: "n_8.8.8.8_32"
      - name: "n_7.8.8.8_32"

你可以循环使用

- name: load vars
  include_vars: "data.yml"

- name: with list of items looping
  debug:
    msg: "{{ item }}"
  with_list: "{{ dstaddr}}"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-07
    • 1970-01-01
    • 2013-07-18
    • 1970-01-01
    相关资源
    最近更新 更多