# Buggy code
def map_obj_to_commands(updates, module):
    commands = list()
    want, have = updates
    state = module.params["state"]
    purge = module.params["purge"]

    for w in want:
        name = w["name"]
        description = w["description"]
        vni = w["vni"]
        rd = w["rd"]
        admin_state = w["admin_state"]
        interfaces = w.get("interfaces") or []
        state = w["state"]
        del w["state"]

        obj_in_have = search_obj_in_list(name, have)

        if state == "absent" and obj_in_have:
            commands.append("no vrf context {0}".format(name))

        elif state == "present":
            if not obj_in_have:
                commands.append("vrf context {0}".format(name))
                if rd and rd != "":
                    commands.append("rd {0}".format(rd))
                if description:
                    commands.append("description {0}".format(description))
                if vni and vni != "":
                    commands.append("vni {0}".format(vni))
                if admin_state == "up":
                    commands.append("no shutdown")
                elif admin_state == "down":
                    commands.append("shutdown")

                if commands:
                    if vni:
                        if have.get("vni") and have.get("vni") != "":
                            commands.insert(1, "no vni {0}".format(have["vni"]))
                commands.append("exit")
                if interfaces:
                    for i in interfaces:
                        commands.append("interface {0}".format(i))
                        commands.append("no switchport")
                        commands.append("vrf member {0}".format(name))

            else:
                if interfaces:
                    if not obj_in_have["interfaces"]:
                        for i in interfaces:
                            commands.append("vrf context {0}".format(name))
                            commands.append("exit")
                            commands.append("interface {0}".format(i))
                            commands.append("no switchport")
                            commands.append("vrf member {0}".format(name))

                    elif set(interfaces) != set(obj_in_have["interfaces"]):
                        missing_interfaces = list(
                            set(interfaces) - set(obj_in_have["interfaces"])
                        )
                        for i in missing_interfaces:
                            commands.append("vrf context {0}".format(name))
                            commands.append("exit")
                            commands.append("interface {0}".format(i))
                            commands.append("no switchport")
                            commands.append("vrf member {0}".format(name))

                        superfluous_interfaces = list(
                            set(obj_in_have["interfaces"]) - set(interfaces)
                        )
                        for i in superfluous_interfaces:
                            commands.append("vrf context {0}".format(name))
                            commands.append("exit")
                            commands.append("interface {0}".format(i))
                            commands.append("no switchport")
                            commands.append("no vrf member {0}".format(name))

    if purge:
        existing = get_existing_vrfs(module)
        if existing:
            for h in existing:
                if h["name"] in ("default", "management"):
                    pass
                else:
                    obj_in_want = search_obj_in_list(h["name"], want)
                    if not obj_in_want:
                        commands.append("no vrf context {0}".format(h["name"]))

    return commands


