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_instance : Add hibernation_options and volumes->ebs->encrypted keys #972

2 changes: 2 additions & 0 deletions changelogs/fragments/972-ec2_instance-stop-hibernate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- ec2_instance - Add hibernation_options and volumes->ebs->encrypted keys to support stop-hibernate instance (https://github.com/ansible-collections/amazon.aws/pull/972).
18 changes: 18 additions & 0 deletions plugins/modules/ec2_instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,14 @@
- Whether to enable termination protection.
- This module will not terminate an instance with termination protection active, it must be turned off first.
type: bool
hibernation_options:
description:
GomathiselviS marked this conversation as resolved.
Show resolved Hide resolved
- Indicates whether an instance is enabled for hibernation.
Refer U(https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/hibernating-prerequisites.html)
for Hibernation prerequisits.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this option requires a specific botocore version you should add a note here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This option is available in the latest and the versions we support.

type: bool
GomathiselviS marked this conversation as resolved.
Show resolved Hide resolved
default: False
version_added: 5.0.0
cpu_credit_specification:
description:
- For T series instances, choose whether to allow increased charges to buy CPU credits if the default pool is depleted.
Expand Down Expand Up @@ -1289,6 +1297,15 @@ def build_top_level_options(params):
spec['InstanceInitiatedShutdownBehavior'] = params.get('instance_initiated_shutdown_behavior')
if params.get('termination_protection') is not None:
spec['DisableApiTermination'] = params.get('termination_protection')
if params.get('hibernation_options') and params.get('volumes'):
for vol in params['volumes']:
if vol.get('ebs') and vol['ebs'].get('encrypted'):
spec['HibernationOptions'] = {'Configured': True}
else:
module.fail_json(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if we want to fail here. Do we want to only warn the user that hibernation_options cannot be enabled because the volume is not encrypted and allow the user to perform the task ignoring hibernation_options? @tremble @jillr

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually we'd throw an error. What would actually happen if they try to enable the option without encryption?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hibernation_options : true without volume.ebs.encryptions (true) is not accepted by AWS. It throws an error and fails.

msg="Hibernation prerequisites not satisfied. Refer {0}".format(
"https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/hibernating-prerequisites.html")
)
if params.get('cpu_options') is not None:
spec['CpuOptions'] = {}
spec['CpuOptions']['ThreadsPerCore'] = params.get('cpu_options').get('threads_per_core')
Expand Down Expand Up @@ -2020,6 +2037,7 @@ def main():
placement_group=dict(type='str'),
instance_initiated_shutdown_behavior=dict(type='str', choices=['stop', 'terminate']),
termination_protection=dict(type='bool'),
hibernation_options=dict(type='bool', default=False),
detailed_monitoring=dict(type='bool'),
instance_ids=dict(default=[], type='list', elements='str'),
network=dict(default=None, type='dict'),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
cloud/aws
ec2_instance_info
GomathiselviS marked this conversation as resolved.
Show resolved Hide resolved
ec2_instance
GomathiselviS marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
# defaults file for ec2_instance
ec2_instance_type: 't3.micro'
ec2_instance_tag_TestId: '{{ resource_prefix }}-instance-hibernation-options'
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# this just makes sure they're in the right place
dependencies:
- role: setup_ec2_facts
- role: setup_ec2_instance_env
vars:
ec2_instance_test_name: hibernation_options
- role: setup_botocore_pip
vars:
boto3_version: "1.20.30"
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
- module_defaults:
group/aws:
aws_access_key: "{{ aws_access_key }}"
aws_secret_key: "{{ aws_secret_key }}"
security_token: "{{ security_token | default(omit) }}"
region: "{{ aws_region }}"
block:
- name: Create instance with hibernation option (check mode)
ec2_instance:
name: "{{ resource_prefix }}-hibernation-options"
image_id: "{{ ec2_ami_id }}"
tags:
TestId: "{{ resource_prefix }}"
security_groups: "{{ sg.group_id }}"
vpc_subnet_id: "{{ testing_subnet_b.subnet.id }}"
hibernation_options: true
instance_type: "{{ ec2_instance_type }}"
volumes:
- device_name: /dev/sda1
ebs:
delete_on_termination: true
encrypted: true
state: running
wait: yes
check_mode: yes
register: create_instance_check_mode_results

- name: Check the returned value for the earlier task
assert:
that:
- create_instance_check_mode_results is changed
- create_instance_check_mode_results.spec.HibernationOptions.Configured == True

- name: Create instance with hibernation config
ec2_instance:
name: "{{ resource_prefix }}-hibernation-options"
image_id: "{{ ec2_ami_id }}"
tags:
TestId: "{{ resource_prefix }}"
security_groups: "{{ sg.group_id }}"
vpc_subnet_id: "{{ testing_subnet_b.subnet.id }}"
hibernation_options: true
instance_type: "{{ ec2_instance_type }}"
volumes:
- device_name: /dev/sda1
ebs:
delete_on_termination: true
encrypted: true
state: running
wait: yes
register: create_instance_results

- set_fact:
instance_id: '{{ create_instance_results.instances[0].instance_id }}'

- name: Check return values of the create instance task
assert:
that:
- "{{ create_instance_results.instances | length }} > 0"
- "'{{ create_instance_results.instances.0.state.name }}' == 'running'"
- "'{{ create_instance_results.spec.HibernationOptions.Configured }}'"

- name: Gather information about the instance to get the hibernation status
ec2_instance_info:
filters:
"tag:Name": "{{ resource_prefix }}-hibernation-options"
register: instance_hibernation_status

- name: Assert hibernation options is true
assert:
that:
- instance_hibernation_status.instances[0].hibernation_options.configured == true

- name: Create instance with hibernation option (check mode) (idempotent)
ec2_instance:
name: "{{ resource_prefix }}-hibernation-options"
image_id: "{{ ec2_ami_id }}"
tags:
TestId: "{{ resource_prefix }}"
security_groups: "{{ sg.group_id }}"
vpc_subnet_id: "{{ testing_subnet_b.subnet.id }}"
hibernation_options: true
instance_type: "{{ ec2_instance_type }}"
volumes:
- device_name: /dev/sda1
ebs:
delete_on_termination: true
encrypted: true
state: running
wait: yes
check_mode: yes
register: create_instance_check_mode_results

- name: Check the returned value for the earlier task
assert:
that:
- create_instance_check_mode_results is not changed

- name: Create instance with hibernation options configured (idempotent)
ec2_instance:
name: "{{ resource_prefix }}-hibernation-options"
image_id: "{{ ec2_ami_id }}"
tags:
TestId: "{{ resource_prefix }}"
security_groups: "{{ sg.group_id }}"
vpc_subnet_id: "{{ testing_subnet_b.subnet.id }}"
hibernation_options: true
instance_type: "{{ ec2_instance_type }}"
volumes:
- device_name: /dev/sda1
ebs:
delete_on_termination: true
encrypted: true
state: running
wait: yes
register: create_instance_results

- name: Check return values of the create instance task
assert:
that:
- "{{ not create_instance_results.changed }}"
- "{{ create_instance_results.instances | length }} > 0"

- name: Create instance with hibernation options configured with unencrypted volume
ec2_instance:
name: "{{ resource_prefix }}-hibernation-options-error"
image_id: "{{ ec2_ami_id }}"
tags:
TestId: "{{ resource_prefix }}"
security_groups: "{{ sg.group_id }}"
vpc_subnet_id: "{{ testing_subnet_b.subnet.id }}"
hibernation_options: true
instance_type: "{{ ec2_instance_type }}"
volumes:
- device_name: /dev/sda1
ebs:
delete_on_termination: true
register: create_instance_results
failed_when: "'Hibernation prerequisites not satisfied' not in create_instance_results.msg"

- name: Terminate the instance
ec2_instance:
filters:
tag:TestId: "{{ resource_prefix }}"
state: absent