# Buggy code
def main():
    argument_spec = ec2_argument_spec()
    argument_spec.update(
        dict(
            state=dict(required=True, choices=["present", "absent"]),
            name=dict(required=True),
            description=dict(required=False),
            subnets=dict(required=False, type="list"),
        )
    )
    module = AnsibleModule(argument_spec=argument_spec)

    if not HAS_BOTO:
        module.fail_json(msg="boto required for this module")

    state = module.params.get("state")
    group_name = module.params.get("name").lower()
    group_description = module.params.get("description")
    group_subnets = module.params.get("subnets") or {}

    if state == "present":
        for required in ["name", "description", "subnets"]:
            if not module.params.get(required):
                module.fail_json(
                    msg=str("Parameter %s required for state='present'" % required)
                )
    else:
        for not_allowed in ["description", "subnets"]:
            if module.params.get(not_allowed):
                module.fail_json(
                    msg=str("Parameter %s not allowed for state='absent'" % not_allowed)
                )

    # Retrieve any AWS settings from the environment.
    region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module)

    if not region:
        module.fail_json(
            msg=str(
                "Either region or AWS_REGION or EC2_REGION environment variable or boto config aws_region or ec2_region must be set."
            )
        )

    """Get an elasticache connection"""
    try:
        endpoint = "elasticache.%s.amazonaws.com" % region
        connect_region = RegionInfo(name=region, endpoint=endpoint)
        conn = ElastiCacheConnection(region=connect_region, **aws_connect_kwargs)
    except boto.exception.NoAuthHandlerFound as e:
        module.fail_json(msg=e.message)

    try:
        changed = False
        exists = False

        try:
            matching_groups = conn.describe_cache_subnet_groups(
                group_name, max_records=100
            )
            exists = len(matching_groups) > 0
        except BotoServerError as e:
            if e.error_code != "CacheSubnetGroupNotFoundFault":
                module.fail_json(msg=e.error_message)

        if state == "absent":
            if exists:
                conn.delete_cache_subnet_group(group_name)
                changed = True
        else:
            if not exists:
                new_group = conn.create_cache_subnet_group(
                    group_name,
                    cache_subnet_group_description=group_description,
                    subnet_ids=group_subnets,
                )
                changed = True
            else:
                changed_group = conn.modify_cache_subnet_group(
                    group_name,
                    cache_subnet_group_description=group_description,
                    subnet_ids=group_subnets,
                )
                changed = True

    except BotoServerError as e:
        if e.error_message != "No modifications were requested.":
            module.fail_json(msg=e.error_message)
        else:
            changed = False

    module.exit_json(changed=changed)


# Traceback (socket.gaierror)
No config file found; using defaults
Set default localhost to localhost
Loading callback plugin minimal of type stdout, v2.0 from /usr/local/lib/python2.7/dist-packages/ansible/plugins/callback/__init__.pyc
META: ran handlers
Using module file /usr/local/lib/python2.7/dist-packages/ansible/modules/cloud/amazon/elasticache_subnet_group.py
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: sszwed
<localhost> EXEC /bin/sh -c 'echo ~ &amp;&amp; sleep 0'
<localhost> EXEC /bin/sh -c '( umask 77 &amp;&amp; mkdir -p "` echo /home/sszwed/.ansible/tmp/ansible-tmp-1493119113.83-14610261905763 `" &amp;&amp; echo ansible-tmp-1493119113.83-14610261905763="` echo /home/sszwed/.ansible/tmp/ansible-tmp-1493119113.83-14610261905763 `" ) &amp;&amp; sleep 0'
<localhost> PUT /tmp/tmp3G1P22 TO /home/sszwed/.ansible/tmp/ansible-tmp-1493119113.83-14610261905763/elasticache_subnet_group.py
<localhost> EXEC /bin/sh -c 'chmod u+x /home/sszwed/.ansible/tmp/ansible-tmp-1493119113.83-14610261905763/ /home/sszwed/.ansible/tmp/ansible-tmp-1493119113.83-14610261905763/elasticache_subnet_group.py &amp;&amp; sleep 0'
<localhost> EXEC /bin/sh -c '/usr/bin/python /home/sszwed/.ansible/tmp/ansible-tmp-1493119113.83-14610261905763/elasticache_subnet_group.py; rm -rf "/home/sszwed/.ansible/tmp/ansible-tmp-1493119113.83-14610261905763/" > /dev/null 2>&amp;1 &amp;&amp; sleep 0'
The full traceback is:
Traceback (most recent call last):
File "/tmp/ansible_vLU7aO/ansible_module_elasticache_subnet_group.py", line 160, in <module>
main()
File "/tmp/ansible_vLU7aO/ansible_module_elasticache_subnet_group.py", line 129, in main
matching_groups = conn.describe_cache_subnet_groups(group_name, max_records=100)
File "/usr/local/lib/python2.7/dist-packages/boto/elasticache/layer1.py", line 851, in describe_cache_subnet_groups
path='/', params=params)
File "/usr/local/lib/python2.7/dist-packages/boto/elasticache/layer1.py", line 1658, in _make_request
path='/', params=params)
File "/usr/local/lib/python2.7/dist-packages/boto/connection.py", line 1116, in make_request
return self._mexe(http_request)
File "/usr/local/lib/python2.7/dist-packages/boto/connection.py", line 1030, in _mexe
raise ex
socket.gaierror: [Errno -2] Name or service not known