# Traceback (AttributeError)
TASK [victorock.overlay-nxos-leaf : Ensure state of VRF for VNIs] ************************************************************
task path: /Users/jdacosta/Devel/ansible-netops/cisco/nxos/applications/fabric/europe-central-fr1/roles/victorock.overlay-nxos-leaf/tasks/vni.yml:14
<127.0.0.1> attempting to start connection
<127.0.0.1> using connection plugin network_cli
<127.0.0.1> found existing local domain socket, using it!
<127.0.0.1> updating play_context for connection
<127.0.0.1>
<127.0.0.1> local domain socket path is /Users/jdacosta/.ansible/pc/32fbfb2e00
Using module_utils file /Library/Python/2.7/site-packages/ansible/module_utils/network/__init__.py
Using module_utils file /Library/Python/2.7/site-packages/ansible/module_utils/basic.py
Using module_utils file /Library/Python/2.7/site-packages/ansible/module_utils/network/nxos/__init__.py
Using module_utils file /Library/Python/2.7/site-packages/ansible/module_utils/network/common/utils.py
Using module_utils file /Library/Python/2.7/site-packages/ansible/module_utils/network/common/__init__.py
Using module_utils file /Library/Python/2.7/site-packages/ansible/module_utils/network/nxos/nxos.py
Using module_utils file /Library/Python/2.7/site-packages/ansible/module_utils/_text.py
Using module_utils file /Library/Python/2.7/site-packages/ansible/module_utils/parsing/convert_bool.py
Using module_utils file /Library/Python/2.7/site-packages/ansible/module_utils/parsing/__init__.py
Using module_utils file /Library/Python/2.7/site-packages/ansible/module_utils/pycompat24.py
Using module_utils file /Library/Python/2.7/site-packages/ansible/module_utils/six/__init__.py
Using module_utils file /Library/Python/2.7/site-packages/ansible/module_utils/connection.py
Using module_utils file /Library/Python/2.7/site-packages/ansible/module_utils/urls.py
Using module file /Library/Python/2.7/site-packages/ansible/modules/network/nxos/nxos_vrf.py
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: jdacosta
<127.0.0.1> EXEC /bin/sh -c 'echo ~ &amp;&amp; sleep 0'
<127.0.0.1> EXEC /bin/sh -c '( umask 77 &amp;&amp; mkdir -p "` echo /Users/jdacosta/.ansible/tmp/ansible-tmp-1519162691.84-261532122578571 `" &amp;&amp; echo ansible-tmp-1519162691.84-261532122578571="` echo /Users/jdacosta/.ansible/tmp/ansible-tmp-1519162691.84-261532122578571 `" ) &amp;&amp; sleep 0'
<127.0.0.1> PUT /Users/jdacosta/.ansible/tmp/ansible-local-27233QmXSr2/tmp2bG1bG TO /Users/jdacosta/.ansible/tmp/ansible-tmp-1519162691.84-261532122578571/nxos_vrf.py
<127.0.0.1> EXEC /bin/sh -c 'chmod u+x /Users/jdacosta/.ansible/tmp/ansible-tmp-1519162691.84-261532122578571/ /Users/jdacosta/.ansible/tmp/ansible-tmp-1519162691.84-261532122578571/nxos_vrf.py &amp;&amp; sleep 0'
<127.0.0.1> EXEC /bin/sh -c '/usr/bin/python /Users/jdacosta/.ansible/tmp/ansible-tmp-1519162691.84-261532122578571/nxos_vrf.py &amp;&amp; sleep 0'
<127.0.0.1> EXEC /bin/sh -c 'rm -f -r /Users/jdacosta/.ansible/tmp/ansible-tmp-1519162691.84-261532122578571/ > /dev/null 2>&amp;1 &amp;&amp; sleep 0'
The full traceback is:
Traceback (most recent call last):
File "/var/folders/jv/29pmt_2j39ngz8ftz40j1mn00000gn/T/ansible_Tj2nE6/ansible_module_nxos_vrf.py", line 467, in <module>
main()
File "/var/folders/jv/29pmt_2j39ngz8ftz40j1mn00000gn/T/ansible_Tj2nE6/ansible_module_nxos_vrf.py", line 453, in main
commands = map_obj_to_commands((want, have), module)
File "/var/folders/jv/29pmt_2j39ngz8ftz40j1mn00000gn/T/ansible_Tj2nE6/ansible_module_nxos_vrf.py", line 258, in map_obj_to_commands
if have.get('vni') and have.get('vni') != '':
AttributeError: 'list' object has no attribute 'get'

failed: [leaf01] (item=nxos_vrf_vni tenant01) => {
"changed": false,
"failed": true,
"nxos_vrf_vni": {
"key": "l2_150_10150",
"value": {
"multicast": {
"group": "239.0.0.150"
},
"name": "l2_150_10150",
"route": {
"distinguisher": "auto",
"target_both": "auto"
},
"states": {
"admin": "up",
"feature": "enabled",
"shutdown": false,
"state": "present"
},
"svi": "10.1.150.1/24",
"vlan": 150,
"vni": 10150,
"vrf": "tenant01"
}
},
"rc": 1
}

MSG:

MODULE FAILURE


MODULE_STDERR:

