# Buggy code
def map_params_to_obj(module):
    vrfs = module.params.get("vrfs")
    if not vrfs:
        if not module.params["name"] and module.params["purge"]:
            return list()
        elif not module.params["name"]:
            module.fail_json(msg="name is required")
        collection = [{"name": module.params["name"]}]
    else:
        collection = list()
        for item in vrfs:
            if not isinstance(item, dict):
                collection.append({"name": item})
            elif "name" not in item:
                module.fail_json(msg="name is required")
            else:
                collection.append(item)

    objects = list()

    for item in collection:
        get_value = partial(get_param_value, item=item, module=module)
        item["description"] = get_value("description")
        item["rd"] = get_value("rd")
        item["interfaces"] = get_value("interfaces")
        item["state"] = get_value("state")
        item["route_import"] = get_value("route_import")
        item["route_export"] = get_value("route_export")
        item["route_both"] = get_value("route_both")
        item["associated_interfaces"] = get_value("associated_interfaces")
        objects.append(item)

    return objects


# Traceback (TypeError)
ansible-playbook 2.5.4
config file = None
configured module search path = [u'/home/e600790/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/local/lib/python2.7/dist-packages/ansible
executable location = /usr/local/bin/ansible-playbook
python version = 2.7.13 (default, Nov 24 2017, 17:33:09) [GCC 6.3.0 20170516]
No config file found; using defaults
setting up inventory plugins
Set default localhost to localhost
Parsed /media/sf_Shared/ansible/static_route/inventory inventory source with ini plugin
Loading callback plugin default of type stdout, v2.0 from /usr/local/lib/python2.7/dist-packages/ansible/plugins/callback/default.pyc

PLAYBOOK: swenet-vrf.yml ****************************************************************************************************************************************************************************
1 plays in swenet-vrf.yml

PLAY [vrf] ******************************************************************************************************************************************************************************************
META: ran handlers

TASK [vrf definition] ***************************************************************************************************************************************************************************
task path: /media/sf_Shared/git/prod-network/swenet-vrf.yml:43
<ix-test-pe01.net.dcinf.se> attempting to start connection
<ix-test-pe01.net.dcinf.se> using connection plugin network_cli
<ix-test-pe02.net.dcinf.se> attempting to start connection
<ix-test-pe02.net.dcinf.se> using connection plugin network_cli
<ix-test-pe01.net.dcinf.se> local domain socket does not exist, starting it
<ix-test-pe01.net.dcinf.se> control socket path is /home/e600790/.ansible/pc/97af846ba3
<ix-test-pe01.net.dcinf.se> <ix-test-pe01.net.dcinf.se> ESTABLISH CONNECTION FOR USER: e600790 on PORT 22 TO ix-test-pe01.net.dcinf.se
<ix-test-pe01.net.dcinf.se> <ix-test-pe01.net.dcinf.se> ssh connection done, setting terminal
<ix-test-pe01.net.dcinf.se> <ix-test-pe01.net.dcinf.se> loaded terminal plugin for network_os ios
<ix-test-pe01.net.dcinf.se> <ix-test-pe01.net.dcinf.se> loaded cliconf plugin for network_os ios
<ix-test-pe01.net.dcinf.se> <ix-test-pe01.net.dcinf.se> firing event: on_open_shell()
<ix-test-pe01.net.dcinf.se> <ix-test-pe01.net.dcinf.se> ssh connection has completed successfully
<ix-test-pe01.net.dcinf.se> connection to remote device started successfully
<ix-test-pe01.net.dcinf.se> local domain socket listeners started successfully
<ix-test-pe01.net.dcinf.se>
<ix-test-pe01.net.dcinf.se> local domain socket path is /home/e600790/.ansible/pc/97af846ba3
<ix-test-pe02.net.dcinf.se> local domain socket does not exist, starting it
<ix-test-pe02.net.dcinf.se> control socket path is /home/e600790/.ansible/pc/c420ed9159
<ix-test-pe02.net.dcinf.se> <ix-test-pe02.net.dcinf.se> ESTABLISH CONNECTION FOR USER: e600790 on PORT 22 TO ix-test-pe02.net.dcinf.se
<ix-test-pe02.net.dcinf.se> <ix-test-pe02.net.dcinf.se> ssh connection done, setting terminal
<ix-test-pe02.net.dcinf.se> <ix-test-pe02.net.dcinf.se> loaded terminal plugin for network_os ios
<ix-test-pe02.net.dcinf.se> <ix-test-pe02.net.dcinf.se> loaded cliconf plugin for network_os ios
<ix-test-pe02.net.dcinf.se> <ix-test-pe02.net.dcinf.se> firing event: on_open_shell()
<ix-test-pe02.net.dcinf.se> <ix-test-pe02.net.dcinf.se> ssh connection has completed successfully
<ix-test-pe02.net.dcinf.se> connection to remote device started successfully
<ix-test-pe02.net.dcinf.se> local domain socket listeners started successfully
<ix-test-pe02.net.dcinf.se>
<ix-test-pe02.net.dcinf.se> local domain socket path is /home/e600790/.ansible/pc/c420ed9159
Using module file /home/e600790/.ansible/plugins/modules/devel_ios_vrf.py
<ix-test-pe02.net.dcinf.se> ESTABLISH LOCAL CONNECTION FOR USER: e600790
<ix-test-pe02.net.dcinf.se> EXEC /bin/sh -c '( umask 77 &amp;&amp; mkdir -p "` echo /home/e600790/.ansible/tmp/ansible-local-1868dyi_qh/ansible-tmp-1529046216.44-94701435360358 `" &amp;&amp; echo ansible-tmp-1529046216.44-94701435360358="` echo /home/e600790/.ansible/tmp/ansible-local-1868dyi_qh/ansible-tmp-1529046216.44-94701435360358 `" ) &amp;&amp; sleep 0'
Using module file /home/e600790/.ansible/plugins/modules/devel_ios_vrf.py
<ix-test-pe01.net.dcinf.se> ESTABLISH LOCAL CONNECTION FOR USER: e600790
<ix-test-pe01.net.dcinf.se> EXEC /bin/sh -c '( umask 77 &amp;&amp; mkdir -p "` echo /home/e600790/.ansible/tmp/ansible-local-1868dyi_qh/ansible-tmp-1529046216.44-237853136648068 `" &amp;&amp; echo ansible-tmp-1529046216.44-237853136648068="` echo /home/e600790/.ansible/tmp/ansible-local-1868dyi_qh/ansible-tmp-1529046216.44-237853136648068 `" ) &amp;&amp; sleep 0'
<ix-test-pe02.net.dcinf.se> PUT /home/e600790/.ansible/tmp/ansible-local-1868dyi_qh/tmpttIp1v TO /home/e600790/.ansible/tmp/ansible-local-1868dyi_qh/ansible-tmp-1529046216.44-94701435360358/devel_ios_vrf.py
<ix-test-pe02.net.dcinf.se> EXEC /bin/sh -c 'chmod u+x /home/e600790/.ansible/tmp/ansible-local-1868dyi_qh/ansible-tmp-1529046216.44-94701435360358/ /home/e600790/.ansible/tmp/ansible-local-1868dyi_qh/ansible-tmp-1529046216.44-94701435360358/devel_ios_vrf.py &amp;&amp; sleep 0'
<ix-test-pe01.net.dcinf.se> PUT /home/e600790/.ansible/tmp/ansible-local-1868dyi_qh/tmp1K9JSV TO /home/e600790/.ansible/tmp/ansible-local-1868dyi_qh/ansible-tmp-1529046216.44-237853136648068/devel_ios_vrf.py
<ix-test-pe01.net.dcinf.se> EXEC /bin/sh -c 'chmod u+x /home/e600790/.ansible/tmp/ansible-local-1868dyi_qh/ansible-tmp-1529046216.44-237853136648068/ /home/e600790/.ansible/tmp/ansible-local-1868dyi_qh/ansible-tmp-1529046216.44-237853136648068/devel_ios_vrf.py &amp;&amp; sleep 0'
<ix-test-pe02.net.dcinf.se> EXEC /bin/sh -c '/usr/bin/python /home/e600790/.ansible/tmp/ansible-local-1868dyi_qh/ansible-tmp-1529046216.44-94701435360358/devel_ios_vrf.py &amp;&amp; sleep 0'
<ix-test-pe01.net.dcinf.se> EXEC /bin/sh -c '/usr/bin/python /home/e600790/.ansible/tmp/ansible-local-1868dyi_qh/ansible-tmp-1529046216.44-237853136648068/devel_ios_vrf.py &amp;&amp; sleep 0'
<ix-test-pe02.net.dcinf.se> EXEC /bin/sh -c 'rm -f -r /home/e600790/.ansible/tmp/ansible-local-1868dyi_qh/ansible-tmp-1529046216.44-94701435360358/ > /dev/null 2>&amp;1 &amp;&amp; sleep 0'
<ix-test-pe01.net.dcinf.se> EXEC /bin/sh -c 'rm -f -r /home/e600790/.ansible/tmp/ansible-local-1868dyi_qh/ansible-tmp-1529046216.44-237853136648068/ > /dev/null 2>&amp;1 &amp;&amp; sleep 0'
The full traceback is:
Traceback (most recent call last):
File "/tmp/ansible_Aug5Jg/ansible_module_devel_ios_vrf.py", line 520, in <module>
main()
File "/tmp/ansible_Aug5Jg/ansible_module_devel_ios_vrf.py", line 497, in main
commands = map_obj_to_commands(update_objects(want, have), module)
File "/tmp/ansible_Aug5Jg/ansible_module_devel_ios_vrf.py", line 428, in update_objects
elif value != item[key]:
TypeError: 'NoneType' object has no attribute '__getitem__'

fatal: [ix-test-pe02.net.dcinf.se]: FAILED! => {
"changed": false,
"module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_Aug5Jg/ansible_module_devel_ios_vrf.py\", line 520, in <module>\n    main()\n  File \"/tmp/ansible_Aug5Jg/ansible_module_devel_ios_vrf.py\", line 497, in main\n    commands = map_obj_to_commands(update_objects(want, have), module)\n  File \"/tmp/ansible_Aug5Jg/ansible_module_devel_ios_vrf.py\", line 428, in update_objects\n    elif value != item[key]:\nTypeError: 'NoneType' object has no attribute '__getitem__'\n",
"module_stdout": "",
"msg": "MODULE FAILURE",
"rc": 1
}
The full traceback is:
Traceback (most recent call last):
File "/tmp/ansible_52bkKf/ansible_module_devel_ios_vrf.py", line 520, in <module>
main()
File "/tmp/ansible_52bkKf/ansible_module_devel_ios_vrf.py", line 497, in main
commands = map_obj_to_commands(update_objects(want, have), module)
File "/tmp/ansible_52bkKf/ansible_module_devel_ios_vrf.py", line 428, in update_objects
elif value != item[key]:
TypeError: 'NoneType' object has no attribute '__getitem__'

fatal: [ix-test-pe01.net.dcinf.se]: FAILED! => {
"changed": false,
"module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_52bkKf/ansible_module_devel_ios_vrf.py\", line 520, in <module>\n    main()\n  File \"/tmp/ansible_52bkKf/ansible_module_devel_ios_vrf.py\", line 497, in main\n    commands = map_obj_to_commands(update_objects(want, have), module)\n  File \"/tmp/ansible_52bkKf/ansible_module_devel_ios_vrf.py\", line 428, in update_objects\n    elif value != item[key]:\nTypeError: 'NoneType' object has no attribute '__getitem__'\n",
"module_stdout": "",
"msg": "MODULE FAILURE",
"rc": 1
}

NO MORE HOSTS LEFT **********************************************************************************************************************************************************************************
to retry, use: --limit @/media/sf_Shared/git/prod-network/swenet-vrf.retry

PLAY RECAP ******************************************************************************************************************************************************************************************
ix-test-pe01.net.dcinf.se  : ok=0    changed=0    unreachable=0    failed=1
ix-test-pe02.net.dcinf.se  : ok=0    changed=0    unreachable=0    failed=1

# Fixed code
def map_params_to_obj(module):
    vrfs = module.params.get("vrfs")
    if not vrfs:
        if not module.params["name"] and module.params["purge"]:
            return list()
        elif not module.params["name"]:
            module.fail_json(msg="name is required")
        collection = [{"name": module.params["name"]}]
    else:
        collection = list()
        for item in vrfs:
            if not isinstance(item, dict):
                collection.append({"name": item})
            elif "name" not in item:
                module.fail_json(msg="name is required")
            else:
                collection.append(item)

    objects = list()
    for item in collection:
        get_value = partial(get_param_value, item=item, module=module)
        item["description"] = get_value("description")
        item["rd"] = get_value("rd")
        item["interfaces"] = get_value("interfaces")
        item["state"] = get_value("state")
        item["route_import"] = get_value("route_import")
        item["route_export"] = get_value("route_export")
        item["route_both"] = get_value("route_both")
        item["route_import_ipv4"] = get_value("route_import_ipv4")
        item["route_export_ipv4"] = get_value("route_export_ipv4")
        item["route_both_ipv4"] = get_value("route_both_ipv4")
        item["route_import_ipv6"] = get_value("route_import_ipv6")
        item["route_export_ipv6"] = get_value("route_export_ipv6")
        item["route_both_ipv6"] = get_value("route_both_ipv6")
        both_addresses_family = ["", "_ipv6", "_ipv4"]
        for address_family in both_addresses_family:
            if item["route_both%s" % address_family]:
                if not item["route_export%s" % address_family]:
                    item["route_export%s" % address_family] = list()
                if not item["route_import%s" % address_family]:
                    item["route_import%s" % address_family] = list()
                item["route_export%s" % address_family].extend(
                    get_value("route_both%s" % address_family)
                )
                item["route_import%s" % address_family].extend(
                    get_value("route_both%s" % address_family)
                )
        item["associated_interfaces"] = get_value("associated_interfaces")
        objects.append(item)

    return objects