Search code examples
ansiblejinja2fortigate

Fortinet Address Loop with subelements filter


I'm a newby at Ansible and am using the fortinet.fortios modules.

I'm having a problem with fortios_firewall_addrgrp.

I follow this previous post, Loop with subelements filter, and I have been trying to use that as my base.

My var is a bit different as I want to keep this as DRY as possible. I have this set in my variables:

address_nets:
  - name: azure_nets
    addresses:
      - member: azure-lw
        subnet: 10.37.0.0/16
      - member: azure-lw2
        subnet: 10.38.0.0/16
  - name: dan
    addresses:
      - member: dan1
        subnet: 10.41.0.0/16
      - member: dan2
        subnet: 10.40.0.0/16        

So basically the firewall address group would look like:

   azure_nets
    member: azure-lw
    member: azure-lw2
   dan
    member: dan1
    member: dan2

My module is this:

  - name: Address Groups 
    fortios_firewall_addrgrp:
      vdom:  "{{ vdom }}"
      access_token: "{{ token }}"
      state: present
      firewall_addrgrp:
        name: "{{ item.name }}"
        member: "{{ grp_members }}"
        allow_routing: "enable"
    vars:
      grp_members: "{{ [item.name] | product(item.addresses) | map('join', '-') | map('community.general.dict_kv', 'member') }}"
    loop: "{{ address_nets }}"

If I run it as debug, I get the following:

ok: [wg-cat-fw] => (item={'name': 'azure_nets', 'addresses': [{'member': 'azure-lw', 'subnet': '10.37.0.0/16'}, {'member': 'azure-lw2', 'subnet': '10.38.0.0/16'}]}) => {
    "msg": [
        {
            "name": "azure_nets-{'member': 'azure-lw', 'subnet': '10.37.0.0/16'}"
        },
        {
            "name": "azure_nets-{'member': 'azure-lw2', 'subnet': '10.38.0.0/16'}"
        }
    ]
}
ok: [wg-cat-fw] => (item={'name': 'dan', 'addresses': [{'member': 'dan1', 'subnet': '10.41.0.0/16'}, {'member': 'dan2', 'subnet': '10.40.0.0/16'}]}) => {
    "msg": [
        {
            "name": "dan-{'member': 'dan1', 'subnet': '10.41.0.0/16'}"
        },
        {
            "name": "dan-{'member': 'dan2', 'subnet': '10.40.0.0/16'}"
        }
    ]
}

Any thoughts on how I can change this into the desired output, which would be:

ok: [localhost] => (item={'name': ''azure_nets', 'addresses': [{'member': 'azure-lw', 'subnet': '10.37.0.0/16'}, {'member': 'azure-lw2', 'subnet': '10.38.0.0/16'}]}) => {
    "msg": [
        {
            "name": "azure-lw"
        },
        {
            "name": "azure-lw2"
        }
    ]
}
ok: [localhost] => (item={'name': 'dan', 'addresses': [{'member': 'dan1', 'subnet': '10.41.0.0/16'}, {'member': 'dan2', 'subnet': '10.40.0.0/16'}]}) => {
    "msg": [
        {
            "name": "dan1"
        },
        {
            "name": "dan2"
        }
    ]
}

And here is the output of the module:

TASK [Address Groups] ***************************************************************************************************************************************************************************************************************************************************failed: [wg-cat-fw] (item={'name': 'azure_nets', 'addresses': [{'member': 'azure-lw', 'subnet': '10.37.0.0/16'}, {'member': 'azure-lw2', 'subnet': '10.38.0.0/16'}]}) => {"ansible_loop_var": "item", "changed": false, "item": {"addresses": [{"member": "azure-lw", "subnet": "10.37.0.0/16"}, {"member": "azure-lw2", "subnet": "10.38.0.0/16"}], "name": "azure_nets"}, "msg": "Unsupported parameters for (fortios_firewall_addrgrp) module: firewall_addrgrp.member.member. Supported parameters include: access_token, state, vdom, ********_log, firewall_addrgrp, member_state, member_path."}
failed: [wg-cat-fw] (item={'name': 'dan', 'addresses': [{'member': 'dan1', 'subnet': '10.41.0.0/16'}, {'member': 'dan2', 'subnet': '10.40.0.0/16'}]}) => {"ansible_loop_var": "item", "changed": false, "item": {"addresses": [{"member": "dan1", "subnet": "10.41.0.0/16"}, {"member": "dan2", "subnet": "10.40.0.0/16"}], "name": "dan"}, "msg": "Unsupported parameters for (fortios_firewall_addrgrp) module: firewall_addrgrp.member.member. Supported parameters include: member_state, member_path, access_token, state, ********_log, firewall_addrgrp, vdom."}

Solution

  • loop over addresses | map the attribute member | create a dictionary from the output with the key member

    - debug:
        msg: "{{ item.addresses | map(attribute='member') | map('community.general.dict_kv', 'member') }}"
      loop: "{{ address_nets }}"
    
    ok: [localhost] => (item={'name': 'azure_nets', 'addresses': [{'member': 'azure-lw', 'subnet': '10.37.0.0/16'}, {'member': 'azure-lw2', 'subnet': '10.38.0.0/16'}]}) => {
        "msg": [
            {
                "member": "azure-lw"
            },
            {
                "member": "azure-lw2"
            }
        ]
    }
    ok: [localhost] => (item={'name': 'dan', 'addresses': [{'member': 'dan1', 'subnet': '10.41.0.0/16'}, {'member': 'dan2', 'subnet': '10.40.0.0/16'}]}) => {
        "msg": [
            {
                "member": "dan1"
            },
            {
                "member": "dan2"
            }
        ]
    }