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

[PR #1681/46e9dd4a backport][stable-6] cloudformation: add support for DisableRollback to upadte stack #1727

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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_changes:
- cloudformation - Add support for ``disable_rollback`` to update stack operation (https://github.com/ansible-collections/amazon.aws/issues/1681).
4 changes: 3 additions & 1 deletion plugins/modules/cloudformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ def create_stack(module, stack_params, cfn, events_limit):
msg="Either 'template', 'template_body' or 'template_url' is required when the stack does not exist."
)

# 'DisableRollback', 'TimeoutInMinutes', 'EnableTerminationProtection' and
# 'TimeoutInMinutes', 'EnableTerminationProtection' and
# 'OnFailure' only apply on creation, not update.
if module.params.get("on_create_failure") is not None:
stack_params["OnFailure"] = module.params["on_create_failure"]
Expand Down Expand Up @@ -483,6 +483,8 @@ def update_stack(module, stack_params, cfn, events_limit):
if module.params["stack_policy_on_update_body"] is not None:
stack_params["StackPolicyDuringUpdateBody"] = module.params["stack_policy_on_update_body"]

stack_params["DisableRollback"] = module.params["disable_rollback"]

# if the state is present and the stack already exists, we try to update it.
# AWS will tell us if the stack template and parameters are the same and
# don't need to be updated.
Expand Down
2 changes: 2 additions & 0 deletions tests/integration/targets/cloudformation/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
stack_name: "{{ resource_prefix }}"
stack_name_disable_rollback_true: "{{ resource_prefix }}-drb-true"
stack_name_disable_rollback_false: "{{ resource_prefix }}-drb-false"

availability_zone: '{{ ec2_availability_zone_names[0] }}'

Expand Down
4 changes: 4 additions & 0 deletions tests/integration/targets/cloudformation/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
az: "{{ availability_zone }}"
register: testing_subnet

# ==== Cloudformation tests with disable_rollback ====================

- import_tasks: test_disable_rollback.yml

# ==== Cloudformation tests ===============================================

# 1. Basic stack creation (check mode, actual run and idempotency)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
---
- name: Run cloudformation tests for `disable_rollback` parameter
block:

# disable rollback to true
- name: create a cloudformation stack (disable_rollback=true) (check mode)
amazon.aws.cloudformation:
stack_name: "{{ stack_name_disable_rollback_true }}"
state: present
disable_rollback: true
template_body: "{{ lookup('file','cf_template.json') }}"
template_parameters:
InstanceType: "t3.nano"
ImageId: "{{ ec2_ami_id }}"
SubnetId: "{{ testing_subnet.subnet.id }}"
register: cf_stack
check_mode: yes

- name: check task return attributes
assert:
that:
- cf_stack.changed
- "'msg' in cf_stack and 'New stack would be created' in cf_stack.msg"

- name: create a cloudformation stack (disable_rollback=true)
amazon.aws.cloudformation:
stack_name: "{{ stack_name_disable_rollback_true }}"
state: present
disable_rollback: true
template_body: "{{ lookup('file','cf_template.json') }}"
template_parameters:
InstanceType: "t3.nano"
ImageId: "{{ ec2_ami_id }}"
SubnetId: "{{ testing_subnet.subnet.id }}"
register: cf_stack

- name: get stack details
cloudformation_info:
stack_name: "{{ stack_name_disable_rollback_true }}"
register: stack_info

- name: assert stack info
assert:
that:
- "'cloudformation' in stack_info"
- stack_info.cloudformation | length == 1
- stack_info.cloudformation[stack_name_disable_rollback_true].stack_description.disable_rollback == true

# disable rollback to false
- name: create a cloudformation stack (disable_rollback=false) (check mode)
amazon.aws.cloudformation:
stack_name: "{{ stack_name_disable_rollback_false }}"
state: present
disable_rollback: false
template_body: "{{ lookup('file','cf_template.json') }}"
template_parameters:
InstanceType: "t3.nano"
ImageId: "{{ ec2_ami_id }}"
SubnetId: "{{ testing_subnet.subnet.id }}"
register: cf_stack
check_mode: yes

- name: check task return attributes
assert:
that:
- cf_stack.changed
- "'msg' in cf_stack and 'New stack would be created' in cf_stack.msg"

- name: create a cloudformation stack (disable_rollback=false)
amazon.aws.cloudformation:
stack_name: "{{ stack_name_disable_rollback_false }}"
state: present
disable_rollback: false
template_body: "{{ lookup('file','cf_template.json') }}"
template_parameters:
InstanceType: "t3.nano"
ImageId: "{{ ec2_ami_id }}"
SubnetId: "{{ testing_subnet.subnet.id }}"
register: cf_stack

- name: get stack details
cloudformation_info:
stack_name: "{{ stack_name_disable_rollback_false }}"
register: stack_info

- name: assert stack info
assert:
that:
- "'cloudformation' in stack_info"
- "stack_info.cloudformation | length == 1"
- "stack_info.cloudformation[stack_name_disable_rollback_false].stack_description.disable_rollback == false"

# disable rollback not set
- name: create a cloudformation stack (disable_rollback not set) (check mode)
amazon.aws.cloudformation:
stack_name: "{{ stack_name }}"
state: present
template_body: "{{ lookup('file','cf_template.json') }}"
template_parameters:
InstanceType: "t3.nano"
ImageId: "{{ ec2_ami_id }}"
SubnetId: "{{ testing_subnet.subnet.id }}"
register: cf_stack
check_mode: yes

- name: check task return attributes
assert:
that:
- cf_stack.changed
- "'msg' in cf_stack and 'New stack would be created' in cf_stack.msg"

- name: create a cloudformation stack (disable_rollback not set)
amazon.aws.cloudformation:
stack_name: "{{ stack_name }}"
state: present
template_body: "{{ lookup('file','cf_template.json') }}"
template_parameters:
InstanceType: "t3.nano"
ImageId: "{{ ec2_ami_id }}"
SubnetId: "{{ testing_subnet.subnet.id }}"
register: cf_stack

- name: get stack details
cloudformation_info:
stack_name: "{{ stack_name }}"
register: stack_info

- name: assert stack info
assert:
that:
- "'cloudformation' in stack_info"
- "stack_info.cloudformation | length == 1"
- "stack_info.cloudformation[stack_name].stack_description.disable_rollback == false"

# =============================================================================================
# Test Scenario
# 1. create a cloudformation stack
# 2. try update, FAILED by providing wrong ami id (disable_rollback=true, do not delete failed stack)
# 3. Fix the ami id, retry update, fails as disable_rollback=False
# 4. Try (3) with disable_rollback=true, update completes
# =============================================================================================

- name: Create a cloudformation stack
amazon.aws.cloudformation:
stack_name: "{{ stack_name }}-failtest"
state: present
template_body: "{{ lookup('file','cf_template.json') }}"
disable_rollback: false
template_parameters:
InstanceType: "t3.nano"
ImageId: "{{ ec2_ami_id }}"
SubnetId: "{{ testing_subnet.subnet.id }}"
register: cf_stack
ignore_errors: true

- name: Update the cloudformation stack with wrong ami (fails, does not delete failed as disable_rollback=true)
amazon.aws.cloudformation:
stack_name: "{{ stack_name }}-failtest"
state: present
template_body: "{{ lookup('file','cf_template.json') }}"
disable_rollback: true
template_parameters:
InstanceType: "t3.nano"
ImageId: "{{ ec2_ami_id }}1" # wrong ami provided
SubnetId: "{{ testing_subnet.subnet.id }}"
register: cf_stack
ignore_errors: true

# update stack by correcting AMI ID
- name: Fix the AMI ID and retry updating the cloudformation stack (fails with disable_rollback=false)
amazon.aws.cloudformation:
stack_name: "{{ stack_name }}-failtest"
state: present
template_body: "{{ lookup('file','cf_template.json') }}"
disable_rollback: false
template_parameters:
InstanceType: "t3.nano"
ImageId: "{{ ec2_ami_id }}"
SubnetId: "{{ testing_subnet.subnet.id }}"
register: cf_stack
ignore_errors: true

- name: Fix the AMI ID and retry updating the cloudformation stack (passes with disable_rollback=true)
amazon.aws.cloudformation:
stack_name: "{{ stack_name }}-failtest"
state: present
template_body: "{{ lookup('file','cf_template.json') }}"
disable_rollback: true
template_parameters:
InstanceType: "t3.nano"
ImageId: "{{ ec2_ami_id }}"
SubnetId: "{{ testing_subnet.subnet.id }}"
register: cf_stack

- name: get stack details
cloudformation_info:
stack_name: "{{ stack_name }}-failtest"
register: stack_info

- name: Assert that update was successful
assert:
that:
- cf_stack.changed
- cf_stack.output == "Stack UPDATE complete"
- stack_info.cloudformation["{{ stack_name }}-failtest"].stack_description.stack_status == "UPDATE_COMPLETE"

always:

- name: delete stack
cloudformation:
stack_name: "{{ item }}"
state: absent
ignore_errors: true
with_items:
- "{{ stack_name_disable_rollback_true }}"
- "{{ stack_name_disable_rollback_false }}"
- "{{ stack_name }}-failtest"
- "{{ stack_name }}"
Loading