localhost | FAILED! => {
"changed": false,
"failed": true,
"module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_vLU7aO/ansible_module_elasticache_subnet_group.py\", line 160, in <module>\n    main()\n  File \"/tmp/ansible_vLU7aO/ansible_module_elasticache_subnet_group.py\", line 129, in main\n    matching_groups = conn.describe_cache_subnet_groups(group_name, max_records=100)\n  File \"/usr/local/lib/python2.7/dist-packages/boto/elasticache/layer1.py\", line 851, in describe_cache_subnet_groups\n    path='/', params=params)\n  File \"/usr/local/lib/python2.7/dist-packages/boto/elasticache/layer1.py\", line 1658, in _make_request\n    path='/', params=params)\n  File \"/usr/local/lib/python2.7/dist-packages/boto/connection.py\", line 1116, in make_request\n    return self._mexe(http_request)\n  File \"/usr/local/lib/python2.7/dist-packages/boto/connection.py\", line 1030, in _mexe\n    raise ex\nsocket.gaierror: [Errno -2] Name or service not known\n",
"module_stdout": "",
"msg": "MODULE FAILURE",
"rc": 0
}

# Fixed code
def main():
    argument_spec = ec2_argument_spec()
    argument_spec.update(
        dict(
            state=dict(required=True, choices=["present", "absent"]),
            name=dict(required=True),
            description=dict(required=False),
            subnets=dict(required=False, type="list"),
        )
    )
    module = AnsibleModule(argument_spec=argument_spec)

    if not HAS_BOTO:
        module.fail_json(msg="boto required for this module")

    state = module.params.get("state")
    group_name = module.params.get("name").lower()
    group_description = module.params.get("description")
    group_subnets = module.params.get("subnets") or {}

    if state == "present":
        for required in ["name", "description", "subnets"]:
            if not module.params.get(required):
                module.fail_json(
                    msg=str("Parameter %s required for state='present'" % required)
                )
    else:
        for not_allowed in ["description", "subnets"]:
            if module.params.get(not_allowed):
                module.fail_json(
                    msg=str("Parameter %s not allowed for state='absent'" % not_allowed)
                )

    # Retrieve any AWS settings from the environment.
    region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module)

    if not region:
        module.fail_json(
            msg=str(
                "Either region or AWS_REGION or EC2_REGION environment variable or boto config aws_region or ec2_region must be set."
            )
        )

    """Get an elasticache connection"""
    try:
        conn = connect_to_region(region_name=region, **aws_connect_kwargs)
    except boto.exception.NoAuthHandlerFound as e:
        module.fail_json(msg=e.message)

    try:
        changed = False
        exists = False

        try:
            matching_groups = conn.describe_cache_subnet_groups(
                group_name, max_records=100
            )
            exists = len(matching_groups) > 0
        except BotoServerError as e:
            if e.error_code != "CacheSubnetGroupNotFoundFault":
                module.fail_json(msg=e.error_message)

        if state == "absent":
            if exists:
                conn.delete_cache_subnet_group(group_name)
                changed = True
        else:
            if not exists:
                new_group = conn.create_cache_subnet_group(
                    group_name,
                    cache_subnet_group_description=group_description,
                    subnet_ids=group_subnets,
                )
                changed = True
            else:
                changed_group = conn.modify_cache_subnet_group(
                    group_name,
                    cache_subnet_group_description=group_description,
                    subnet_ids=group_subnets,
                )
                changed = True

    except BotoServerError as e:
        if e.error_message != "No modifications were requested.":
            module.fail_json(msg=e.error_message)
        else:
            changed = False

    module.exit_json(changed=changed)