From 8e2b4f3b7995913b1aa7143a20e9392b6cb1d4b3 Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Mon, 30 Aug 2021 16:13:23 -0700 Subject: [PATCH 01/24] Added initial work: ec2_spot_instance_info module --- meta/runtime.yml | 1 + plugins/modules/ec2_spot_instance_info.py | 58 +++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 plugins/modules/ec2_spot_instance_info.py diff --git a/meta/runtime.yml b/meta/runtime.yml index 10412c79bff..894f5ca7ecd 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -38,6 +38,7 @@ action_groups: - ec2_snapshot - ec2_snapshot_info - ec2_spot_instance + - ec2_spot_instance_info - ec2_tag - ec2_tag_info - ec2_vol diff --git a/plugins/modules/ec2_spot_instance_info.py b/plugins/modules/ec2_spot_instance_info.py new file mode 100644 index 00000000000..9e5839a9232 --- /dev/null +++ b/plugins/modules/ec2_spot_instance_info.py @@ -0,0 +1,58 @@ +#!/usr/bin/python +# This file is part of Ansible +# GNU General Public License v3.0+ (see COPYING or https://wwww.gnu.org/licenses/gpl-3.0.txt) + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +''' + +EXAMPLES = ''' +''' + +RETURN = ''' +''' + +import time +import datetime + +try: + import botocore +except ImportError: + pass # Handled by AnsibleAWSModule +from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import ansible_dict_to_boto3_filter_list +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import boto3_tag_list_to_ansible_dict +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import ansible_dict_to_boto3_tag_list +from ansible.module_utils.common.dict_transformations import snake_dict_to_camel_dict +from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict +from ansible_collections.amazon.aws.plugins.module_utils.core import is_boto3_error_code + +def describe_spot_instance_requests(module,connection): + pass + +def main(): + + argument_spec=dict( + filters=dict(default={}, type='list', elements='dict'), + dry_run_options = dict(type='bool'), + spot_instance_request__ids=dict(default=[], type='list', elements='str'), + next_token = dict(type='str'), + max_results = dict(type='int') + ) + module = AnsibleAWSModule( + argument_spec=argument_spec, + supports_check_mode=True + ) + print(argument_spec) + try: + connection = module.client('ec2', retry_decorator=AWSRetry.jittered_backoff()) + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: + module.fail_json_aws(e, msg='Failed to connect to AWS') + + describe_spot_instance_requests(connection, module) + +if __name__ == '__main__': + main() \ No newline at end of file From 39d41e0429a4072040c180018c8075898f369e81 Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Tue, 31 Aug 2021 11:07:50 -0700 Subject: [PATCH 02/24] Capture params from playbook --- plugins/modules/ec2_spot_instance_info.py | 28 ++++++++++++++++------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/plugins/modules/ec2_spot_instance_info.py b/plugins/modules/ec2_spot_instance_info.py index 9e5839a9232..e287d07697f 100644 --- a/plugins/modules/ec2_spot_instance_info.py +++ b/plugins/modules/ec2_spot_instance_info.py @@ -13,7 +13,6 @@ RETURN = ''' ''' - import time import datetime @@ -30,23 +29,36 @@ from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict from ansible_collections.amazon.aws.plugins.module_utils.core import is_boto3_error_code -def describe_spot_instance_requests(module,connection): +def describe_spot_instance_requests(connection, module): + + params = {} + + if module.params.get('filters'): + params['Filters'] = module.params.get('filters') + if module.params.get('dry_run'): + params['DryRun'] = module.params.get('dry_run') + if module.params.get('spot_instance_request_ids'): + params['SpotInstanceRequestIds'] = module.params.get('spot_instance_request_ids') + if module.params.get('next_token'): + params['NextToken'] = module.params.get('next_token') + if module.params.get('max_results'): + params['MaxResults'] = module.params.get('max_results') + pass def main(): argument_spec=dict( - filters=dict(default={}, type='list', elements='dict'), - dry_run_options = dict(type='bool'), - spot_instance_request__ids=dict(default=[], type='list', elements='str'), - next_token = dict(type='str'), + filters=dict(default=[], type='list', elements='dict'), + dry_run = dict(default=False, type='bool', choices=[True, False]), + spot_instance_request_ids=dict(default=[], type='list', elements='str'), + next_token = dict(default=None, type='str'), max_results = dict(type='int') ) module = AnsibleAWSModule( argument_spec=argument_spec, supports_check_mode=True ) - print(argument_spec) try: connection = module.client('ec2', retry_decorator=AWSRetry.jittered_backoff()) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: @@ -55,4 +67,4 @@ def main(): describe_spot_instance_requests(connection, module) if __name__ == '__main__': - main() \ No newline at end of file + main() From 10d9a9764533be3acf38ca23e58754242968a76c Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Tue, 31 Aug 2021 12:56:39 -0700 Subject: [PATCH 03/24] Fix Filters case, add request call --- plugins/modules/ec2_spot_instance_info.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/plugins/modules/ec2_spot_instance_info.py b/plugins/modules/ec2_spot_instance_info.py index e287d07697f..41c5a39f902 100644 --- a/plugins/modules/ec2_spot_instance_info.py +++ b/plugins/modules/ec2_spot_instance_info.py @@ -13,6 +13,8 @@ RETURN = ''' ''' + +import q import time import datetime @@ -31,10 +33,17 @@ def describe_spot_instance_requests(connection, module): + changed = True + + if module.check_mode: + module.exit_json(changed=changed) + params = {} if module.params.get('filters'): - params['Filters'] = module.params.get('filters') + filters_dit = module.params.get('filters') + camel_filters = snake_dict_to_camel_dict(filters_dit, capitalize_first=True) + params['Filters'] = camel_filters if module.params.get('dry_run'): params['DryRun'] = module.params.get('dry_run') if module.params.get('spot_instance_request_ids'): @@ -44,7 +53,14 @@ def describe_spot_instance_requests(connection, module): if module.params.get('max_results'): params['MaxResults'] = module.params.get('max_results') - pass + try: + describe_spot_instance_requests_response = (connection.describe_spot_instance_requests(**params)) + except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: + module.fail_json_aws(e, msg='Failed to describe sport instance requests') + + describe_spot_instance_requests_response['Tags'] = boto3_tag_list_to_ansible_dict(describe_spot_instance_requests_response.get('Tags', [])) + describe_spot_requests = camel_dict_to_snake_dict(describe_spot_instance_requests_response, ignore_list=['Tags']) + module.exit_json(describe_spot_requests=describe_spot_requests, changed=changed) def main(): From 0c03f758ec615501da5af3f5aab1f81e46663236 Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Wed, 1 Sep 2021 12:58:32 -0700 Subject: [PATCH 04/24] Adding basic descriptions --- plugins/modules/ec2_spot_instance_info.py | 37 +++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/plugins/modules/ec2_spot_instance_info.py b/plugins/modules/ec2_spot_instance_info.py index 41c5a39f902..33e63ba38e3 100644 --- a/plugins/modules/ec2_spot_instance_info.py +++ b/plugins/modules/ec2_spot_instance_info.py @@ -6,6 +6,39 @@ DOCUMENTATION = ''' --- +module: ec2_spot_instance_info +version_added: 2.0.0 +short_description: Gather information about ec2 spot instance requests +description: + - Describes the specified Spot Instance requests. +options: + filters: + description: + - A list of filters to apply. + - Each list item is a dict consisting of a filter key and a filter value. + - See U(https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSpotInstanceRequests.html) for possible filters. + type: list + dry_run: + description: + - A boolean to check if you have the required permissions for the action. + - Does not make the request. + - If required permissions are not present then returns an error response UnauthorizedOperation else DryRunOperation. + type: bool + spot_instance_request_ids: + description: + - One or more Spot Instance request IDs. + type: str + next_token: + description: + - A token to request the next set of results. + - Value is null when no more results to return + type: str + max_results: + description: + - Maximum number of results to be returned in a single call. + - Value can be between 5 and 1000. + type: int + ''' EXAMPLES = ''' @@ -19,9 +52,9 @@ import datetime try: - import botocore + import botocore except ImportError: - pass # Handled by AnsibleAWSModule + pass # Handled by AnsibleAWSModule from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry from ansible_collections.amazon.aws.plugins.module_utils.ec2 import ansible_dict_to_boto3_filter_list From 4de8dbfc2c22ea2fe6780dc7cda0c80644e2337a Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Wed, 1 Sep 2021 13:23:23 -0700 Subject: [PATCH 05/24] Minor description update --- plugins/modules/ec2_spot_instance_info.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/modules/ec2_spot_instance_info.py b/plugins/modules/ec2_spot_instance_info.py index 33e63ba38e3..f28893d8768 100644 --- a/plugins/modules/ec2_spot_instance_info.py +++ b/plugins/modules/ec2_spot_instance_info.py @@ -39,6 +39,9 @@ - Value can be between 5 and 1000. type: int +extends_documentation_fragment: +- amazon.aws.aws +- amazon.aws.ec2 ''' EXAMPLES = ''' @@ -47,7 +50,6 @@ RETURN = ''' ''' -import q import time import datetime From 80064947123ff310b561c591a1b98baf9cd592a8 Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Wed, 1 Sep 2021 16:00:22 -0700 Subject: [PATCH 06/24] Sanity fixes --- plugins/modules/ec2_spot_instance_info.py | 79 +++++++++++-------- .../targets/ec2_spot_instance/aliases | 1 + 2 files changed, 46 insertions(+), 34 deletions(-) diff --git a/plugins/modules/ec2_spot_instance_info.py b/plugins/modules/ec2_spot_instance_info.py index f28893d8768..61b8f9e789f 100644 --- a/plugins/modules/ec2_spot_instance_info.py +++ b/plugins/modules/ec2_spot_instance_info.py @@ -2,42 +2,44 @@ # This file is part of Ansible # GNU General Public License v3.0+ (see COPYING or https://wwww.gnu.org/licenses/gpl-3.0.txt) +from __future__ import absolute_import, division, print_function __metaclass__ = type + DOCUMENTATION = ''' --- module: ec2_spot_instance_info version_added: 2.0.0 short_description: Gather information about ec2 spot instance requests description: - - Describes the specified Spot Instance requests. + - Describes the specified Spot Instance requests. options: - filters: - description: - - A list of filters to apply. - - Each list item is a dict consisting of a filter key and a filter value. - - See U(https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSpotInstanceRequests.html) for possible filters. - type: list - dry_run: - description: - - A boolean to check if you have the required permissions for the action. - - Does not make the request. - - If required permissions are not present then returns an error response UnauthorizedOperation else DryRunOperation. - type: bool - spot_instance_request_ids: - description: - - One or more Spot Instance request IDs. - type: str - next_token: - description: - - A token to request the next set of results. - - Value is null when no more results to return - type: str - max_results: - description: - - Maximum number of results to be returned in a single call. - - Value can be between 5 and 1000. - type: int + filters: + description: + - A list of filters to apply. + - Each list item is a dict consisting of a filter key and a filter value. + - See U(https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSpotInstanceRequests.html) for possible filters. + type: list + dry_run: + description: + - A boolean to check if you have the required permissions for the action. + - Does not make the request. + - If required permissions are not present then returns an error response UnauthorizedOperation else DryRunOperation. + type: bool + spot_instance_request_ids: + description: + - One or more Spot Instance request IDs. + type: str + next_token: + description: + - A token to request the next set of results. + - Value is null when no more results to return + type: str + max_results: + description: + - Maximum number of results to be returned in a single call. + - Value can be between 5 and 1000. + type: int extends_documentation_fragment: - amazon.aws.aws @@ -48,15 +50,21 @@ ''' RETURN = ''' +# Note: These examples do not set authentication details, see the AWS Guide for details. + +- name: describe the Spot Instance requests based on request IDs + amazon.aws.ec2_spot_instance_info: + spot_instance_request_ids: + - sir-c3cp9jsk ''' import time import datetime try: - import botocore + import botocore except ImportError: - pass # Handled by AnsibleAWSModule + pass # Handled by AnsibleAWSModule from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry from ansible_collections.amazon.aws.plugins.module_utils.ec2 import ansible_dict_to_boto3_filter_list @@ -66,6 +74,7 @@ from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict from ansible_collections.amazon.aws.plugins.module_utils.core import is_boto3_error_code + def describe_spot_instance_requests(connection, module): changed = True @@ -95,16 +104,17 @@ def describe_spot_instance_requests(connection, module): describe_spot_instance_requests_response['Tags'] = boto3_tag_list_to_ansible_dict(describe_spot_instance_requests_response.get('Tags', [])) describe_spot_requests = camel_dict_to_snake_dict(describe_spot_instance_requests_response, ignore_list=['Tags']) - module.exit_json(describe_spot_requests=describe_spot_requests, changed=changed) + module.exit_json(spot_requests=describe_spot_requests, changed=changed) + def main(): - argument_spec=dict( + argument_spec = dict( filters=dict(default=[], type='list', elements='dict'), - dry_run = dict(default=False, type='bool', choices=[True, False]), + dry_run=dict(default=False, type='bool', choices=[True, False]), spot_instance_request_ids=dict(default=[], type='list', elements='str'), - next_token = dict(default=None, type='str'), - max_results = dict(type='int') + next_token=dict(default=None, type='str'), + max_results=dict(type='int') ) module = AnsibleAWSModule( argument_spec=argument_spec, @@ -117,5 +127,6 @@ def main(): describe_spot_instance_requests(connection, module) + if __name__ == '__main__': main() diff --git a/tests/integration/targets/ec2_spot_instance/aliases b/tests/integration/targets/ec2_spot_instance/aliases index 4ef4b2067d0..f556641fbed 100644 --- a/tests/integration/targets/ec2_spot_instance/aliases +++ b/tests/integration/targets/ec2_spot_instance/aliases @@ -1 +1,2 @@ cloud/aws +ec2_spot_instance_info \ No newline at end of file From ed06ed6a3513c9a6b627ec64f12581568af7a344 Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Tue, 31 Aug 2021 11:07:50 -0700 Subject: [PATCH 07/24] Capture params from playbook --- plugins/modules/ec2_spot_instance_info.py | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/modules/ec2_spot_instance_info.py b/plugins/modules/ec2_spot_instance_info.py index 61b8f9e789f..cd3c878f221 100644 --- a/plugins/modules/ec2_spot_instance_info.py +++ b/plugins/modules/ec2_spot_instance_info.py @@ -57,7 +57,6 @@ spot_instance_request_ids: - sir-c3cp9jsk ''' - import time import datetime From 05459275488178f909c36e118ee6e5c53dace563 Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Tue, 31 Aug 2021 12:56:39 -0700 Subject: [PATCH 08/24] Fix Filters case, add request call --- plugins/modules/ec2_spot_instance_info.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/modules/ec2_spot_instance_info.py b/plugins/modules/ec2_spot_instance_info.py index cd3c878f221..654075be454 100644 --- a/plugins/modules/ec2_spot_instance_info.py +++ b/plugins/modules/ec2_spot_instance_info.py @@ -57,6 +57,8 @@ spot_instance_request_ids: - sir-c3cp9jsk ''' + +import q import time import datetime From f9529829bd5416e812ca58316069f525ab556b15 Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Wed, 1 Sep 2021 12:58:32 -0700 Subject: [PATCH 09/24] Adding basic descriptions --- plugins/modules/ec2_spot_instance_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/ec2_spot_instance_info.py b/plugins/modules/ec2_spot_instance_info.py index 654075be454..9de90a69764 100644 --- a/plugins/modules/ec2_spot_instance_info.py +++ b/plugins/modules/ec2_spot_instance_info.py @@ -63,7 +63,7 @@ import datetime try: - import botocore + import botocore except ImportError: pass # Handled by AnsibleAWSModule from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule From 23f3300e4429233a7723d343c202d1f86bbf10d7 Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Wed, 1 Sep 2021 13:23:23 -0700 Subject: [PATCH 10/24] Minor description update --- plugins/modules/ec2_spot_instance_info.py | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/modules/ec2_spot_instance_info.py b/plugins/modules/ec2_spot_instance_info.py index 9de90a69764..bea066b9e2d 100644 --- a/plugins/modules/ec2_spot_instance_info.py +++ b/plugins/modules/ec2_spot_instance_info.py @@ -58,7 +58,6 @@ - sir-c3cp9jsk ''' -import q import time import datetime From e8a715f09315405afedf9edf06a4cb440de8c027 Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Wed, 1 Sep 2021 17:02:10 -0700 Subject: [PATCH 11/24] bug fix, add return block --- plugins/modules/ec2_spot_instance_info.py | 64 ++++++++++++++++++++--- 1 file changed, 56 insertions(+), 8 deletions(-) diff --git a/plugins/modules/ec2_spot_instance_info.py b/plugins/modules/ec2_spot_instance_info.py index bea066b9e2d..125c21f8971 100644 --- a/plugins/modules/ec2_spot_instance_info.py +++ b/plugins/modules/ec2_spot_instance_info.py @@ -13,6 +13,8 @@ short_description: Gather information about ec2 spot instance requests description: - Describes the specified Spot Instance requests. +author: + - Mandar Vijay Kulkarni (@mandar242) options: filters: description: @@ -20,16 +22,20 @@ - Each list item is a dict consisting of a filter key and a filter value. - See U(https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSpotInstanceRequests.html) for possible filters. type: list + elements: dict dry_run: description: - A boolean to check if you have the required permissions for the action. - Does not make the request. - If required permissions are not present then returns an error response UnauthorizedOperation else DryRunOperation. + default: False + choices: [ True, False ] type: bool spot_instance_request_ids: description: - One or more Spot Instance request IDs. - type: str + type: list + elements: str next_token: description: - A token to request the next set of results. @@ -47,15 +53,57 @@ ''' EXAMPLES = ''' -''' - -RETURN = ''' # Note: These examples do not set authentication details, see the AWS Guide for details. - name: describe the Spot Instance requests based on request IDs amazon.aws.ec2_spot_instance_info: spot_instance_request_ids: - - sir-c3cp9jsk + - sir-12345678 + +''' + +RETURN = ''' +spot_request: + description: The gathered information about specified spot instance requests. + returned: when success + type: dict + sample: { + "create_time": "2021-09-01T21:05:57+00:00", + "instance_id": "i-08877936b801ac475", + "instance_interruption_behavior": "terminate", + "launch_specification": { + "ebs_optimized": false, + "image_id": "ami-0443305dabd4be2bc", + "instance_type": "t2.medium", + "key_name": "zuul", + "monitoring": { + "enabled": false + }, + "placement": { + "availability_zone": "us-east-2b" + }, + "security_groups": [ + { + "group_id": "sg-01f9833207d53b937", + "group_name": "default" + } + ], + "subnet_id": "subnet-07d906b8358869bda" + }, + "launched_availability_zone": "us-east-2b", + "product_description": "Linux/UNIX", + "spot_instance_request_id": "sir-c3cp9jsk", + "spot_price": "0.046400", + "state": "active", + "status": { + "code": "fulfilled", + "message": "Your spot request is fulfilled.", + "update_time": "2021-09-01T21:05:59+00:00" + }, + "tags": {}, + "type": "one-time", + "valid_until": "2021-09-08T21:05:57+00:00" + } ''' import time @@ -98,13 +146,13 @@ def describe_spot_instance_requests(connection, module): params['MaxResults'] = module.params.get('max_results') try: - describe_spot_instance_requests_response = (connection.describe_spot_instance_requests(**params)) + describe_spot_instance_requests_response = (connection.describe_spot_instance_requests(**params))['SpotInstanceRequests'][0] except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg='Failed to describe sport instance requests') describe_spot_instance_requests_response['Tags'] = boto3_tag_list_to_ansible_dict(describe_spot_instance_requests_response.get('Tags', [])) describe_spot_requests = camel_dict_to_snake_dict(describe_spot_instance_requests_response, ignore_list=['Tags']) - module.exit_json(spot_requests=describe_spot_requests, changed=changed) + module.exit_json(spot_request=describe_spot_requests, changed=changed) def main(): @@ -113,7 +161,7 @@ def main(): filters=dict(default=[], type='list', elements='dict'), dry_run=dict(default=False, type='bool', choices=[True, False]), spot_instance_request_ids=dict(default=[], type='list', elements='str'), - next_token=dict(default=None, type='str'), + next_token=dict(default=None, type='str', no_log=False), max_results=dict(type='int') ) module = AnsibleAWSModule( From b67d94b47150748c82c575355f5af8eae51934c5 Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Thu, 2 Sep 2021 16:35:47 -0700 Subject: [PATCH 12/24] Bugfix: handle multiple instance in response, Added filter example --- plugins/modules/ec2_spot_instance_info.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/plugins/modules/ec2_spot_instance_info.py b/plugins/modules/ec2_spot_instance_info.py index 125c21f8971..8e21603b5c3 100644 --- a/plugins/modules/ec2_spot_instance_info.py +++ b/plugins/modules/ec2_spot_instance_info.py @@ -60,6 +60,17 @@ spot_instance_request_ids: - sir-12345678 +- name: describe the Spot Instance requests and filter results based on instance type + amazon.aws.ec2_spot_instance_info: + spot_instance_request_ids: + - sir-12345678 + - sir-13579246 + - sir-87654321 + filters: + - name: 'launch.instance-type' + values: + - t3.medium + ''' RETURN = ''' @@ -146,13 +157,17 @@ def describe_spot_instance_requests(connection, module): params['MaxResults'] = module.params.get('max_results') try: - describe_spot_instance_requests_response = (connection.describe_spot_instance_requests(**params))['SpotInstanceRequests'][0] + describe_spot_instance_requests_response = (connection.describe_spot_instance_requests(**params))['SpotInstanceRequests'] + import q + q(describe_spot_instance_requests_response) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg='Failed to describe sport instance requests') - describe_spot_instance_requests_response['Tags'] = boto3_tag_list_to_ansible_dict(describe_spot_instance_requests_response.get('Tags', [])) - describe_spot_requests = camel_dict_to_snake_dict(describe_spot_instance_requests_response, ignore_list=['Tags']) - module.exit_json(spot_request=describe_spot_requests, changed=changed) + spot_request = {'spot_instance_requests': []} + for response_list_item in describe_spot_instance_requests_response: + spot_request['spot_instance_requests'].append(camel_dict_to_snake_dict(response_list_item)) + + module.exit_json(spot_request=spot_request, changed=changed) def main(): From b0cf0a26e4a927e971f9e0c41ff0fa7ceb32efa1 Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Thu, 2 Sep 2021 16:57:07 -0700 Subject: [PATCH 13/24] Fix exit_json response --- plugins/modules/ec2_spot_instance_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/ec2_spot_instance_info.py b/plugins/modules/ec2_spot_instance_info.py index 8e21603b5c3..9aae4ec81fd 100644 --- a/plugins/modules/ec2_spot_instance_info.py +++ b/plugins/modules/ec2_spot_instance_info.py @@ -167,7 +167,7 @@ def describe_spot_instance_requests(connection, module): for response_list_item in describe_spot_instance_requests_response: spot_request['spot_instance_requests'].append(camel_dict_to_snake_dict(response_list_item)) - module.exit_json(spot_request=spot_request, changed=changed) + module.exit_json(spot_request=spot_request['spot_instance_requests'], changed=changed) def main(): From aa2cd956a1221808fe7340c7911170fba8916594 Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Tue, 7 Sep 2021 13:21:08 -0700 Subject: [PATCH 14/24] Sanity fixes --- plugins/modules/ec2_spot_instance_info.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/modules/ec2_spot_instance_info.py b/plugins/modules/ec2_spot_instance_info.py index 9aae4ec81fd..29aff37d7b9 100644 --- a/plugins/modules/ec2_spot_instance_info.py +++ b/plugins/modules/ec2_spot_instance_info.py @@ -121,7 +121,7 @@ import datetime try: - import botocore + import botocore except ImportError: pass # Handled by AnsibleAWSModule from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule @@ -165,7 +165,7 @@ def describe_spot_instance_requests(connection, module): spot_request = {'spot_instance_requests': []} for response_list_item in describe_spot_instance_requests_response: - spot_request['spot_instance_requests'].append(camel_dict_to_snake_dict(response_list_item)) + spot_request['spot_instance_requests'].append(camel_dict_to_snake_dict(response_list_item)) module.exit_json(spot_request=spot_request['spot_instance_requests'], changed=changed) From ac41431edf25523a5b9f98091d5a678e185cc847 Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Tue, 7 Sep 2021 22:04:36 -0700 Subject: [PATCH 15/24] Add integration test --- plugins/modules/ec2_spot_instance_info.py | 2 -- .../targets/ec2_spot_instance/tasks/main.yaml | 22 +++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/plugins/modules/ec2_spot_instance_info.py b/plugins/modules/ec2_spot_instance_info.py index 29aff37d7b9..541d4e9685d 100644 --- a/plugins/modules/ec2_spot_instance_info.py +++ b/plugins/modules/ec2_spot_instance_info.py @@ -158,8 +158,6 @@ def describe_spot_instance_requests(connection, module): try: describe_spot_instance_requests_response = (connection.describe_spot_instance_requests(**params))['SpotInstanceRequests'] - import q - q(describe_spot_instance_requests_response) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg='Failed to describe sport instance requests') diff --git a/tests/integration/targets/ec2_spot_instance/tasks/main.yaml b/tests/integration/targets/ec2_spot_instance/tasks/main.yaml index 6f1515f8aa8..964a2a12567 100644 --- a/tests/integration/targets/ec2_spot_instance/tasks/main.yaml +++ b/tests/integration/targets/ec2_spot_instance/tasks/main.yaml @@ -90,6 +90,17 @@ - create_result.spot_request.spot_instance_request_id is defined - create_result.spot_request.launch_specification.subnet_id == vpc_subnet_result.subnet.id + - name: Get info about the spot instance request created + ec2_spot_instance_info: + spot_instance_request_ids: + - "{{ create_result.spot_request.spot_instance_request_id }}" + register: spot_instance_info_result + + - name: Assert that the spot request created is open or active + assert: + that: + - spot_instance_info_result.spot_request[0].state in ['open', 'active'] + - name: Create spot request with more complex options ec2_spot_instance: launch_specification: @@ -145,6 +156,17 @@ launch_spec: '{{ complex_create_result.spot_request.launch_specification }}' spot_request_tags: '{{ complex_create_result.spot_request.tags }}' + - name: Get info about the complex spot instance request created + ec2_spot_instance_info: + spot_instance_request_ids: + - "{{ complex_create_result.spot_request.spot_instance_request_id }}" + register: complex_spot_instance_info_result + + - name: Assert that the complex spot request created is open or active + assert: + that: + - complex_spot_instance_info_result.spot_request[0].state in ['open', 'active'] + # Assert check mode - name: Create spot instance request (check_mode) ec2_spot_instance: From 889b55ad476c676b159e0f6b85d730cf9c517cdc Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Wed, 8 Sep 2021 10:50:23 -0700 Subject: [PATCH 16/24] Remove dry run --- plugins/modules/ec2_spot_instance_info.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/plugins/modules/ec2_spot_instance_info.py b/plugins/modules/ec2_spot_instance_info.py index 541d4e9685d..322261e45a2 100644 --- a/plugins/modules/ec2_spot_instance_info.py +++ b/plugins/modules/ec2_spot_instance_info.py @@ -23,14 +23,6 @@ - See U(https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSpotInstanceRequests.html) for possible filters. type: list elements: dict - dry_run: - description: - - A boolean to check if you have the required permissions for the action. - - Does not make the request. - - If required permissions are not present then returns an error response UnauthorizedOperation else DryRunOperation. - default: False - choices: [ True, False ] - type: bool spot_instance_request_ids: description: - One or more Spot Instance request IDs. @@ -147,8 +139,6 @@ def describe_spot_instance_requests(connection, module): filters_dit = module.params.get('filters') camel_filters = snake_dict_to_camel_dict(filters_dit, capitalize_first=True) params['Filters'] = camel_filters - if module.params.get('dry_run'): - params['DryRun'] = module.params.get('dry_run') if module.params.get('spot_instance_request_ids'): params['SpotInstanceRequestIds'] = module.params.get('spot_instance_request_ids') if module.params.get('next_token'): @@ -172,7 +162,6 @@ def main(): argument_spec = dict( filters=dict(default=[], type='list', elements='dict'), - dry_run=dict(default=False, type='bool', choices=[True, False]), spot_instance_request_ids=dict(default=[], type='list', elements='str'), next_token=dict(default=None, type='str', no_log=False), max_results=dict(type='int') From cf0ac0dcff6a4443a36d22a7fd46fea9de7f9da7 Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Wed, 8 Sep 2021 13:15:12 -0700 Subject: [PATCH 17/24] Add paginator, remove next_token & max_result, add integration test --- plugins/modules/ec2_spot_instance_info.py | 40 +++++-------------- .../targets/ec2_spot_instance/tasks/main.yaml | 13 ++++++ 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/plugins/modules/ec2_spot_instance_info.py b/plugins/modules/ec2_spot_instance_info.py index 322261e45a2..ab400f5a9a7 100644 --- a/plugins/modules/ec2_spot_instance_info.py +++ b/plugins/modules/ec2_spot_instance_info.py @@ -28,16 +28,6 @@ - One or more Spot Instance request IDs. type: list elements: str - next_token: - description: - - A token to request the next set of results. - - Value is null when no more results to return - type: str - max_results: - description: - - Maximum number of results to be returned in a single call. - - Value can be between 5 and 1000. - type: int extends_documentation_fragment: - amazon.aws.aws @@ -109,8 +99,6 @@ } ''' -import time -import datetime try: import botocore @@ -118,13 +106,12 @@ pass # Handled by AnsibleAWSModule from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import ansible_dict_to_boto3_filter_list -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import boto3_tag_list_to_ansible_dict -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import ansible_dict_to_boto3_tag_list from ansible.module_utils.common.dict_transformations import snake_dict_to_camel_dict from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict -from ansible_collections.amazon.aws.plugins.module_utils.core import is_boto3_error_code +def _describe_spot_instance_requests(connection, **params): + paginator = connection.get_paginator('describe_spot_instance_requests') + return paginator.paginate(**params).build_full_result() def describe_spot_instance_requests(connection, module): @@ -136,26 +123,23 @@ def describe_spot_instance_requests(connection, module): params = {} if module.params.get('filters'): - filters_dit = module.params.get('filters') - camel_filters = snake_dict_to_camel_dict(filters_dit, capitalize_first=True) + filters_dict = module.params.get('filters') + camel_filters = snake_dict_to_camel_dict(filters_dict, capitalize_first=True) params['Filters'] = camel_filters if module.params.get('spot_instance_request_ids'): params['SpotInstanceRequestIds'] = module.params.get('spot_instance_request_ids') - if module.params.get('next_token'): - params['NextToken'] = module.params.get('next_token') - if module.params.get('max_results'): - params['MaxResults'] = module.params.get('max_results') try: - describe_spot_instance_requests_response = (connection.describe_spot_instance_requests(**params))['SpotInstanceRequests'] + describe_spot_instance_requests_response = _describe_spot_instance_requests(connection, **params)['SpotInstanceRequests'] except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - module.fail_json_aws(e, msg='Failed to describe sport instance requests') + module.fail_json_aws(e, msg='Failed to describe spot instance requests') - spot_request = {'spot_instance_requests': []} + # spot_request = {'spot_instance_requests': []} + spot_request = [] for response_list_item in describe_spot_instance_requests_response: - spot_request['spot_instance_requests'].append(camel_dict_to_snake_dict(response_list_item)) + spot_request.append(camel_dict_to_snake_dict(response_list_item)) - module.exit_json(spot_request=spot_request['spot_instance_requests'], changed=changed) + module.exit_json(spot_request=spot_request, changed=changed) def main(): @@ -163,8 +147,6 @@ def main(): argument_spec = dict( filters=dict(default=[], type='list', elements='dict'), spot_instance_request_ids=dict(default=[], type='list', elements='str'), - next_token=dict(default=None, type='str', no_log=False), - max_results=dict(type='int') ) module = AnsibleAWSModule( argument_spec=argument_spec, diff --git a/tests/integration/targets/ec2_spot_instance/tasks/main.yaml b/tests/integration/targets/ec2_spot_instance/tasks/main.yaml index 964a2a12567..97ce7b34988 100644 --- a/tests/integration/targets/ec2_spot_instance/tasks/main.yaml +++ b/tests/integration/targets/ec2_spot_instance/tasks/main.yaml @@ -252,6 +252,19 @@ ignore_errors: true retries: 5 + - name: Get info about the complex spot instance request created + ec2_spot_instance_info: + spot_instance_request_ids: + - '{{ create_result.spot_request.spot_instance_request_id }}' + - '{{ complex_create_result.spot_request.spot_instance_request_id }}' + register: spot_instance_request_info_result + + - name: Assert that the created spot instance requests are removed + assert: + that: + - spot_instance_request_info_result.spot_request[0].state == 'cancelled' + - spot_instance_request_info_result.spot_request[1].state == 'cancelled' + - name: remove the security group ec2_group: name: "{{ resource_prefix }}-sg" From e79efc968954faf51621fcf1a2517df520e6a3d1 Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Wed, 8 Sep 2021 14:54:29 -0700 Subject: [PATCH 18/24] Add integration test, example --- plugins/modules/ec2_spot_instance_info.py | 16 +++++++++++++++- .../targets/ec2_spot_instance/tasks/main.yaml | 16 ++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/plugins/modules/ec2_spot_instance_info.py b/plugins/modules/ec2_spot_instance_info.py index ab400f5a9a7..4b1e6b391cb 100644 --- a/plugins/modules/ec2_spot_instance_info.py +++ b/plugins/modules/ec2_spot_instance_info.py @@ -53,6 +53,16 @@ values: - t3.medium +- name: describe the Spot requests filtered using multiple filters + amazon.aws.ec2_spot_instance_info: + filters: + - name: 'state' + values: + - active + - name: launch.block-device-mapping.device-name + values: + - /dev/sdb + ''' RETURN = ''' @@ -109,10 +119,12 @@ from ansible.module_utils.common.dict_transformations import snake_dict_to_camel_dict from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict + def _describe_spot_instance_requests(connection, **params): paginator = connection.get_paginator('describe_spot_instance_requests') return paginator.paginate(**params).build_full_result() + def describe_spot_instance_requests(connection, module): changed = True @@ -134,11 +146,13 @@ def describe_spot_instance_requests(connection, module): except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg='Failed to describe spot instance requests') - # spot_request = {'spot_instance_requests': []} spot_request = [] for response_list_item in describe_spot_instance_requests_response: spot_request.append(camel_dict_to_snake_dict(response_list_item)) + if len(spot_request) == 0: + module.exit_json(changed=changed, msg='No spot requests found for specified options') + module.exit_json(spot_request=spot_request, changed=changed) diff --git a/tests/integration/targets/ec2_spot_instance/tasks/main.yaml b/tests/integration/targets/ec2_spot_instance/tasks/main.yaml index 97ce7b34988..0b1046bd238 100644 --- a/tests/integration/targets/ec2_spot_instance/tasks/main.yaml +++ b/tests/integration/targets/ec2_spot_instance/tasks/main.yaml @@ -167,6 +167,22 @@ that: - complex_spot_instance_info_result.spot_request[0].state in ['open', 'active'] + - name: Get info about the created spot instance requests and filter result based on provided filters + ec2_spot_instance_info: + spot_instance_request_ids: + - '{{ create_result.spot_request.spot_instance_request_id }}' + - '{{ complex_create_result.spot_request.spot_instance_request_id }}' + filters: + - name: launch.block-device-mapping.device-name + values: + - /dev/sdb + register: spot_instance_info_filter_result + + - name: Assert that the correct spot request was returned in the filtered result + assert: + that: + - spot_instance_info_filter_result.spot_request[0].spot_instance_request_id == complex_create_result.spot_request.spot_instance_request_id + # Assert check mode - name: Create spot instance request (check_mode) ec2_spot_instance: From 8cd982209287c5fc470c6f21df36dfd1387199c4 Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Wed, 8 Sep 2021 18:20:05 -0700 Subject: [PATCH 19/24] Add changelogs fragment, integration test --- .../487-ec2_spot_instance_info-add-new-module.yml | 2 ++ .../targets/ec2_spot_instance/tasks/main.yaml | 11 ++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/487-ec2_spot_instance_info-add-new-module.yml diff --git a/changelogs/fragments/487-ec2_spot_instance_info-add-new-module.yml b/changelogs/fragments/487-ec2_spot_instance_info-add-new-module.yml new file mode 100644 index 00000000000..a12a5d6e067 --- /dev/null +++ b/changelogs/fragments/487-ec2_spot_instance_info-add-new-module.yml @@ -0,0 +1,2 @@ +new_plugin: +- ec2_spot_instance_info - Added a new module that describes the specified Spot Instance requests (https://github.com/ansible-collections/amazon.aws/pull/487). diff --git a/tests/integration/targets/ec2_spot_instance/tasks/main.yaml b/tests/integration/targets/ec2_spot_instance/tasks/main.yaml index 0b1046bd238..e975eec1155 100644 --- a/tests/integration/targets/ec2_spot_instance/tasks/main.yaml +++ b/tests/integration/targets/ec2_spot_instance/tasks/main.yaml @@ -115,6 +115,7 @@ volume_size: 5 network_interfaces: - associate_public_ip_address: False + subnet_id: "{{ vpc_subnet_result.subnet.id }}" delete_on_termination: True device_index: 0 placement: @@ -181,7 +182,15 @@ - name: Assert that the correct spot request was returned in the filtered result assert: that: - - spot_instance_info_filter_result.spot_request[0].spot_instance_request_id == complex_create_result.spot_request.spot_instance_request_id + - spot_instance_info_filter_result.spot_request[0].spot_instance_request_id == complex_create_result.spot_request.spot_instance_request_id + + - name: Assert that the correct keys are set while creating the spot instance with complex options + assert: + that: + - complex_create_result.spot_request.spot_price == "0.002000" + - complex_create_result.spot_request.launch_specification.block_device_mappings[0].ebs.volume_size == 5 + - complex_create_result.spot_request.launch_specification.block_device_mappings[0].ebs.volume_type == "gp3" + - complex_create_result.spot_request.launch_specification.network_interfaces[0].delete_on_termination == True # Assert check mode - name: Create spot instance request (check_mode) From b877e27a52d52ad88dce86bcedbb4a85e5c61833 Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Thu, 9 Sep 2021 14:13:20 -0700 Subject: [PATCH 20/24] Correcting changelogs fragment category --- .../fragments/487-ec2_spot_instance_info-add-new-module.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelogs/fragments/487-ec2_spot_instance_info-add-new-module.yml b/changelogs/fragments/487-ec2_spot_instance_info-add-new-module.yml index a12a5d6e067..31ac09c283e 100644 --- a/changelogs/fragments/487-ec2_spot_instance_info-add-new-module.yml +++ b/changelogs/fragments/487-ec2_spot_instance_info-add-new-module.yml @@ -1,2 +1,2 @@ -new_plugin: +minor_change: - ec2_spot_instance_info - Added a new module that describes the specified Spot Instance requests (https://github.com/ansible-collections/amazon.aws/pull/487). From 14297ea4981c638591286918c95e3215d80bb91e Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Thu, 9 Sep 2021 15:15:57 -0700 Subject: [PATCH 21/24] Modified filter list, changed key, check_mode, integration test based on feedback --- ...-ec2_spot_instance_info-add-new-module.yml | 2 +- plugins/modules/ec2_spot_instance_info.py | 38 +++++++------------ .../targets/ec2_spot_instance/tasks/main.yaml | 18 +++------ 3 files changed, 21 insertions(+), 37 deletions(-) diff --git a/changelogs/fragments/487-ec2_spot_instance_info-add-new-module.yml b/changelogs/fragments/487-ec2_spot_instance_info-add-new-module.yml index 31ac09c283e..6ba3d9767f5 100644 --- a/changelogs/fragments/487-ec2_spot_instance_info-add-new-module.yml +++ b/changelogs/fragments/487-ec2_spot_instance_info-add-new-module.yml @@ -1,2 +1,2 @@ -minor_change: +minor_changes: - ec2_spot_instance_info - Added a new module that describes the specified Spot Instance requests (https://github.com/ansible-collections/amazon.aws/pull/487). diff --git a/plugins/modules/ec2_spot_instance_info.py b/plugins/modules/ec2_spot_instance_info.py index 4b1e6b391cb..c7c06b0a703 100644 --- a/plugins/modules/ec2_spot_instance_info.py +++ b/plugins/modules/ec2_spot_instance_info.py @@ -18,14 +18,16 @@ options: filters: description: - - A list of filters to apply. - - Each list item is a dict consisting of a filter key and a filter value. + - A dict of filters to apply. Each dict item consists of a filter key and a filter value. + - Filter names and values are case sensitive. - See U(https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSpotInstanceRequests.html) for possible filters. - type: list - elements: dict + required: false + default: {} + type: dict spot_instance_request_ids: description: - One or more Spot Instance request IDs. + required: false type: list elements: str @@ -49,19 +51,13 @@ - sir-13579246 - sir-87654321 filters: - - name: 'launch.instance-type' - values: - - t3.medium + launch.instance-type: t3.medium - name: describe the Spot requests filtered using multiple filters amazon.aws.ec2_spot_instance_info: filters: - - name: 'state' - values: - - active - - name: launch.block-device-mapping.device-name - values: - - /dev/sdb + state: active + launch.block-device-mapping.device-name: /dev/sdb ''' @@ -118,6 +114,7 @@ from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry from ansible.module_utils.common.dict_transformations import snake_dict_to_camel_dict from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict +from ansible_collections.amazon.aws.plugins.module_utils.ec2 import ansible_dict_to_boto3_filter_list def _describe_spot_instance_requests(connection, **params): @@ -127,17 +124,10 @@ def _describe_spot_instance_requests(connection, **params): def describe_spot_instance_requests(connection, module): - changed = True - - if module.check_mode: - module.exit_json(changed=changed) - params = {} if module.params.get('filters'): - filters_dict = module.params.get('filters') - camel_filters = snake_dict_to_camel_dict(filters_dict, capitalize_first=True) - params['Filters'] = camel_filters + params['Filters'] = ansible_dict_to_boto3_filter_list(module.params.get('filters')) if module.params.get('spot_instance_request_ids'): params['SpotInstanceRequestIds'] = module.params.get('spot_instance_request_ids') @@ -151,15 +141,15 @@ def describe_spot_instance_requests(connection, module): spot_request.append(camel_dict_to_snake_dict(response_list_item)) if len(spot_request) == 0: - module.exit_json(changed=changed, msg='No spot requests found for specified options') + module.exit_json(msg='No spot requests found for specified options') - module.exit_json(spot_request=spot_request, changed=changed) + module.exit_json(spot_request=spot_request) def main(): argument_spec = dict( - filters=dict(default=[], type='list', elements='dict'), + filters=dict(default={}, type='dict'), spot_instance_request_ids=dict(default=[], type='list', elements='str'), ) module = AnsibleAWSModule( diff --git a/tests/integration/targets/ec2_spot_instance/tasks/main.yaml b/tests/integration/targets/ec2_spot_instance/tasks/main.yaml index e975eec1155..761d5ee8483 100644 --- a/tests/integration/targets/ec2_spot_instance/tasks/main.yaml +++ b/tests/integration/targets/ec2_spot_instance/tasks/main.yaml @@ -163,10 +163,14 @@ - "{{ complex_create_result.spot_request.spot_instance_request_id }}" register: complex_spot_instance_info_result - - name: Assert that the complex spot request created is open or active + - name: Assert that the complex spot request created is open/active and correct keys are set assert: that: - complex_spot_instance_info_result.spot_request[0].state in ['open', 'active'] + - complex_create_result.spot_request.spot_price == "0.002000" + - complex_create_result.spot_request.launch_specification.block_device_mappings[0].ebs.volume_size == 5 + - complex_create_result.spot_request.launch_specification.block_device_mappings[0].ebs.volume_type == "gp3" + - complex_create_result.spot_request.launch_specification.network_interfaces[0].delete_on_termination == True - name: Get info about the created spot instance requests and filter result based on provided filters ec2_spot_instance_info: @@ -174,9 +178,7 @@ - '{{ create_result.spot_request.spot_instance_request_id }}' - '{{ complex_create_result.spot_request.spot_instance_request_id }}' filters: - - name: launch.block-device-mapping.device-name - values: - - /dev/sdb + launch.block-device-mapping.device-name: /dev/sdb register: spot_instance_info_filter_result - name: Assert that the correct spot request was returned in the filtered result @@ -184,14 +186,6 @@ that: - spot_instance_info_filter_result.spot_request[0].spot_instance_request_id == complex_create_result.spot_request.spot_instance_request_id - - name: Assert that the correct keys are set while creating the spot instance with complex options - assert: - that: - - complex_create_result.spot_request.spot_price == "0.002000" - - complex_create_result.spot_request.launch_specification.block_device_mappings[0].ebs.volume_size == 5 - - complex_create_result.spot_request.launch_specification.block_device_mappings[0].ebs.volume_type == "gp3" - - complex_create_result.spot_request.launch_specification.network_interfaces[0].delete_on_termination == True - # Assert check mode - name: Create spot instance request (check_mode) ec2_spot_instance: From aee2d43cfcec7387fdad8ca1209846a671098134 Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Fri, 10 Sep 2021 13:53:03 -0700 Subject: [PATCH 22/24] Modify cleanup --- .../targets/ec2_spot_instance/tasks/main.yaml | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/tests/integration/targets/ec2_spot_instance/tasks/main.yaml b/tests/integration/targets/ec2_spot_instance/tasks/main.yaml index 761d5ee8483..953740441ff 100644 --- a/tests/integration/targets/ec2_spot_instance/tasks/main.yaml +++ b/tests/integration/targets/ec2_spot_instance/tasks/main.yaml @@ -80,6 +80,8 @@ key_name: "{{ resource_prefix }}-keypair" instance_type: "t2.medium" subnet_id: "{{ vpc_subnet_result.subnet.id }}" + tags: + ansible-test: "{{ resource_prefix }}" register: create_result - name: Assert that result has changed and request has been created @@ -129,6 +131,7 @@ snake_case: "hello_world" "Title Case": "Hello World" "lowercase spaced": "hello world" + ansible-test: "{{ resource_prefix }}" register: complex_create_result - assert: @@ -147,7 +150,7 @@ - launch_spec.network_interfaces.0.device_index == 0 - launch_spec.network_interfaces.0.associate_public_ip_address == false - launch_spec.network_interfaces.0.delete_on_termination == true - - spot_request_tags|length == 5 + - spot_request_tags|length == 6 - spot_request_tags['camelCase'] == 'helloWorld' - spot_request_tags['PascalCase'] == 'HelloWorld' - spot_request_tags['snake_case'] == 'hello_world' @@ -194,6 +197,8 @@ key_name: "{{ resource_prefix }}-keypair" instance_type: "t2.medium" subnet_id: "{{ vpc_subnet_result.subnet.id }}" + tags: + ansible-test: "{{ resource_prefix }}" check_mode: True register: check_create_result @@ -262,27 +267,26 @@ filters: vpc-id: "{{ vpc_result.vpc.id }}" + - name: get all spot requests created during test + ec2_spot_instance_info: + filters: + tag:ansible-test: "{{ resource_prefix }}" + register: spot_request_list + - name: remove spot instance requests ec2_spot_instance: spot_instance_request_ids: - - '{{ create_result.spot_request.spot_instance_request_id }}' - - '{{ complex_create_result.spot_request.spot_instance_request_id }}' + - '{{ item.spot_instance_request_id }}' state: 'absent' ignore_errors: true retries: 5 - - - name: Get info about the complex spot instance request created - ec2_spot_instance_info: - spot_instance_request_ids: - - '{{ create_result.spot_request.spot_instance_request_id }}' - - '{{ complex_create_result.spot_request.spot_instance_request_id }}' - register: spot_instance_request_info_result + with_items: "{{ spot_request_list.spot_request }}" - name: Assert that the created spot instance requests are removed assert: that: - - spot_instance_request_info_result.spot_request[0].state == 'cancelled' - - spot_instance_request_info_result.spot_request[1].state == 'cancelled' + - item.state == 'cancelled' + with_items: "{{ spot_request_list.spot_request }}" - name: remove the security group ec2_group: From 69e4b172ce3ebbadf959359e522f5b4c9d25ff6e Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Fri, 10 Sep 2021 14:34:57 -0700 Subject: [PATCH 23/24] Improved assertion readability --- .../targets/ec2_spot_instance/tasks/main.yaml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/tests/integration/targets/ec2_spot_instance/tasks/main.yaml b/tests/integration/targets/ec2_spot_instance/tasks/main.yaml index 953740441ff..5fa6ef3adaf 100644 --- a/tests/integration/targets/ec2_spot_instance/tasks/main.yaml +++ b/tests/integration/targets/ec2_spot_instance/tasks/main.yaml @@ -164,16 +164,19 @@ ec2_spot_instance_info: spot_instance_request_ids: - "{{ complex_create_result.spot_request.spot_instance_request_id }}" - register: complex_spot_instance_info_result + register: complex_info_result - name: Assert that the complex spot request created is open/active and correct keys are set assert: that: - - complex_spot_instance_info_result.spot_request[0].state in ['open', 'active'] - - complex_create_result.spot_request.spot_price == "0.002000" - - complex_create_result.spot_request.launch_specification.block_device_mappings[0].ebs.volume_size == 5 - - complex_create_result.spot_request.launch_specification.block_device_mappings[0].ebs.volume_type == "gp3" - - complex_create_result.spot_request.launch_specification.network_interfaces[0].delete_on_termination == True + - complex_info_result.spot_request[0].state in ['open', 'active'] + - complex_create_result.spot_request.spot_price == complex_info_result.spot_request[0].spot_price + - create_launch_spec.block_device_mappings[0].ebs.volume_size == info_launch_spec.block_device_mappings[0].ebs.volume_size + - create_launch_spec.block_device_mappings[0].ebs.volume_type == info_launch_spec.block_device_mappings[0].ebs.volume_type + - create_launch_spec.network_interfaces[0].delete_on_termination == info_launch_spec.network_interfaces[0].delete_on_termination + vars: + create_launch_spec: "{{ complex_create_result.spot_request.launch_specification }}" + info_launch_spec: "{{ complex_info_result.spot_request[0].launch_specification }}" - name: Get info about the created spot instance requests and filter result based on provided filters ec2_spot_instance_info: @@ -181,6 +184,7 @@ - '{{ create_result.spot_request.spot_instance_request_id }}' - '{{ complex_create_result.spot_request.spot_instance_request_id }}' filters: + tag:ansible-test: "{{ resource_prefix }}" launch.block-device-mapping.device-name: /dev/sdb register: spot_instance_info_filter_result From e84855621d50154a9a0ca087a1de09709ec0ce29 Mon Sep 17 00:00:00 2001 From: Mandar Kulkarni Date: Fri, 10 Sep 2021 17:35:27 -0700 Subject: [PATCH 24/24] Remove assertion from cleanup --- tests/integration/targets/ec2_spot_instance/tasks/main.yaml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/integration/targets/ec2_spot_instance/tasks/main.yaml b/tests/integration/targets/ec2_spot_instance/tasks/main.yaml index 5fa6ef3adaf..680b3249964 100644 --- a/tests/integration/targets/ec2_spot_instance/tasks/main.yaml +++ b/tests/integration/targets/ec2_spot_instance/tasks/main.yaml @@ -286,12 +286,6 @@ retries: 5 with_items: "{{ spot_request_list.spot_request }}" - - name: Assert that the created spot instance requests are removed - assert: - that: - - item.state == 'cancelled' - with_items: "{{ spot_request_list.spot_request }}" - - name: remove the security group ec2_group: name: "{{ resource_prefix }}-sg"