# Buggy code
def main():
    argument_spec = ec2_argument_spec()
    argument_spec.update(
        dict(
            key_name=dict(aliases=["keypair"]),
            id=dict(),
            group=dict(type="list", aliases=["groups"]),
            group_id=dict(type="list"),
            zone=dict(aliases=["aws_zone", "ec2_zone"]),
            instance_type=dict(aliases=["type"]),
            spot_price=dict(),
            spot_type=dict(default="one-time", choices=["one-time", "persistent"]),
            spot_launch_group=dict(),
            image=dict(),
            kernel=dict(),
            count=dict(type="int", default="1"),
            monitoring=dict(type="bool", default=False),
            ramdisk=dict(),
            wait=dict(type="bool", default=False),
            wait_timeout=dict(default=300),
            spot_wait_timeout=dict(default=600),
            placement_group=dict(),
            user_data=dict(),
            instance_tags=dict(type="dict"),
            vpc_subnet_id=dict(),
            assign_public_ip=dict(type="bool", default=False),
            private_ip=dict(),
            instance_profile_name=dict(),
            instance_ids=dict(type="list", aliases=["instance_id"]),
            source_dest_check=dict(type="bool", default=True),
            termination_protection=dict(type="bool", default=None),
            state=dict(
                default="present",
                choices=["present", "absent", "running", "restarted", "stopped"],
            ),
            instance_initiated_shutdown_behavior=dict(
                default=None, choices=["stop", "terminate"]
            ),
            exact_count=dict(type="int", default=None),
            count_tag=dict(),
            volumes=dict(type="list"),
            ebs_optimized=dict(type="bool", default=False),
            tenancy=dict(default="default"),
            network_interfaces=dict(type="list", aliases=["network_interface"]),
        )
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        mutually_exclusive=[
            ["group_name", "group_id"],
            ["exact_count", "count"],
            ["exact_count", "state"],
            ["exact_count", "instance_ids"],
            ["network_interfaces", "assign_public_ip"],
            ["network_interfaces", "group"],
            ["network_interfaces", "group_id"],
            ["network_interfaces", "private_ip"],
            ["network_interfaces", "vpc_subnet_id"],
        ],
    )

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

    ec2 = ec2_connect(module)

    region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module)

    if region:
        try:
            vpc = connect_to_aws(boto.vpc, region, **aws_connect_kwargs)
        except boto.exception.NoAuthHandlerFound as e:
            module.fail_json(msg=str(e))
    else:
        vpc = None

    tagged_instances = []

    state = module.params["state"]

    if state == "absent":
        instance_ids = module.params["instance_ids"]
        if not instance_ids:
            module.fail_json(msg="instance_ids list is required for absent state")

        (changed, instance_dict_array, new_instance_ids) = terminate_instances(
            module, ec2, instance_ids
        )

    elif state in ("running", "stopped"):
        instance_ids = module.params.get("instance_ids")
        instance_tags = module.params.get("instance_tags")
        if not (isinstance(instance_ids, list) or isinstance(instance_tags, dict)):
            module.fail_json(
                msg="running list needs to be a list of instances or set of tags to run: %s"
                % instance_ids
            )

        (changed, instance_dict_array, new_instance_ids) = startstop_instances(
            module, ec2, instance_ids, state, instance_tags
        )

    elif state in ("restarted"):
        instance_ids = module.params.get("instance_ids")
        instance_tags = module.params.get("instance_tags")
        if not (isinstance(instance_ids, list) or isinstance(instance_tags, dict)):
            module.fail_json(
                msg="running list needs to be a list of instances or set of tags to run: %s"
                % instance_ids
            )

        (changed, instance_dict_array, new_instance_ids) = restart_instances(
            module, ec2, instance_ids, state, instance_tags
        )

    elif state == "present":
        # Changed is always set to true when provisioning new instances
        if not module.params.get("image"):
            module.fail_json(msg="image parameter is required for new instance")

        if module.params.get("exact_count") is None:
            (instance_dict_array, new_instance_ids, changed) = create_instances(
                module, ec2, vpc
            )
        else:
            (tagged_instances, instance_dict_array, new_instance_ids, changed) = (
                enforce_count(module, ec2, vpc)
            )

    module.exit_json(
        changed=changed,
        instance_ids=new_instance_ids,
        instances=instance_dict_array,
        tagged_instances=tagged_instances,
    )


