# Buggy code
def modify_cluster(module, redshift):
    """
    Modify an existing cluster.

    module: Ansible module object
    redshift: authenticated redshift connection object
    """

    identifier = module.params.get("identifier")
    wait = module.params.get("wait")
    wait_timeout = module.params.get("wait_timeout")

    # Package up the optional parameters
    params = {}
    for p in (
        "cluster_type",
        "cluster_security_groups",
        "vpc_security_group_ids",
        "cluster_subnet_group_name",
        "availability_zone",
        "preferred_maintenance_window",
        "cluster_parameter_group_name",
        "automated_snapshot_retention_period",
        "port",
        "cluster_version",
        "allow_version_upgrade",
        "number_of_nodes",
        "new_cluster_identifier",
        "enhanced_vpc_routing",
    ):
        if p in module.params:
            params[p] = module.params.get(p)

    try:
        redshift.describe_clusters(identifier)["DescribeClustersResponse"][
            "DescribeClustersResult"
        ]["Clusters"][0]
    except boto.exception.JSONResponseError as e:
        try:
            redshift.modify_cluster(identifier, **params)
        except boto.exception.JSONResponseError as e:
            module.fail_json(msg=str(e))

    try:
        resource = redshift.describe_clusters(identifier)["DescribeClustersResponse"][
            "DescribeClustersResult"
        ]["Clusters"][0]
    except boto.exception.JSONResponseError as e:
        module.fail_json(msg=str(e))

    if wait:
        try:
            wait_timeout = time.time() + wait_timeout
            time.sleep(5)

            while (
                wait_timeout > time.time() and resource["ClusterStatus"] != "available"
            ):
                time.sleep(5)
                if wait_timeout <= time.time():
                    module.fail_json(
                        msg="Timeout waiting for resource %s" % resource.id
                    )

                resource = redshift.describe_clusters(identifier)[
                    "DescribeClustersResponse"
                ]["DescribeClustersResult"]["Clusters"][0]

        except boto.exception.JSONResponseError as e:
            # https://github.com/boto/boto/issues/2776 is fixed.
            module.fail_json(msg=str(e))

    return (True, _collect_facts(resource))


# Traceback (TypeError)
TASK [Launch Redshift instances] ******************************************************************************************************************************************************************************
task path: /home/rdriutti/code/ansible/create-cluster.yml:6
Using module file /home/rdriutti/code/ansible/lib/ansible/modules/cloud/amazon/redshift.py
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: rdriutti
<localhost> EXEC /bin/sh -c 'echo ~ &amp;&amp; sleep 0'
<localhost> EXEC /bin/sh -c '( umask 77 &amp;&amp; mkdir -p "` echo /home/rdriutti/.ansible/tmp/ansible-tmp-1520300144.74-278909426876762 `" &amp;&amp; echo ansible-tmp-1520300144.74-278909426876762="` echo /home/rdriutti/.ansible/tmp/ansible-tmp-1520300144.74-278909426876762 `" ) &amp;&amp; sleep 0'
<localhost> PUT /home/rdriutti/.ansible/tmp/ansible-local-18151rOE_gi/tmpX7AGbv TO /home/rdriutti/.ansible/tmp/ansible-tmp-1520300144.74-278909426876762/redshift.py
<localhost> EXEC /bin/sh -c 'chmod u+x /home/rdriutti/.ansible/tmp/ansible-tmp-1520300144.74-278909426876762/ /home/rdriutti/.ansible/tmp/ansible-tmp-1520300144.74-278909426876762/redshift.py &amp;&amp; sleep 0'
<localhost> EXEC /bin/sh -c '/usr/bin/python /home/rdriutti/.ansible/tmp/ansible-tmp-1520300144.74-278909426876762/redshift.py &amp;&amp; sleep 0'
<localhost> EXEC /bin/sh -c 'rm -f -r /home/rdriutti/.ansible/tmp/ansible-tmp-1520300144.74-278909426876762/ > /dev/null 2>&amp;1 &amp;&amp; sleep 0'
The full traceback is:
Traceback (most recent call last):
File "/tmp/ansible_QpwK2x/ansible_module_redshift.py", line 515, in <module>
main()
File "/tmp/ansible_QpwK2x/ansible_module_redshift.py", line 500, in main
(changed, cluster) = create_cluster(module, conn)
File "/tmp/ansible_QpwK2x/ansible_module_redshift.py", line 298, in create_cluster
redshift.create_cluster(identifier, node_type, username, password, **params)
TypeError: create_cluster() got an unexpected keyword argument 'enhanced_vpc_routing'

