From 7ff21336e87509a1bf0dcb1c2c02bc93c5c7384a Mon Sep 17 00:00:00 2001 From: Sean Cavanaugh Date: Wed, 13 Jan 2021 13:48:15 -0500 Subject: [PATCH] add uptime parameter for ec2_instance_info module in minutes (#356) * syncing module and tests for uptime with tons of help from Yanis, we now have uptime in there * updating pr with fixes from suggestions adding to https://github.com/ansible-collections/community.aws/pull/356 with comments from @tremble and @duderamos * Create 356_add_minimum_uptime_parameter.yaml adding changelog fragment per @gravesm suggestion * Update 356_add_minimum_uptime_parameter.yaml last comment from @tremble Co-authored-by: Sean Cavanaugh --- .../356_add_minimum_uptime_parameter.yaml | 3 + plugins/modules/ec2_instance_info.py | 33 +++++++++- .../roles/ec2_instance/tasks/uptime.yml | 66 +++++++++++++++++++ 3 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 changelogs/fragments/356_add_minimum_uptime_parameter.yaml create mode 100644 tests/integration/targets/ec2_instance/roles/ec2_instance/tasks/uptime.yml diff --git a/changelogs/fragments/356_add_minimum_uptime_parameter.yaml b/changelogs/fragments/356_add_minimum_uptime_parameter.yaml new file mode 100644 index 00000000000..c436c96f0ea --- /dev/null +++ b/changelogs/fragments/356_add_minimum_uptime_parameter.yaml @@ -0,0 +1,3 @@ +--- +minor_changes: +- ec2_instance_info - added ``minimum_uptime`` option with alias ``uptime`` for filtering instances that have only been online for certain duration of time in minutes (https://github.com/ansible-collections/community.aws/pull/356). diff --git a/plugins/modules/ec2_instance_info.py b/plugins/modules/ec2_instance_info.py index 1c4c1f0df33..e37f2cf9cd1 100644 --- a/plugins/modules/ec2_instance_info.py +++ b/plugins/modules/ec2_instance_info.py @@ -33,6 +33,13 @@ required: false default: {} type: dict + minimum_uptime: + description: + - Minimum running uptime in minutes of instances. For example if I(uptime) is C(60) return all instances that have run more than 60 minutes. + required: false + aliases: ['uptime'] + type: int + extends_documentation_fragment: - amazon.aws.aws @@ -66,6 +73,15 @@ filters: instance-state-name: [ "shutting-down", "stopping", "stopped" ] +- name: Gather information about any instance with Name beginning with RHEL and an uptime of at least 60 minutes + community.aws.ec2_instance_info: + region: "{{ ec2_region }}" + uptime: 60 + filters: + "tag:Name": "RHEL-*" + instance-state-name: [ "running"] + register: ec2_node_info + ''' RETURN = r''' @@ -492,6 +508,8 @@ ''' import traceback +import datetime + try: import boto3 @@ -509,6 +527,7 @@ def list_ec2_instances(connection, module): instance_ids = module.params.get("instance_ids") + uptime = module.params.get('minimum_uptime') filters = ansible_dict_to_boto3_filter_list(module.params.get("filters")) try: @@ -517,10 +536,17 @@ def list_ec2_instances(connection, module): except ClientError as e: module.fail_json_aws(e, msg="Failed to list ec2 instances") - # Get instances from reservations instances = [] - for reservation in reservations['Reservations']: - instances = instances + reservation['Instances'] + + if uptime: + timedelta = int(uptime) if uptime else 0 + oldest_launch_time = datetime.datetime.utcnow() - datetime.timedelta(minutes=timedelta) + # Get instances from reservations + for reservation in reservations['Reservations']: + instances += [instance for instance in reservation['Instances'] if instance['LaunchTime'].replace(tzinfo=None) < oldest_launch_time] + else: + for reservation in reservations['Reservations']: + instances = instances + reservation['Instances'] # Turn the boto3 result in to ansible_friendly_snaked_names snaked_instances = [camel_dict_to_snake_dict(instance) for instance in instances] @@ -535,6 +561,7 @@ def list_ec2_instances(connection, module): def main(): argument_spec = dict( + minimum_uptime=dict(required=False, type='int', default=None, aliases=['uptime']), instance_ids=dict(default=[], type='list', elements='str'), filters=dict(default={}, type='dict') ) diff --git a/tests/integration/targets/ec2_instance/roles/ec2_instance/tasks/uptime.yml b/tests/integration/targets/ec2_instance/roles/ec2_instance/tasks/uptime.yml new file mode 100644 index 00000000000..6f6c5fe0d49 --- /dev/null +++ b/tests/integration/targets/ec2_instance/roles/ec2_instance/tasks/uptime.yml @@ -0,0 +1,66 @@ +--- +- block: + - name: "create t3.nano instance" + ec2_instance: + name: "{{ resource_prefix }}-test-uptime" + region: "{{ ec2_region }}" + image_id: "{{ ec2_ami_image }}" + tags: + TestId: "{{ ec2_instance_tag_TestId }}" + vpc_subnet_id: "{{ testing_subnet_a.subnet.id }}" + instance_type: t3.nano + wait: yes + + - name: "check ec2 instance" + ec2_instance_info: + filters: + "tag:Name": "{{ resource_prefix }}-test-uptime" + instance-state-name: [ "running"] + register: instance_facts + + - name: "Confirm existence of instance id." + assert: + that: + - "{{ instance_facts.instances | length }} == 1" + + - name: "check using uptime 100 hours - should find nothing" + ec2_instance_info: + region: "{{ ec2_region }}" + uptime: 6000 + filters: + instance-state-name: [ "running"] + "tag:Name": "{{ resource_prefix }}-test-uptime" + register: instance_facts + + - name: "Confirm there is no running instance" + assert: + that: + - "{{ instance_facts.instances | length }} == 0" + + - name: Sleep for 61 seconds and continue with play + wait_for: + timeout: 61 + delegate_to: localhost + + - name: "check using uptime 1 minute" + ec2_instance_info: + region: "{{ ec2_region }}" + uptime: 1 + filters: + instance-state-name: [ "running"] + "tag:Name": "{{ resource_prefix }}-test-uptime" + register: instance_facts + + - name: "Confirm there is one running instance" + assert: + that: + - "{{ instance_facts.instances | length }} == 1" + + always: + - name: "Terminate instances" + ec2_instance: + state: absent + filters: + "tag:TestId": "{{ ec2_instance_tag_TestId }}" + wait: yes + ignore_errors: yes