# Traceback (AttributeError)
Using module_utils file /usr/local/lib/python2.7/site-packages/ansible/module_utils/basic.py
Using module_utils file /usr/local/lib/python2.7/site-packages/ansible/module_utils/ec2.py
Using module_utils file /usr/local/lib/python2.7/site-packages/ansible/module_utils/six/__init__.py
Using module_utils file /usr/local/lib/python2.7/site-packages/ansible/module_utils/_text.py
Using module_utils file /usr/local/lib/python2.7/site-packages/ansible/module_utils/pycompat24.py
Using module_utils file /usr/local/lib/python2.7/site-packages/ansible/module_utils/cloud.py
Using module_utils file /usr/local/lib/python2.7/site-packages/ansible/module_utils/six/_six.py
Using module file /usr/local/lib/python2.7/site-packages/ansible/modules/cloud/amazon/ec2.py
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: root
<localhost> EXEC /bin/sh -c 'echo ~ &amp;&amp; sleep 0'
<localhost> EXEC /bin/sh -c '( umask 77 &amp;&amp; mkdir -p "` echo /Users/matheus/.ansible/tmp/ansible-tmp-1494271535.47-249816046272594 `" &amp;&amp; echo ansible-tmp-1494271535.47-249816046272594="` echo /Users/matheus/.ansible/tmp/ansible-tmp-1494271535.47-249816046272594 `" ) &amp;&amp; sleep 0'
<localhost> PUT /tmp/tmpIM5bXL TO /Users/matheus/.ansible/tmp/ansible-tmp-1494271535.47-249816046272594/ec2.py
<localhost> EXEC /bin/sh -c 'chmod u+x /Users/matheus/.ansible/tmp/ansible-tmp-1494271535.47-249816046272594/ /Users/matheus/.ansible/tmp/ansible-tmp-1494271535.47-249816046272594/ec2.py &amp;&amp; sleep 0'
<localhost> EXEC /bin/sh -c 'python /Users/matheus/.ansible/tmp/ansible-tmp-1494271535.47-249816046272594/ec2.py; rm -rf "/Users/matheus/.ansible/tmp/ansible-tmp-1494271535.47-249816046272594/" > /dev/null 2>&amp;1 &amp;&amp; sleep 0'
The full traceback is:
Traceback (most recent call last):
File "/tmp/ansible_nSZPD5/ansible_module_ec2.py", line 1673, in <module>
main()
File "/tmp/ansible_nSZPD5/ansible_module_ec2.py", line 1667, in main
(tagged_instances, instance_dict_array, new_instance_ids, changed) = enforce_count(module, ec2, vpc)
File "/tmp/ansible_nSZPD5/ansible_module_ec2.py", line 932, in enforce_count
reservations, instances = find_running_instances_by_count_tag(module, ec2, count_tag, zone)
File "/tmp/ansible_nSZPD5/ansible_module_ec2.py", line 638, in find_running_instances_by_count_tag
reservations = get_reservations(module, ec2, tags=count_tag, state="running", zone=zone)
File "/tmp/ansible_nSZPD5/ansible_module_ec2.py", line 697, in get_reservations
results = ec2.get_all_instances(filters=filters)
File "/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/boto/ec2/connection.py", line 585, in get_all_instances
max_results=max_results)
File "/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/boto/ec2/connection.py", line 681, in get_all_reservations
[('item', Reservation)], verb='POST')
File "/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/boto/connection.py", line 1170, in get_list
response = self.make_request(action, params, path, verb)
File "/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/boto/connection.py", line 1116, in make_request
return self._mexe(http_request)
File "/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/boto/connection.py", line 913, in _mexe
self.is_secure)
File "/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/boto/connection.py", line 705, in get_http_connection
return self.new_http_connection(host, port, is_secure)
File "/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/boto/connection.py", line 729, in new_http_connection
host = boto.utils.parse_host(host)
File "/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/boto/utils.py", line 1086, in parse_host
hostname = hostname.strip()
AttributeError: 'NoneType' object has no attribute 'strip'

fatal: [localhost]: FAILED! => {
"changed": false,
"failed": true,
"module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_nSZPD5/ansible_module_ec2.py\", line 1673, in <module>\n    main()\n  File \"/tmp/ansible_nSZPD5/ansible_module_ec2.py\", line 1667, in main\n    (tagged_instances, instance_dict_array, new_instance_ids, changed) = enforce_count(module, ec2, vpc)\n  File \"/tmp/ansible_nSZPD5/ansible_module_ec2.py\", line 932, in enforce_count\n    reservations, instances = find_running_instances_by_count_tag(module, ec2, count_tag, zone)\n  File \"/tmp/ansible_nSZPD5/ansible_module_ec2.py\", line 638, in find_running_instances_by_count_tag\n    reservations = get_reservations(module, ec2, tags=count_tag, state=\"running\", zone=zone)\n  File \"/tmp/ansible_nSZPD5/ansible_module_ec2.py\", line 697, in get_reservations\n    results = ec2.get_all_instances(filters=filters)\n  File \"/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/boto/ec2/connection.py\", line 585, in get_all_instances\n    max_results=max_results)\n  File \"/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/boto/ec2/connection.py\", line 681, in get_all_reservations\n    [('item', Reservation)], verb='POST')\n  File \"/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/boto/connection.py\", line 1170, in get_list\n    response = self.make_request(action, params, path, verb)\n  File \"/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/boto/connection.py\", line 1116, in make_request\n    return self._mexe(http_request)\n  File \"/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/boto/connection.py\", line 913, in _mexe\n    self.is_secure)\n  File \"/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/boto/connection.py\", line 705, in get_http_connection\n    return self.new_http_connection(host, port, is_secure)\n  File \"/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/boto/connection.py\", line 729, in new_http_connection\n    host = boto.utils.parse_host(host)\n  File \"/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/boto/utils.py\", line 1086, in parse_host\n    hostname = hostname.strip()\nAttributeError: 'NoneType' object has no attribute 'strip'\n",
"module_stdout": "",
"msg": "MODULE FAILURE",
"rc": 0
}

