@ -118,6 +118,10 @@ options:
required : false
required : false
default : null
default : null
version_added : " 2.3 "
version_added : " 2.3 "
termination_protection :
description :
- enable or disable termination protection on the stack . Only works with botocore > = 1.7 .18 .
version_added : " 2.5 "
author : " James S. Martin (@jsmartin) "
author : " James S. Martin (@jsmartin) "
extends_documentation_fragment :
extends_documentation_fragment :
@ -173,6 +177,16 @@ EXAMPLES = '''
ClusterSize : 3
ClusterSize : 3
tags :
tags :
Stack : ansible - cloudformation
Stack : ansible - cloudformation
# Enable termination protection on a stack.
# If the stack already exists, this will update its termination protection
- name : enable termination protection during stack creation
cloudformation :
stack_name : my_stack
state : present
template_url : https : / / s3 . amazonaws . com / my - bucket / cloudformation . template
termination_protection : yes
'''
'''
RETURN = '''
RETURN = '''
@ -256,8 +270,14 @@ def create_stack(module, stack_params, cfn):
if ' TemplateBody ' not in stack_params and ' TemplateURL ' not in stack_params :
if ' TemplateBody ' not in stack_params and ' TemplateURL ' not in stack_params :
module . fail_json ( msg = " Either ' template ' or ' template_url ' is required when the stack does not exist. " )
module . fail_json ( msg = " Either ' template ' or ' template_url ' is required when the stack does not exist. " )
# 'disablerollback' only applies on creation, not update.
# 'disablerollback' and 'EnableTerminationProtection' only
# apply on creation, not update.
stack_params [ ' DisableRollback ' ] = module . params [ ' disable_rollback ' ]
stack_params [ ' DisableRollback ' ] = module . params [ ' disable_rollback ' ]
if module . params . get ( ' termination_protection ' ) is not None :
if boto_supports_termination_protection ( cfn ) :
stack_params [ ' EnableTerminationProtection ' ] = bool ( module . params . get ( ' termination_protection ' ) )
else :
module . fail_json ( msg = " termination_protection parameter requires botocore >= 1.7.18 " )
try :
try :
cfn . create_stack ( * * stack_params )
cfn . create_stack ( * * stack_params )
@ -328,6 +348,26 @@ def update_stack(module, stack_params, cfn):
return result
return result
def update_termination_protection ( module , cfn , stack_name , desired_termination_protection_state ) :
''' updates termination protection of a stack '''
if not boto_supports_termination_protection ( cfn ) :
module . fail_json ( msg = " termination_protection parameter requires botocore >= 1.7.18 " )
stack = get_stack_facts ( cfn , stack_name )
if stack :
if stack [ ' EnableTerminationProtection ' ] is not desired_termination_protection_state :
try :
cfn . update_termination_protection (
EnableTerminationProtection = desired_termination_protection_state ,
StackName = stack_name )
except botocore . exceptions . ClientError as e :
module . fail_json ( msg = boto_exception ( e ) , exception = traceback . format_exc ( ) )
def boto_supports_termination_protection ( cfn ) :
''' termination protection was added in botocore 1.7.18 '''
return hasattr ( cfn , " update_termination_protection " )
def stack_operation ( cfn , stack_name , operation ) :
def stack_operation ( cfn , stack_name , operation ) :
''' gets the status of a stack while it is created/updated/deleted '''
''' gets the status of a stack while it is created/updated/deleted '''
existed = [ ]
existed = [ ]
@ -450,7 +490,8 @@ def main():
create_changeset = dict ( default = False , type = ' bool ' ) ,
create_changeset = dict ( default = False , type = ' bool ' ) ,
changeset_name = dict ( default = None , required = False ) ,
changeset_name = dict ( default = None , required = False ) ,
role_arn = dict ( default = None , required = False ) ,
role_arn = dict ( default = None , required = False ) ,
tags = dict ( default = None , type = ' dict ' )
tags = dict ( default = None , type = ' dict ' ) ,
termination_protection = dict ( default = None , type = ' bool ' )
)
)
)
)
@ -511,6 +552,8 @@ def main():
cfn . describe_stacks = backoff_wrapper ( cfn . describe_stacks )
cfn . describe_stacks = backoff_wrapper ( cfn . describe_stacks )
cfn . list_stack_resources = backoff_wrapper ( cfn . list_stack_resources )
cfn . list_stack_resources = backoff_wrapper ( cfn . list_stack_resources )
cfn . delete_stack = backoff_wrapper ( cfn . delete_stack )
cfn . delete_stack = backoff_wrapper ( cfn . delete_stack )
if boto_supports_termination_protection ( cfn ) :
cfn . update_termination_protection = backoff_wrapper ( cfn . update_termination_protection )
stack_info = get_stack_facts ( cfn , stack_params [ ' StackName ' ] )
stack_info = get_stack_facts ( cfn , stack_params [ ' StackName ' ] )
@ -530,6 +573,9 @@ def main():
elif module . params . get ( ' create_changeset ' ) :
elif module . params . get ( ' create_changeset ' ) :
result = create_changeset ( module , stack_params , cfn )
result = create_changeset ( module , stack_params , cfn )
else :
else :
if module . params . get ( ' termination_protection ' ) is not None :
update_termination_protection ( module , cfn , stack_params [ ' StackName ' ] ,
bool ( module . params . get ( ' termination_protection ' ) ) )
result = update_stack ( module , stack_params , cfn )
result = update_stack ( module , stack_params , cfn )
# format the stack output
# format the stack output