# Buggy code
def tags_changed(nacl_id, client, module):
    changed = False
    tags = dict()
    if module.params.get("tags"):
        tags = module.params.get("tags")
    tags["Name"] = module.params.get("name")
    nacl = find_acl_by_id(nacl_id, client, module)
    if nacl["NetworkAcls"]:
        nacl_values = [t.values() for t in nacl["NetworkAcls"][0]["Tags"]]
        nacl_tags = [item for sublist in nacl_values for item in sublist]
        tag_values = [[key, str(value)] for key, value in tags.items()]
        tags = [item for sublist in tag_values for item in sublist]
        if sorted(nacl_tags) == sorted(tags):
            changed = False
            return changed
        else:
            delete_tags(nacl_id, client, module)
            create_tags(nacl_id, client, module)
            changed = True
            return changed
    return changed


# Traceback (ParamValidationError)
johnn@johnn-ws:/tmp$ ansible-playbook ./test.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'


PLAY [localhost] ********************************************************************************************************************************************************************************************

TASK [Find the VPCs default NACL] ***************************************************************************************************************************************************************************
ok: [localhost]

TASK [Report found NACL ID] *********************************************************************************************************************************************************************************
ok: [localhost] => {
"found_default_nacl.nacls[0].nacl_id": "acl-05b7862fef4a975e9"
}

TASK [Ensure VPCs default NACL allows our CIDR lists] *******************************************************************************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: Invalid type for parameter Tags[0].Value, value: None, type: <type 'NoneType'>, valid types: <type 'basestring'>
fatal: [localhost]: FAILED! => {"changed": false, "module_stderr": "Traceback (most recent call last):\n  File \"/home/johnn/.ansible/tmp/ansible-tmp-1542412593.52-119506277744319/AnsiballZ_ec2_vpc_nacl.py\", line 113, in <module>\n    _ansiballz_main()\n  File \"/home/johnn/.ansible/tmp/ansible-tmp-1542412593.52-119506277744319/AnsiballZ_ec2_vpc_nacl.py\", line 105, in _ansiballz_main\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n  File \"/home/johnn/.ansible/tmp/ansible-tmp-1542412593.52-119506277744319/AnsiballZ_ec2_vpc_nacl.py\", line 48, in invoke_module\n    imp.load_module('__main__', mod, module, MOD_DESC)\n  File \"/tmp/ansible_ec2_vpc_nacl_payload_QpEKry/__main__.py\", line 587, in <module>\n  File \"/tmp/ansible_ec2_vpc_nacl_payload_QpEKry/__main__.py\", line 582, in main\n  File \"/tmp/ansible_ec2_vpc_nacl_payload_QpEKry/__main__.py\", line 353, in setup_network_acl\n  File \"/tmp/ansible_ec2_vpc_nacl_payload_QpEKry/__main__.py\", line 267, in tags_changed\n  File \"/tmp/ansible_ec2_vpc_nacl_payload_QpEKry/__main__.py\", line 410, in create_tags\n  File \"/usr/lib/python2.7/dist-packages/botocore/client.py\", line 324, in _api_call\n    return self._make_api_call(operation_name, kwargs)\n  File \"/usr/lib/python2.7/dist-packages/botocore/client.py\", line 596, in _make_api_call\n    api_params, operation_model, context=request_context)\n  File \"/usr/lib/python2.7/dist-packages/botocore/client.py\", line 631, in _convert_to_request_dict\n    api_params, operation_model)\n  File \"/usr/lib/python2.7/dist-packages/botocore/validate.py\", line 291, in serialize_to_request\n    raise ParamValidationError(report=report.generate_report())\nbotocore.exceptions.ParamValidationError: Parameter validation failed:\nInvalid type for parameter Tags[0].Value, value: None, type: <type 'NoneType'>, valid types: <type 'basestring'>\n", "module_stdout": "", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}
to retry, use: --limit @/tmp/test.retry

PLAY RECAP **************************************************************************************************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=1

# Fixed code
def tags_changed(nacl_id, client, module):
    changed = False
    tags = dict()
    if module.params.get("tags"):
        tags = module.params.get("tags")
    if module.params.get("name") and not tags.get("Name"):
        tags["Name"] = module.params["name"]
    nacl = find_acl_by_id(nacl_id, client, module)
    if nacl["NetworkAcls"]:
        nacl_values = [t.values() for t in nacl["NetworkAcls"][0]["Tags"]]
        nacl_tags = [item for sublist in nacl_values for item in sublist]
        tag_values = [[key, str(value)] for key, value in tags.items()]
        tags = [item for sublist in tag_values for item in sublist]
        if sorted(nacl_tags) == sorted(tags):
            changed = False
            return changed
        else:
            delete_tags(nacl_id, client, module)
            create_tags(nacl_id, client, module)
            changed = True
            return changed
    return changed