Skip to content

Commit

Permalink
ec2_instance don't change termination protection in check mode (ansib…
Browse files Browse the repository at this point in the history
…le-collections#505)

* ec2_instance don't change termination protection in check mode

Fixes: ansible/ansible/issues/67716
Extend termination protection tests

* Set the path for the aws CLI tool - setting ansible_python_interpreter updates the python search path but not the shell search path

* changelog

Co-authored-by: Mark Chappell <[email protected]>
  • Loading branch information
jillr and tremble authored Apr 3, 2021
1 parent 60d09d0 commit b216f8d
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bugfixes:
- ec2_instance - ensure that termination protection isn't modified when using check_mode (https://github.com/ansible/ansible/issues/67716).
4 changes: 3 additions & 1 deletion plugins/modules/ec2_instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -1512,6 +1512,7 @@ def change_instance_state(filters, desired_state, ec2=None):
unchanged = set()
failure_reason = ""

# TODO: better check_moding in here https://github.com/ansible-collections/community.aws/issues/16
for inst in instances:
try:
if desired_state == 'TERMINATED':
Expand Down Expand Up @@ -1588,7 +1589,8 @@ def handle_existing(existing_matches, changed, ec2, state):
)
changes = diff_instance_and_params(existing_matches[0], module.params)
for c in changes:
ec2.modify_instance_attribute(aws_retry=True, **c)
if not module.check_mode:
ec2.modify_instance_attribute(aws_retry=True, **c)
changed |= bool(changes)
changed |= add_or_update_instance_profile(existing_matches[0], module.params.get('instance_role'))
changed |= change_network_attachments(existing_matches[0], module.params, ec2)
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/targets/ec2_instance/inventory
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ default_vpc_tests
external_resource_attach
instance_no_wait
iam_instance_role
termination_protection
termination_protection_wrapper
tags_and_vpc_settings
checkmode_tests
security_group
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
- block:

- name: Create instance with termination protection (check mode)
ec2_instance:
name: "{{ resource_prefix }}-termination-protection"
Expand Down Expand Up @@ -35,13 +34,34 @@
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.DisableApiTermination }}'"

- name: Get info on termination protection
command: '{{ aws_cli }} ec2 describe-instance-attribute --attribute disableApiTermination --instance-id {{ instance_id }}'
environment:
AWS_ACCESS_KEY_ID: "{{ aws_access_key }}"
AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}"
AWS_SESSION_TOKEN: "{{ security_token | default('') }}"
AWS_DEFAULT_REGION: "{{ aws_region }}"
register: instance_termination_check

- name: convert it to an object
set_fact:
instance_termination_status: "{{ instance_termination_check.stdout | from_json }}"

- name: Assert termination protection status did not change in check_mode
assert:
that:
- instance_termination_status.DisableApiTermination.Value == true

- name: Create instance with termination protection (check mode) (idempotent)
ec2_instance:
name: "{{ resource_prefix }}-termination-protection"
Expand Down Expand Up @@ -90,13 +110,46 @@
failed_when: "'Unable to terminate instances' not in terminate_instance_results.msg"
register: terminate_instance_results

# https://github.com/ansible/ansible/issues/67716
# Updates to termination protection in check mode has a bug (listed above)
- name: Set termination protection to false (check_mode)
ec2_instance:
name: "{{ resource_prefix }}-termination-protection"
image_id: "{{ ec2_ami_image }}"
tags:
TestId: "{{ resource_prefix }}"
termination_protection: false
instance_type: "{{ ec2_instance_type }}"
vpc_subnet_id: "{{ testing_subnet_b.subnet.id }}"
check_mode: True
register: set_termination_protectioncheck_mode_results

- name: Check return value
assert:
that:
- "{{ set_termination_protectioncheck_mode_results.changed }}"

- name: Get info on termination protection
command: '{{ aws_cli }} ec2 describe-instance-attribute --attribute disableApiTermination --instance-id {{ instance_id }}'
environment:
AWS_ACCESS_KEY_ID: "{{ aws_access_key }}"
AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}"
AWS_SESSION_TOKEN: "{{ security_token | default('') }}"
AWS_DEFAULT_REGION: "{{ aws_region }}"
register: instance_termination_check

