# Buggy code
def delete_instance(module, client, instance_name):
    """
    Terminates an instance

    module: Ansible module object
    client: authenticated lightsail connection object
    instance_name: name of instance to delete

    Returns a dictionary of instance information
    about the instance deleted (pre-deletion).

    If the instance to be deleted is running
    "changed" will be set to False.

    """

    # It looks like deleting removes the instance immediately, nothing to wait for
    wait = module.params.get("wait")
    wait_timeout = int(module.params.get("wait_timeout"))
    wait_max = time.time() + wait_timeout

    changed = False

    inst = None
    try:
        inst = _find_instance_info(client, instance_name)
    except botocore.exceptions.ClientError as e:
        if e.response["Error"]["Code"] != "NotFoundException":
            module.fail_json(
                msg="Error finding instance {0}, error: {1}".format(instance_name, e)
            )

    # If instance doesn't exist, then return with 'changed:false'
    if not inst:
        return changed, {}

    # Wait for instance to exit transition state before deleting
    if wait:
        while (
            wait_max > time.time()
            and inst is not None
            and inst["state"]["name"] in ("pending", "stopping")
        ):
            try:
                time.sleep(5)
                inst = _find_instance_info(client, instance_name)
            except botocore.exceptions.ClientError as e:
                if e.response["ResponseMetadata"]["HTTPStatusCode"] == "403":
                    module.fail_json(
                        msg="Failed to delete instance {0}. Check that you have permissions to perform the operation.".format(
                            instance_name
                        ),
                        exception=traceback.format_exc(),
                    )
                elif e.response["Error"]["Code"] == "RequestExpired":
                    module.fail_json(
                        msg="RequestExpired: Failed to delete instance {0}.".format(
                            instance_name
                        ),
                        exception=traceback.format_exc(),
                    )
                # sleep and retry
                time.sleep(10)

    # Attempt to delete
    if inst is not None:
        while not changed and ((wait and wait_max > time.time()) or (not wait)):
            try:
                client.delete_instance(instanceName=instance_name)
                changed = True
            except botocore.exceptions.ClientError as e:
                module.fail_json(
                    msg="Error deleting instance {0}, error: {1}".format(
                        instance_name, e
                    )
                )

    # Timed out
    if wait and not changed and wait_max <= time.time():
        module.fail_json(msg="wait for instance delete timeout at %s" % time.asctime())

    return (changed, inst)


# Traceback (ParamValidationError)
The full traceback is:
Traceback (most recent call last):
File "/tmp/ansible_Vslj3B/ansible_module_lightsail.py", line 467, in main
core(module)
File "/tmp/ansible_Vslj3B/ansible_module_lightsail.py", line 429, in core
changed, instance_dict = create_instance(module, client, name)
File "/tmp/ansible_Vslj3B/ansible_module_lightsail.py", line 219, in create_instance
keyPairName=key_pair_name,
File "/home/jack/git/lightsail/ansible/env/local/lib/python2.7/site-packages/botocore/client.py", line 324, in _api_call
return self._make_api_call(operation_name, kwargs)
File "/home/jack/git/lightsail/ansible/env/local/lib/python2.7/site-packages/botocore/client.py", line 596, in _make_api_call
api_params, operation_model, context=request_context)
File "/home/jack/git/lightsail/ansible/env/local/lib/python2.7/site-packages/botocore/client.py", line 631, in _convert_to_request_dict
api_params, operation_model)
File "/home/jack/git/lightsail/ansible/env/local/lib/python2.7/site-packages/botocore/validate.py", line 291, in serialize_to_request
raise ParamValidationError(report=report.generate_report())
ParamValidationError: Parameter validation failed:
Invalid type for parameter keyPairName, value: None, type: <type 'NoneType'>, valid types: <type 'basestring'>

fatal: [localhost]: FAILED! => {
"changed": false,
"invocation": {
"module_args": {
"aws_access_key": null,
"aws_secret_key": null,
"blueprint_id": "ubuntu_16_04",
"bundle_id": "nano_1_0",
"ec2_url": null,
"key_pair_name": null,
"name": "test",
"profile": null,
"region": "eu-west-1",
"security_token": null,
"state": "present",
"user_data": null,
"validate_certs": true,
"wait": true,
"wait_timeout": "500",
"zone": "eu-west-1a"
}
},
"msg": "Parameter validation failed:\nInvalid type for parameter keyPairName, value: None, type: <type 'NoneType'>, valid types: <type 'basestring'>"
}

# Fixed code
def delete_instance(module, client, instance_name):
    changed = False

    inst = find_instance_info(module, client, instance_name)
    if inst is None:
        module.exit_json(changed=changed, instance={})

    # Wait for instance to exit transition state before deleting
    desired_states = ["running", "stopped"]
    wait_for_instance_state(module, client, instance_name, desired_states)

    try:
        client.delete_instance(instanceName=instance_name)
        changed = True
    except botocore.exceptions.ClientError as e:
        module.fail_json_aws(e)

    module.exit_json(changed=changed, instance=camel_dict_to_snake_dict(inst))