Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PR #964/c6906a3f backport] [5.0.0] fix incomplete enforce_count() return values #1389

Merged
merged 1 commit into from
Feb 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions changelogs/fragments/964-ec2_instance-return-instances.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- ec2_instance - more consistently return ``instances`` information (https://github.com/ansible-collections/amazon.aws/pull/964).
108 changes: 84 additions & 24 deletions plugins/modules/ec2_instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
__metaclass__ = type


DOCUMENTATION = r'''
DOCUMENTATION = r"""
---
module: ec2_instance
version_added: 1.0.0
Expand Down Expand Up @@ -378,9 +378,9 @@
- amazon.aws.ec2
- amazon.aws.tags
- amazon.aws.boto3
'''
"""

EXAMPLES = '''
EXAMPLES = r"""
# Note: These examples do not set authentication details, see the AWS Guide for details.

- name: Terminate every running instance in a region. Use with EXTREME caution.
Expand Down Expand Up @@ -534,12 +534,30 @@
state: present
tags:
foo: bar
'''
"""

RETURN = '''
RETURN = r"""
instance_ids:
description: a list of ec2 instance IDs matching the provided specification and filters
returned: always
type: list
sample: ["i-0123456789abcdef0", "i-0123456789abcdef1"]
version_added: 5.3.0
changed_ids:
description: a list of the set of ec2 instance IDs changed by the module action
returned: when instances that must be present are launched
type: list
sample: ["i-0123456789abcdef0"]
version_added: 5.3.0
terminated_ids:
description: a list of the set of ec2 instance IDs terminated by the module action
returned: when instances that must be absent are terminated
type: list
sample: ["i-0123456789abcdef1"]
version_added: 5.3.0
instances:
description: a list of ec2 instances
returned: when wait == true
returned: when wait == true or when matching instances already exist
type: complex
contains:
ami_launch_index:
Expand Down Expand Up @@ -942,7 +960,7 @@
returned: always
type: dict
sample: vpc-0011223344
'''
"""

from collections import namedtuple
import time
Expand Down Expand Up @@ -1824,7 +1842,9 @@ def enforce_count(existing_matches, module, desired_module_state):
if current_count == exact_count:
module.exit_json(
changed=False,
msg='{0} instances already running, nothing to do.'.format(exact_count)
instances=[pretty_instance(i) for i in existing_matches],
instance_ids=[i["InstanceId"] for i in existing_matches],
msg=f"{exact_count} instances already running, nothing to do.",
)

elif current_count < exact_count:
Expand All @@ -1843,7 +1863,12 @@ def enforce_count(existing_matches, module, desired_module_state):
all_instance_ids = [x['InstanceId'] for x in existing_matches]
terminate_ids = all_instance_ids[0:to_terminate]
if module.check_mode:
module.exit_json(changed=True, msg='Would have terminated following instances if not in check mode {0}'.format(terminate_ids))
module.exit_json(
changed=True,
terminated_ids=terminate_ids,
instance_ids=all_instance_ids,
msg=f"Would have terminated following instances if not in check mode {terminate_ids}",
)
# terminate instances
try:
client.terminate_instances(aws_retry=True, InstanceIds=terminate_ids)
Expand All @@ -1852,10 +1877,14 @@ def enforce_count(existing_matches, module, desired_module_state):
pass
except botocore.exceptions.ClientError as e: # pylint: disable=duplicate-except
module.fail_json(e, msg='Unable to terminate instances')
# include data for all matched instances in addition to the list of terminations
# allowing for recovery of metadata from the destructive operation
module.exit_json(
changed=True,
msg='Successfully terminated instances.',
terminated_ids=terminate_ids,
instance_ids=all_instance_ids,
instances=existing_matches,
)

except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e:
Expand All @@ -1872,11 +1901,21 @@ def ensure_present(existing_matches, desired_module_state):
instance_spec = build_run_instance_spec(module.params)
# If check mode is enabled,suspend 'ensure function'.
if module.check_mode:
module.exit_json(
changed=True,
spec=instance_spec,
msg='Would have launched instances if not in check_mode.',
)
if existing_matches:
instance_ids = [x["InstanceId"] for x in existing_matches]
module.exit_json(
changed=True,
instance_ids=instance_ids,
instances=existing_matches,
spec=instance_spec,
msg="Would have launched instances if not in check_mode.",
)
else:
module.exit_json(
changed=True,
spec=instance_spec,
msg="Would have launched instances if not in check_mode.",
)
instance_response = run_instances(**instance_spec)
instances = instance_response['Instances']
instance_ids = [i['InstanceId'] for i in instances]
Expand Down Expand Up @@ -1904,22 +1943,43 @@ def ensure_present(existing_matches, desired_module_state):
client.modify_instance_attribute(aws_retry=True, **c)
except botocore.exceptions.ClientError as e:
module.fail_json_aws(e, msg="Could not apply change {0} to new instance.".format(str(c)))
if existing_matches:
# If we came from enforce_count, create a second list to distinguish
# between existing and new instances when returning the entire cohort
all_instance_ids = [x["InstanceId"] for x in existing_matches] + instance_ids
if not module.params.get("wait"):
if existing_matches:
module.exit_json(
changed=True,
changed_ids=instance_ids,
instance_ids=all_instance_ids,
spec=instance_spec,
)
else:
module.exit_json(
changed=True,
instance_ids=instance_ids,
spec=instance_spec,
)
await_instances(instance_ids, desired_module_state=desired_module_state)
instances = find_instances(ids=instance_ids)

if not module.params.get('wait'):
if existing_matches:
all_instances = existing_matches + instances
module.exit_json(
changed=True,
changed_ids=instance_ids,
instance_ids=all_instance_ids,
instances=[pretty_instance(i) for i in all_instances],
spec=instance_spec,
)
else:
module.exit_json(
changed=True,
instance_ids=instance_ids,
instances=[pretty_instance(i) for i in instances],
spec=instance_spec,
)
await_instances(instance_ids, desired_module_state=desired_module_state)
instances = find_instances(ids=instance_ids)

module.exit_json(
changed=True,
instances=[pretty_instance(i) for i in instances],
instance_ids=instance_ids,
spec=instance_spec,
)
except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e:
module.fail_json_aws(e, msg="Failed to create new EC2 instance")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,8 @@
that:
- create_multiple_instances is not failed
- create_multiple_instances is not changed
- '"instance_ids" not in create_multiple_instances'
- '"instance_ids" in create_multiple_instances'
- create_multiple_instances.instance_ids | length == 5
- '"ec2:RunInstances" not in create_multiple_instances.resource_actions'

- name: "Enforce instance count - launch 5 instances (Idempotency)"
Expand All @@ -183,7 +184,8 @@
that:
- create_multiple_instances is not failed
- create_multiple_instances is not changed
- '"instance_ids" not in create_multiple_instances'
- '"instance_ids" in create_multiple_instances'
- create_multiple_instances.instance_ids | length == 5
- '"ec2:RunInstances" not in create_multiple_instances.resource_actions'

- name: "Enforce instance count to 3 - Terminate 2 instances (check_mode)"
Expand All @@ -202,7 +204,10 @@
that:
- terminate_multiple_instances is not failed
- terminate_multiple_instances is changed
- '"instance_ids" not in terminate_multiple_instances'
- '"instance_ids" in terminate_multiple_instances'
- terminate_multiple_instances.instance_ids | length == 5
- '"terminated_ids" in terminate_multiple_instances'
- terminate_multiple_instances.terminated_ids | length == 2
- '"ec2:RunInstances" not in terminate_multiple_instances.resource_actions'

- name: "Enforce instance count to 3 - Terminate 2 instances"
Expand All @@ -221,6 +226,8 @@
that:
- terminate_multiple_instances is not failed
- terminate_multiple_instances is changed
- '"instance_ids" in terminate_multiple_instances'
- terminate_multiple_instances.instance_ids | length == 5
- '"terminated_ids" in terminate_multiple_instances'
- terminate_multiple_instances.terminated_ids | length == 2

Expand All @@ -240,7 +247,9 @@
that:
- terminate_multiple_instances is not failed
- terminate_multiple_instances is not changed
- '"instance_ids" not in terminate_multiple_instances'
- '"instance_ids" in terminate_multiple_instances'
- terminate_multiple_instances.instance_ids | length == 3
- '"terminated_ids" not in terminate_multiple_instances'
- '"ec2:TerminateInstances" not in terminate_multiple_instances.resource_actions'

- name: "Enforce instance count to 3 - Terminate 2 instances (Idempotency)"
Expand All @@ -258,7 +267,9 @@
that:
- terminate_multiple_instances is not failed
- terminate_multiple_instances is not changed
- '"instance_ids" not in terminate_multiple_instances'
- '"instance_ids" in terminate_multiple_instances'
- terminate_multiple_instances.instance_ids | length == 3
- '"terminated_ids" not in terminate_multiple_instances'
- '"ec2:TerminateInstances" not in terminate_multiple_instances.resource_actions'

- name: "Enforce instance count to 6 - Launch 3 more instances (check_mode)"
Expand All @@ -278,7 +289,9 @@
that:
- create_multiple_instances is not failed
- create_multiple_instances is changed
- '"instance_ids" not in create_multiple_instances'
- '"instance_ids" in create_multiple_instances'
- create_multiple_instances.instance_ids | length == 3
- '"changed_ids" not in create_multiple_instances'
- '"ec2:RunInstances" not in create_multiple_instances.resource_actions'

- name: "Enforce instance count to 6 - Launch 3 more instances"
Expand All @@ -301,7 +314,9 @@
- create_multiple_instances is not failed
- create_multiple_instances is changed
- '"instance_ids" in create_multiple_instances'
- create_multiple_instances.instance_ids | length == 3
- create_multiple_instances.instance_ids | length == 6
- '"changed_ids" in create_multiple_instances'
- create_multiple_instances.changed_ids | length == 3

- name: "Enforce instance count to 6 - Launch 3 more instances (check_mode - Idempotency)"
ec2_instance:
Expand All @@ -320,7 +335,9 @@
that:
- create_multiple_instances is not failed
- create_multiple_instances is not changed
- '"instance_ids" not in create_multiple_instances'
- '"instance_ids" in create_multiple_instances'
- create_multiple_instances.instance_ids | length == 6
- '"changed_ids" not in create_multiple_instances'
- '"ec2:RunInstances" not in create_multiple_instances.resource_actions'

- name: "Enforce instance count to 6 - Launch 3 more instances (Idempotency)"
Expand All @@ -339,7 +356,9 @@
that:
- create_multiple_instances is not failed
- create_multiple_instances is not changed
- '"instance_ids" not in create_multiple_instances'
- '"instance_ids" in create_multiple_instances'
- create_multiple_instances.instance_ids | length == 6
- '"changed_ids" not in create_multiple_instances'
- '"ec2:RunInstances" not in create_multiple_instances.resource_actions'


Expand Down