Traceback (most recent call last):
File "/var/folders/jv/29pmt_2j39ngz8ftz40j1mn00000gn/T/ansible_Tj2nE6/ansible_module_nxos_vrf.py", line 467, in <module>
main()
File "/var/folders/jv/29pmt_2j39ngz8ftz40j1mn00000gn/T/ansible_Tj2nE6/ansible_module_nxos_vrf.py", line 453, in main
commands = map_obj_to_commands((want, have), module)
File "/var/folders/jv/29pmt_2j39ngz8ftz40j1mn00000gn/T/ansible_Tj2nE6/ansible_module_nxos_vrf.py", line 258, in map_obj_to_commands
if have.get('vni') and have.get('vni') != '':
AttributeError: 'list' object has no attribute 'get'

# Fixed code
def map_obj_to_commands(updates, module):
    commands = list()
    want, have = updates
    state = module.params["state"]
    purge = module.params["purge"]

    args = ("rd", "description", "vni")

    for w in want:
        name = w["name"]
        admin_state = w["admin_state"]
        vni = w["vni"]
        interfaces = w.get("interfaces") or []
        state = w["state"]
        del w["state"]

        obj_in_have = search_obj_in_list(name, have)

        if state == "absent" and obj_in_have:
            commands.append("no vrf context {0}".format(name))

        elif state == "present":
            if not obj_in_have:
                commands.append("vrf context {0}".format(name))
                for item in args:
                    candidate = w.get(item)
                    if candidate:
                        cmd = item + " " + str(candidate)
                        commands.append(cmd)
                if admin_state == "up":
                    commands.append("no shutdown")
                elif admin_state == "down":
                    commands.append("shutdown")
                commands.append("exit")

                if interfaces:
                    for i in interfaces:
                        commands.append("interface {0}".format(i))
                        commands.append("no switchport")
                        commands.append("vrf member {0}".format(name))

            else:
                # If vni is already configured on vrf, unconfigure it first.
                if vni:
                    if obj_in_have.get("vni") and vni != obj_in_have.get("vni"):
                        commands.append("no vni {0}".format(obj_in_have.get("vni")))

                for item in args:
                    candidate = w.get(item)
                    if candidate and candidate != obj_in_have.get(item):
                        cmd = item + " " + str(candidate)
                        commands.append(cmd)
                if admin_state and admin_state != obj_in_have.get("admin_state"):
                    if admin_state == "up":
                        commands.append("no shutdown")
                    elif admin_state == "down":
                        commands.append("shutdown")

                if commands:
                    commands.insert(0, "vrf context {0}".format(name))
                    commands.append("exit")

                if interfaces:
                    if not obj_in_have["interfaces"]:
                        for i in interfaces:
                            commands.append("vrf context {0}".format(name))
                            commands.append("exit")
                            commands.append("interface {0}".format(i))
                            commands.append("no switchport")
                            commands.append("vrf member {0}".format(name))

                    elif set(interfaces) != set(obj_in_have["interfaces"]):
                        missing_interfaces = list(
                            set(interfaces) - set(obj_in_have["interfaces"])
                        )
                        for i in missing_interfaces:
                            commands.append("vrf context {0}".format(name))
                            commands.append("exit")
                            commands.append("interface {0}".format(i))
                            commands.append("no switchport")
                            commands.append("vrf member {0}".format(name))

                        superfluous_interfaces = list(
                            set(obj_in_have["interfaces"]) - set(interfaces)
                        )
                        for i in superfluous_interfaces:
                            commands.append("vrf context {0}".format(name))
                            commands.append("exit")
                            commands.append("interface {0}".format(i))
                            commands.append("no switchport")
                            commands.append("no vrf member {0}".format(name))

    if purge:
        existing = get_existing_vrfs(module)
        if existing:
            for h in existing:
                if h["name"] in ("default", "management"):
                    pass
                else:
                    obj_in_want = search_obj_in_list(h["name"], want)
                    if not obj_in_want:
                        commands.append("no vrf context {0}".format(h["name"]))

    return commands