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

ec2_spot_instance_info: add new module for describing spot instance requests #487

Merged
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
8e2b4f3
Added initial work: ec2_spot_instance_info module
mandar242 Aug 30, 2021
39d41e0
Capture params from playbook
mandar242 Aug 31, 2021
10d9a97
Fix Filters case, add request call
mandar242 Aug 31, 2021
0c03f75
Adding basic descriptions
mandar242 Sep 1, 2021
4de8dbf
Minor description update
mandar242 Sep 1, 2021
8006494
Sanity fixes
mandar242 Sep 1, 2021
ed06ed6
Capture params from playbook
mandar242 Aug 31, 2021
0545927
Fix Filters case, add request call
mandar242 Aug 31, 2021
f952982
Adding basic descriptions
mandar242 Sep 1, 2021
23f3300
Minor description update
mandar242 Sep 1, 2021
e8a715f
bug fix, add return block
mandar242 Sep 2, 2021
b67d94b
Bugfix: handle multiple instance in response, Added filter example
mandar242 Sep 2, 2021
b0cf0a2
Fix exit_json response
mandar242 Sep 2, 2021
aa2cd95
Sanity fixes
mandar242 Sep 7, 2021
ac41431
Add integration test
mandar242 Sep 8, 2021
889b55a
Remove dry run
mandar242 Sep 8, 2021
cf0ac0d
Add paginator, remove next_token & max_result, add integration test
mandar242 Sep 8, 2021
e79efc9
Add integration test, example
mandar242 Sep 8, 2021
8cd9822
Add changelogs fragment, integration test
mandar242 Sep 9, 2021
b877e27
Correcting changelogs fragment category
mandar242 Sep 9, 2021
14297ea
Modified filter list, changed key, check_mode, integration test based…
mandar242 Sep 9, 2021
aee2d43
Modify cleanup
mandar242 Sep 10, 2021
69e4b17
Improved assertion readability
mandar242 Sep 10, 2021
e848556
Remove assertion from cleanup
mandar242 Sep 11, 2021
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
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).
1 change: 1 addition & 0 deletions meta/runtime.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
178 changes: 178 additions & 0 deletions plugins/modules/ec2_spot_instance_info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
#!/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)

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.
author:
- Mandar Vijay Kulkarni (@mandar242)
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
elements: dict
spot_instance_request_ids:
description:
- One or more Spot Instance request IDs.
type: list
elements: str

extends_documentation_fragment:
- amazon.aws.aws
- amazon.aws.ec2
'''

EXAMPLES = '''
# 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-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

- name: describe the Spot requests filtered using multiple filters
amazon.aws.ec2_spot_instance_info:
filters:
- name: 'state'
mandar242 marked this conversation as resolved.
Show resolved Hide resolved
values:
- active
- name: launch.block-device-mapping.device-name
values:
- /dev/sdb

'''

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"
}
'''


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.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
mandar242 marked this conversation as resolved.
Show resolved Hide resolved

if module.check_mode:
mandar242 marked this conversation as resolved.
Show resolved Hide resolved
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
if module.params.get('spot_instance_request_ids'):
params['SpotInstanceRequestIds'] = module.params.get('spot_instance_request_ids')

try:
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 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)


def main():

argument_spec = dict(
filters=dict(default=[], type='list', elements='dict'),
spot_instance_request_ids=dict(default=[], type='list', elements='str'),
)
module = AnsibleAWSModule(
argument_spec=argument_spec,
supports_check_mode=True
)
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()
1 change: 1 addition & 0 deletions tests/integration/targets/ec2_spot_instance/aliases
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
cloud/aws
ec2_spot_instance_info
60 changes: 60 additions & 0 deletions tests/integration/targets/ec2_spot_instance/tasks/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -104,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:
Expand Down Expand Up @@ -145,6 +157,41 @@
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']

- 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

- name: Assert that the correct keys are set while creating the spot instance with complex options
mandar242 marked this conversation as resolved.
Show resolved Hide resolved
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:
Expand Down Expand Up @@ -230,6 +277,19 @@
ignore_errors: true
retries: 5

- name: Get info about the complex spot instance request created
mandar242 marked this conversation as resolved.
Show resolved Hide resolved
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
mandar242 marked this conversation as resolved.
Show resolved Hide resolved
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"
Expand Down