# Buggy code
def has_different_config(self, net):
    """
    Evaluates an existing network and returns a tuple containing a boolean
    indicating if the configuration is different and a list of differences.

    :param net: the inspection output for an existing network
    :return: (bool, list)
    """
    different = False
    differences = []
    if self.parameters.driver and self.parameters.driver != net["Driver"]:
        different = True
        differences.append("driver")
    if self.parameters.driver_options:
        if not net.get("Options"):
            different = True
            differences.append("driver_options")
        else:
            for key, value in self.parameters.driver_options.items():
                if not net["Options"].get(key) or value != net["Options"][key]:
                    different = True
                    differences.append("driver_options.%s" % key)
    if self.parameters.ipam_driver:
        if not net.get("IPAM") or net["IPAM"]["Driver"] != self.parameters.ipam_driver:
            different = True
            differences.append("ipam_driver")
    if self.parameters.ipam_options:
        if not net.get("IPAM") or not net["IPAM"].get("Config"):
            different = True
            differences.append("ipam_options")
        else:
            for key, value in self.parameters.ipam_options.items():
                camelkey = None
                for net_key in net["IPAM"]["Config"][0]:
                    if key == net_key.lower():
                        camelkey = net_key
                        break
                if not camelkey:
                    # key not found
                    different = True
                    differences.append("ipam_options.%s" % key)
                elif net["IPAM"]["Config"][0].get(camelkey) != value:
                    # key has different value
                    different = True
                    differences.append("ipam_options.%s" % key)
    return different, differences


# Traceback (AttributeError)
The full traceback is:
Traceback (most recent call last):
File "/tmp/ansible_9Ntaqw/ansible_module_docker_network.py", line 392, in <module>
main()
File "/tmp/ansible_9Ntaqw/ansible_module_docker_network.py", line 385, in main
cm = DockerNetworkManager(client)
File "/tmp/ansible_9Ntaqw/ansible_module_docker_network.py", line 218, in __init__
self.present()
File "/tmp/ansible_9Ntaqw/ansible_module_docker_network.py", line 352, in present
self.disconnect_missing()
File "/tmp/ansible_9Ntaqw/ansible_module_docker_network.py", line 323, in disconnect_missing
for c in self.existing_network['Containers'].values():
AttributeError: 'NoneType' object has no attribute 'values'

failed: [192.168.1.120 -> 127.0.0.1] (item={u'driver': u'overlay', u'name': u'networks_default_1'}) => {
"failed": true,
"item": {
"driver": "overlay",
"name": "networks_default_1"
},
"module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_9Ntaqw/ansible_module_docker_network.py\", line 392, in <module>\n    main()\n  File \"/tmp/ansible_9Ntaqw/ansible_module_docker_network.py\", line 385, in main\n    cm = DockerNetworkManager(client)\n  File \"/tmp/ansible_9Ntaqw/ansible_module_docker_network.py\", line 218, in __init__\n    self.present()\n  File \"/tmp/ansible_9Ntaqw/ansible_module_docker_network.py\", line 352, in present\n    self.disconnect_missing()\n  File \"/tmp/ansible_9Ntaqw/ansible_module_docker_network.py\", line 323, in disconnect_missing\n    for c in self.existing_network['Containers'].values():\nAttributeError: 'NoneType' object has no attribute 'values'\n",
"module_stdout": "",
"msg": "MODULE FAILURE",
"rc": 0

# Fixed code
def has_different_config(self, net):
    """
    Evaluates an existing network and returns a tuple containing a boolean
    indicating if the configuration is different and a list of differences.

    :param net: the inspection output for an existing network
    :return: (bool, list)
    """
    different = False
    differences = []
    if self.parameters.driver and self.parameters.driver != net["Driver"]:
        different = True
        differences.append("driver")
    if self.parameters.driver_options:
        if not net.get("Options"):
            different = True
            differences.append("driver_options")
        else:
            for key, value in self.parameters.driver_options.items():
                if not (key in net["Options"]) or value != net["Options"][key]:
                    different = True
                    differences.append("driver_options.%s" % key)
    if self.parameters.ipam_driver:
        if not net.get("IPAM") or net["IPAM"]["Driver"] != self.parameters.ipam_driver:
            different = True
            differences.append("ipam_driver")
    if self.parameters.ipam_options:
        if not net.get("IPAM") or not net["IPAM"].get("Config"):
            different = True
            differences.append("ipam_options")
        else:
            for key, value in self.parameters.ipam_options.items():
                camelkey = None
                for net_key in net["IPAM"]["Config"][0]:
                    if key == net_key.lower():
                        camelkey = net_key
                        break
                if not camelkey:
                    # key not found
                    different = True
                    differences.append("ipam_options.%s" % key)
                elif net["IPAM"]["Config"][0].get(camelkey) != value:
                    # key has different value
                    different = True
                    differences.append("ipam_options.%s" % key)
    return different, differences