# Fixed code
def main():
    argument_spec = ec2_argument_spec()
    argument_spec.update(
        dict(
            key_name=dict(aliases=["keypair"]),
            id=dict(),
            group=dict(type="list", aliases=["groups"]),
            group_id=dict(type="list"),
            zone=dict(aliases=["aws_zone", "ec2_zone"]),
            instance_type=dict(aliases=["type"]),
            spot_price=dict(),
            spot_type=dict(default="one-time", choices=["one-time", "persistent"]),
            spot_launch_group=dict(),
            image=dict(),
            kernel=dict(),
            count=dict(type="int", default="1"),
            monitoring=dict(type="bool", default=False),
            ramdisk=dict(),
            wait=dict(type="bool", default=False),
            wait_timeout=dict(default=300),
            spot_wait_timeout=dict(default=600),
            placement_group=dict(),
            user_data=dict(),
            instance_tags=dict(type="dict"),
            vpc_subnet_id=dict(),
            assign_public_ip=dict(type="bool", default=False),
            private_ip=dict(),
            instance_profile_name=dict(),
            instance_ids=dict(type="list", aliases=["instance_id"]),
            source_dest_check=dict(type="bool", default=True),
            termination_protection=dict(type="bool", default=None),
            state=dict(
                default="present",
                choices=["present", "absent", "running", "restarted", "stopped"],
            ),
            instance_initiated_shutdown_behavior=dict(
                default=None, choices=["stop", "terminate"]
            ),
            exact_count=dict(type="int", default=None),
            count_tag=dict(),
            volumes=dict(type="list"),
            ebs_optimized=dict(type="bool", default=False),
            tenancy=dict(default="default"),
            network_interfaces=dict(type="list", aliases=["network_interface"]),
        )
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        mutually_exclusive=[
            ["group_name", "group_id"],
            ["exact_count", "count"],
            ["exact_count", "state"],
            ["exact_count", "instance_ids"],
            ["network_interfaces", "assign_public_ip"],
            ["network_interfaces", "group"],
            ["network_interfaces", "group_id"],
            ["network_interfaces", "private_ip"],
            ["network_interfaces", "vpc_subnet_id"],
        ],
    )

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

    try:
        _, ec2_url, aws_connect_kwargs = get_aws_connection_info(module)
        if module.params.get("region") or not module.params.get("ec2_url"):
            ec2 = ec2_connect(module)
        elif module.params.get("ec2_url"):
            ec2 = connect_ec2_endpoint(ec2_url, **aws_connect_kwargs)

        vpc = connect_vpc(**aws_connect_kwargs)
    except boto.exception.NoAuthHandlerFound as e:
        module.fail_json(
            msg="Failed to get connection: %s" % e.message,
            exception=traceback.format_exc(),
        )

    tagged_instances = []

    state = module.params["state"]

    if state == "absent":
        instance_ids = module.params["instance_ids"]
        if not instance_ids:
            module.fail_json(msg="instance_ids list is required for absent state")

        (changed, instance_dict_array, new_instance_ids) = terminate_instances(
            module, ec2, instance_ids
        )

    elif state in ("running", "stopped"):
        instance_ids = module.params.get("instance_ids")
        instance_tags = module.params.get("instance_tags")
        if not (isinstance(instance_ids, list) or isinstance(instance_tags, dict)):
            module.fail_json(
                msg="running list needs to be a list of instances or set of tags to run: %s"
                % instance_ids
            )

        (changed, instance_dict_array, new_instance_ids) = startstop_instances(
            module, ec2, instance_ids, state, instance_tags
        )

    elif state in ("restarted"):
        instance_ids = module.params.get("instance_ids")
        instance_tags = module.params.get("instance_tags")
        if not (isinstance(instance_ids, list) or isinstance(instance_tags, dict)):
            module.fail_json(
                msg="running list needs to be a list of instances or set of tags to run: %s"
                % instance_ids
            )

        (changed, instance_dict_array, new_instance_ids) = restart_instances(
            module, ec2, instance_ids, state, instance_tags
        )

    elif state == "present":
        # Changed is always set to true when provisioning new instances
        if not module.params.get("image"):
            module.fail_json(msg="image parameter is required for new instance")

        if module.params.get("exact_count") is None:
            (instance_dict_array, new_instance_ids, changed) = create_instances(
                module, ec2, vpc
            )
        else:
            (tagged_instances, instance_dict_array, new_instance_ids, changed) = (
                enforce_count(module, ec2, vpc)
            )

    module.exit_json(
        changed=changed,
        instance_ids=new_instance_ids,
        instances=instance_dict_array,
        tagged_instances=tagged_instances,
    )