如何在ansible中一起使用多个with_items

how to use mutiple with_items together in ansible

这里我附上了Json的输入格式,它由两个数组,对象和目标组成,我尝试使用Ansible with_item模块将对象循环到Uri模块中。

此概念适用于单个数组,但当我尝试将两个数组项都调用到 uri 时遇到问题。 有什么办法可以同时使用两个项目数组

Json 输入

{
  "objects": [
    {
      "item": {
          "action": "deny",
          "srcaddr": "IP_100.1.2.3",
          "src_ipv4": "ipmask",
          "src_ipv4addr": "100.1.2.3/32",
          "dstaddr": "IP_100.4.5.6",
          "dst_ipv4addr": "100.4.5.6/32",
          "dst_ipv4": "ipmask",
          "port": "65511",
          "protocol": "tcp"
      }
    },
    {
      "item": {
          "action": "deny",
          "srcaddr": "IP_200.1.2.3",
          "src_ipv4": "ipmask",
          "src_ipv4addr": "200.1.2.3/32",
          "dstaddr": "IP_100.4.5.6",
          "dst_ipv4addr": "100.4.5.6/32",
          "dst_ipv4": "ipmask",
          "port": "65511",
          "protocol": "tcp"
      }
    }
  ],
    "targets": [
    {
      "item": {
        "domain": "dom-cn-1",
        "fingerprint": "9125544D272B5AD28F3E9AB7BC8AA3F276E45064",
        "mgmt_password": "admin123",
        "mgmt_server": "192.168.10.20",
        "target_fw": "dev-cn-c1"
      }
    },
    {
      "item": {
        "domain": "dom-cn-2",
        "fingerprint": "9125544D272B5AD28F3E9AB7BC8AA3F276E45064",
        "mgmt_password": "admin123",
        "mgmt_server": "192.168.10.20",
        "target_fw": "dev-cn-c3"
      }
    }
  ]
}

基于uri模块的任务

- name: upating the task status
    uri:
      url: http://192.168.30.20/api/v2/job_templates/7/launch/
      method: POST
      body: '{ "extra_vars": { "action": "{{ item.item.action }}", "srcaddr": "{{ item.item.srcaddr }}", "src_ipv4": "{{ item.item.src_ipv4 }}", "mgmt_password": "{{ item.item.mgmt_password }}", "mgmt_server": "{{ item.item.mgmt_server }}", "targets": [  "{{ item.item.target_fw }}" ]} }'
      status_code: 201
      body_format: json
      force_basic_auth: yes
      validate_certs: no
      user: "admin"
      password: "admin123"
      headers:
          Accept: "application/json"
          Content-Type: "application/json"
    with_items: "{{ tmpdata.objects }}"

预期响应

"msg": [
    "action is deny",
    "srcaddr is IP_100.1.2.3",
    "src_ipv4 is ipmask",
    "mgmt_password is admin123",
    "mgmt_server is 192.168.10.20",
    "target_fw is dev-cn-c1"
]


"msg": [
    "action is deny",
    "srcaddr is IP_200.1.2.3",
    "src_ipv4 is ipmask",
    "mgmt_password is admin123",
    "mgmt_server is 192.168.10.20",
    "target_fw is dev-cn-c1"
]


    "msg": [
    "action is deny",
    "srcaddr is IP_100.1.2.3",
    "src_ipv4 is ipmask",
    "mgmt_password is admin123",
    "mgmt_server is 192.168.10.20",
    "target_fw is dev-cn-c3"
]


"msg": [
    "action is deny",
    "srcaddr is IP_200.1.2.3",
    "src_ipv4 is ipmask",
    "mgmt_password is admin123",
    "mgmt_server is 192.168.10.20",
    "target_fw is dev-cn-c3"
]

您要实现的只是两个列表之间的乘积。非常幸运的是,ansible 有一个过滤器专门用于那个叫做.... product.

在我下面的示例中,我还清理了一些原始数据,以从原始数据中删除 item 条目,这些条目使结果不太清晰。我使用 map 过滤器来提取我们需要的属性。

以下剧本:

- name: product and map(attribute=) demo
  hosts: localhost
  gather_facts: false

  vars:
    # Your orig data on a single line for legibility
    tmpdata: {"objects": [{"item": {"action": "deny", "srcaddr": "IP_100.1.2.3", "src_ipv4": "ipmask", "src_ipv4addr": "100.1.2.3/32", "dstaddr": "IP_100.4.5.6", "dst_ipv4addr": "100.4.5.6/32", "dst_ipv4": "ipmask", "port": "65511", "protocol": "tcp"}}, {"item": {"action": "deny", "srcaddr": "IP_200.1.2.3", "src_ipv4": "ipmask", "src_ipv4addr": "200.1.2.3/32", "dstaddr": "IP_100.4.5.6", "dst_ipv4addr": "100.4.5.6/32", "dst_ipv4": "ipmask", "port": "65511", "protocol": "tcp"}}], "targets": [{"item": {"domain": "dom-cn-1", "fingerprint": "9125544D272B5AD28F3E9AB7BC8AA3F276E45064", "mgmt_password": "admin123", "mgmt_server": "192.168.10.20", "target_fw": "dev-cn-c1"}}, {"item": {"domain": "dom-cn-2", "fingerprint": "9125544D272B5AD28F3E9AB7BC8AA3F276E45064", "mgmt_password": "admin123", "mgmt_server": "192.168.10.20", "target_fw": "dev-cn-c3"}}]}

  tasks:
    - name: This is our final objects list for demo
      debug:
        msg: "{{ tmpdata.objects | map(attribute='item') | list }}"
        verbosity: 1

    - name: This is our final targets list for demo
      debug:
        msg: "{{ tmpdata.targets | map(attribute='item') | list }}"
        verbosity: 1

    - name: This is what the product list will look like
      debug:
        msg: >-
          {{
            tmpdata.objects | map(attribute='item')
            | product(tmpdata.targets | map(attribute='item'))
            | list
          }}
        verbosity: 1

    - name: And this how we can loop on the result
      vars:
        msg_content:
          - action is {{ item.0.action }}
          - srcaddr is {{ item.0.srcaddr }}
          - src_ipv4 is {{ item.0.src_ipv4 }}
          - mgmt_password is {{ item.1.mgmt_password }}
          - mgmt_server is {{ item.1.mgmt_server }}
          - target_fw is {{ item.1.target_fw }}
      debug:
        msg: "{{ msg_content }}"
      # Loop is equivalent to with_items here.
      # see https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html
      loop: >-
        {{
            tmpdata.objects | map(attribute='item')
            | product(tmpdata.targets | map(attribute='item'))
            | list
        }}