fatal: [localhost -> localhost]: FAILED! => {
"changed": false,
"module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_QpwK2x/ansible_module_redshift.py\", line 515, in <module>\n    main()\n  File \"/tmp/ansible_QpwK2x/ansible_module_redshift.py\", line 500, in main\n    (changed, cluster) = create_cluster(module, conn)\n  File \"/tmp/ansible_QpwK2x/ansible_module_redshift.py\", line 298, in create_cluster\n    redshift.create_cluster(identifier, node_type, username, password, **params)\nTypeError: create_cluster() got an unexpected keyword argument 'enhanced_vpc_routing'\n",
"module_stdout": "",
"msg": "MODULE FAILURE",
"rc": 1
}

# Fixed code
def modify_cluster(module, redshift):
    """
    Modify an existing cluster.

    module: Ansible module object
    redshift: authenticated redshift connection object
    """

    identifier = module.params.get("identifier")
    wait = module.params.get("wait")
    wait_timeout = module.params.get("wait_timeout")

    # Package up the optional parameters
    params = {}
    for p in (
        "cluster_type",
        "cluster_security_groups",
        "vpc_security_group_ids",
        "cluster_subnet_group_name",
        "availability_zone",
        "preferred_maintenance_window",
        "cluster_parameter_group_name",
        "automated_snapshot_retention_period",
        "port",
        "cluster_version",
        "allow_version_upgrade",
        "number_of_nodes",
        "new_cluster_identifier",
    ):
        # https://github.com/boto/boto3/issues/400
        if module.params.get(p) is not None:
            params[p] = module.params.get(p)

    # enhanced_vpc_routing parameter change needs an exclusive request
    if module.params.get("enhanced_vpc_routing") is not None:
        try:
            redshift.modify_cluster(
                ClusterIdentifier=identifier,
                EnhancedVpcRouting=module.params.get("enhanced_vpc_routing"),
            )
        except (
            botocore.exceptions.BotoCoreError,
            botocore.exceptions.ClientError,
        ) as e:
            module.fail_json_aws(
                e, msg="Couldn't modify redshift cluster %s " % identifier
            )
    if wait:
        attempts = wait_timeout // 60
        waiter = redshift.get_waiter("cluster_available")
        try:
            waiter.wait(
                ClusterIdentifier=identifier, WaiterConfig=dict(MaxAttempts=attempts)
            )
        except (
            botocore.exceptions.ClientError,
            botocore.exceptions.BotoCoreError,
        ) as e:
            module.fail_json_aws(
                e, msg="Timeout waiting for cluster enhanced vpc routing modification"
            )

    # change the rest
    try:
        redshift.modify_cluster(
            ClusterIdentifier=identifier,
            **snake_dict_to_camel_dict(params, capitalize_first=True),
        )
    except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e:
        module.fail_json_aws(e, msg="Couldn't modify redshift cluster %s " % identifier)

    if module.params.get("new_cluster_identifier"):
        identifier = module.params.get("new_cluster_identifier")

    if wait:
        attempts = wait_timeout // 60
        waiter2 = redshift.get_waiter("cluster_available")
        try:
            waiter2.wait(
                ClusterIdentifier=identifier, WaiterConfig=dict(MaxAttempts=attempts)
            )
        except (
            botocore.exceptions.ClientError,
            botocore.exceptions.BotoCoreError,
        ) as e:
            module.fail_json_aws(e, msg="Timeout waiting for cluster modification")
    try:
        resource = redshift.describe_clusters(ClusterIdentifier=identifier)["Clusters"][
            0
        ]
    except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e:
        module.fail_json(e, msg="Couldn't modify redshift cluster %s " % identifier)

    return (True, _collect_facts(resource))