- name: convert it to an object
set_fact:
instance_termination_status: "{{ instance_termination_check.stdout | from_json }}"

- assert:
that:
- instance_termination_status.DisableApiTermination.Value == true

- name: Set termination protection to false
ec2_instance:
name: "{{ resource_prefix }}-termination-protection"
image_id: "{{ ec2_ami_image }}"
tags:
TestId: "{{ resource_prefix }}"
termination_protection: false
instance_type: "{{ ec2_instance_type }}"
vpc_subnet_id: "{{ testing_subnet_b.subnet.id }}"
Expand All @@ -105,13 +158,31 @@
- name: Check return value
assert:
that:
- "{{ set_termination_protection_results.changed }}"
- "{{ not set_termination_protection_results.changes[0].DisableApiTermination.Value }}"
- set_termination_protection_results.changed

- name: Get info on termination protection
command: '{{ aws_cli }} ec2 describe-instance-attribute --attribute disableApiTermination --instance-id {{ instance_id }}'
environment:
AWS_ACCESS_KEY_ID: "{{ aws_access_key }}"
AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}"
AWS_SESSION_TOKEN: "{{ security_token | default('') }}"
AWS_DEFAULT_REGION: "{{ aws_region }}"
register: instance_termination_check

- name: convert it to an object
set_fact:
instance_termination_status: "{{ instance_termination_check.stdout | from_json }}"

- assert:
that:
- instance_termination_status.DisableApiTermination.Value == false

- name: Set termination protection to false (idempotent)
ec2_instance:
name: "{{ resource_prefix }}-termination-protection"
image_id: "{{ ec2_ami_image }}"
tags:
TestId: "{{ resource_prefix }}"
termination_protection: false
instance_type: "{{ ec2_instance_type }}"
vpc_subnet_id: "{{ testing_subnet_b.subnet.id }}"
Expand All @@ -126,6 +197,8 @@
ec2_instance:
name: "{{ resource_prefix }}-termination-protection"
image_id: "{{ ec2_ami_image }}"
tags:
TestId: "{{ resource_prefix }}"
termination_protection: true
instance_type: "{{ ec2_instance_type }}"
vpc_subnet_id: "{{ testing_subnet_b.subnet.id }}"
Expand All @@ -141,6 +214,8 @@
ec2_instance:
name: "{{ resource_prefix }}-termination-protection"
image_id: "{{ ec2_ami_image }}"
tags:
TestId: "{{ resource_prefix }}"
termination_protection: true
instance_type: "{{ ec2_instance_type }}"
vpc_subnet_id: "{{ testing_subnet_b.subnet.id }}"
Expand All @@ -155,6 +230,8 @@
ec2_instance:
name: "{{ resource_prefix }}-termination-protection"
image_id: "{{ ec2_ami_image }}"
tags:
TestId: "{{ resource_prefix }}"
termination_protection: false
instance_type: "{{ ec2_instance_type }}"
vpc_subnet_id: "{{ testing_subnet_b.subnet.id }}"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
- include_role:
name: 'setup_remote_tmp_dir'

- set_fact:
virtualenv: "{{ remote_tmp_dir }}/virtualenv"
virtualenv_command: "{{ ansible_python_interpreter }} -m virtualenv"

- set_fact:
virtualenv_interpreter: "{{ virtualenv }}/bin/python"
aws_cli: "{{ virtualenv }}/bin/aws"

- pip:
name: "virtualenv"

- pip:
name:
- awscli<=1.18.159
- botocore<1.19.0,>=1.13.3
- boto3 >= 1.9.250, <= 1.15.18
- coverage<5
virtualenv: "{{ virtualenv }}"
virtualenv_command: "{{ virtualenv_command }}"
virtualenv_site_packages: no

- include_tasks: termination_protection.yml
vars:
ansible_python_interpreter: "{{ virtualenv_interpreter }}"

- file:
state: absent
path: "{{ virtualenv }}"

0 comments on commit b216f8d

Please sign in to comment.