给(运行 自己用 -v 获取中间调试信息)

$ ansible-playbook playbook.yml

PLAY [product and map(attribute=) demo] ************************************************************************************************************************************************************************************************

TASK [This is our final objects list for demo] *****************************************************************************************************************************************************************************************
skipping: [localhost]

TASK [This is our final targets list for demo] *****************************************************************************************************************************************************************************************
skipping: [localhost]

TASK [This is what the product list will look like] ************************************************************************************************************************************************************************************
skipping: [localhost]

TASK [And this how we can loop on the result] ******************************************************************************************************************************************************************************************
ok: [localhost] => (item=[{'action': 'deny', 'srcaddr': 'IP_100.1.2.3', 'src_ipv4': 'ipmask', 'src_ipv4addr': '100.1.2.3/32', 'dstaddr': 'IP_100.4.5.6', 'dst_ipv4addr': '100.4.5.6/32', 'dst_ipv4': 'ipmask', 'port': '65511', 'protocol': 'tcp'}, {'domain': 'dom-cn-1', 'fingerprint': '9125544D272B5AD28F3E9AB7BC8AA3F276E45064', 'mgmt_password': 'admin123', 'mgmt_server': '192.168.10.20', 'target_fw': 'dev-cn-c1'}]) => {
    "msg": [
        "action is deny",
        "srcaddr is IP_100.1.2.3",
        "src_ipv4 is ipmask",
        "mgmt_password is admin123",
        "mgmt_server is 192.168.10.20",
        "target_fw is dev-cn-c1"
    ]
}
ok: [localhost] => (item=[{'action': 'deny', 'srcaddr': 'IP_100.1.2.3', 'src_ipv4': 'ipmask', 'src_ipv4addr': '100.1.2.3/32', 'dstaddr': 'IP_100.4.5.6', 'dst_ipv4addr': '100.4.5.6/32', 'dst_ipv4': 'ipmask', 'port': '65511', 'protocol': 'tcp'}, {'domain': 'dom-cn-2', 'fingerprint': '9125544D272B5AD28F3E9AB7BC8AA3F276E45064', 'mgmt_password': 'admin123', 'mgmt_server': '192.168.10.20', 'target_fw': 'dev-cn-c3'}]) => {
    "msg": [
        "action is deny",
        "srcaddr is IP_100.1.2.3",
        "src_ipv4 is ipmask",
        "mgmt_password is admin123",
        "mgmt_server is 192.168.10.20",
        "target_fw is dev-cn-c3"
    ]
}
ok: [localhost] => (item=[{'action': 'deny', 'srcaddr': 'IP_200.1.2.3', 'src_ipv4': 'ipmask', 'src_ipv4addr': '200.1.2.3/32', 'dstaddr': 'IP_100.4.5.6', 'dst_ipv4addr': '100.4.5.6/32', 'dst_ipv4': 'ipmask', 'port': '65511', 'protocol': 'tcp'}, {'domain': 'dom-cn-1', 'fingerprint': '9125544D272B5AD28F3E9AB7BC8AA3F276E45064', 'mgmt_password': 'admin123', 'mgmt_server': '192.168.10.20', 'target_fw': 'dev-cn-c1'}]) => {
    "msg": [
        "action is deny",
        "srcaddr is IP_200.1.2.3",
        "src_ipv4 is ipmask",
        "mgmt_password is admin123",
        "mgmt_server is 192.168.10.20",
        "target_fw is dev-cn-c1"
    ]
}
ok: [localhost] => (item=[{'action': 'deny', 'srcaddr': 'IP_200.1.2.3', 'src_ipv4': 'ipmask', 'src_ipv4addr': '200.1.2.3/32', 'dstaddr': 'IP_100.4.5.6', 'dst_ipv4addr': '100.4.5.6/32', 'dst_ipv4': 'ipmask', 'port': '65511', 'protocol': 'tcp'}, {'domain': 'dom-cn-2', 'fingerprint': '9125544D272B5AD28F3E9AB7BC8AA3F276E45064', 'mgmt_password': 'admin123', 'mgmt_server': '192.168.10.20', 'target_fw': 'dev-cn-c3'}]) => {
    "msg": [
        "action is deny",
        "srcaddr is IP_200.1.2.3",
        "src_ipv4 is ipmask",
        "mgmt_password is admin123",
        "mgmt_server is 192.168.10.20",
        "target_fw is dev-cn-c3"
    ]
}

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