@@ -16,9 +16,10 @@ func (a *action) cleanCfStacks(ctx context.Context, input *CleanupScope) error {
1616 for _ , stack := range page .Stacks {
1717 var ignore , markedForDeletion bool
1818 for _ , tag := range stack .Tags {
19- if * tag .Key == input .IgnoreTag {
19+ switch * tag .Key {
20+ case input .IgnoreTag :
2021 ignore = true
21- } else if * tag . Key == DeletionTag {
22+ case DeletionTag :
2223 markedForDeletion = true
2324 }
2425 }
@@ -29,6 +30,12 @@ func (a *action) cleanCfStacks(ctx context.Context, input *CleanupScope) error {
2930 }
3031
3132 if ! markedForDeletion {
33+ if ! a .canUpdateStack (aws .StringValue (stack .StackStatus )) {
34+ LogDebug ("cloudformation stack %s is in state %s and cannot be updated, skipping" ,
35+ * stack .StackName , aws .StringValue (stack .StackStatus ))
36+ continue
37+ }
38+
3239 // NOTE: only mark for future deletion if we're not running in dry-mode
3340 if a .commit {
3441 LogDebug ("cloudformation stack %s does not have deletion tag, marking for future deletion and skipping cleanup" , * stack .StackName )
@@ -44,6 +51,10 @@ func (a *action) cleanCfStacks(ctx context.Context, input *CleanupScope) error {
4451 cf .ResourceStatusDeleteInProgress :
4552 LogDebug ("cloudformation stack %s is already deleted/deleting, skipping cleanup" , * stack .StackName )
4653 continue
54+ case cf .StackStatusDeleteFailed :
55+ LogDebug ("cloudformation stack %s is in DELETE_FAILED state, adding to delete list" , * stack .StackName )
56+ stacksToDelete = append (stacksToDelete , stack .StackName )
57+ continue
4758 }
4859
4960 LogDebug ("adding cloudformation stack %s to delete list" , * stack .StackName )
@@ -102,8 +113,27 @@ func (a *action) markCfStackForFutureDeletion(ctx context.Context, stack *cf.Sta
102113func (a * action ) deleteCfStack (ctx context.Context , stackName string , client * cf.CloudFormation ) error {
103114 Log ("Deleting CloudFormation stack %s" , stackName )
104115
105- if _ , err := client .DeleteStackWithContext (ctx , & cf.DeleteStackInput {StackName : & stackName }); err != nil {
106- return fmt .Errorf ("failed to delete cloudformation stack %s: %w" , stackName , err )
116+ stacks , err := client .DescribeStacksWithContext (ctx , & cf.DescribeStacksInput {StackName : & stackName })
117+ if err != nil {
118+ return fmt .Errorf ("failed to describe cloudformation stack %s: %w" , stackName , err )
119+ }
120+
121+ if len (stacks .Stacks ) > 0 {
122+ stackStatus := aws .StringValue (stacks .Stacks [0 ].StackStatus )
123+ if stackStatus == cf .StackStatusDeleteFailed {
124+ Log ("Stack %s is in DELETE_FAILED state, attempting to continue deletion" , stackName )
125+
126+ if _ , err := client .DeleteStackWithContext (ctx , & cf.DeleteStackInput {
127+ StackName : & stackName ,
128+ RetainResources : []* string {},
129+ }); err != nil {
130+ return fmt .Errorf ("failed to continue deletion of cloudformation stack %s: %w" , stackName , err )
131+ }
132+ } else {
133+ if _ , err := client .DeleteStackWithContext (ctx , & cf.DeleteStackInput {StackName : & stackName }); err != nil {
134+ return fmt .Errorf ("failed to delete cloudformation stack %s: %w" , stackName , err )
135+ }
136+ }
107137 }
108138
109139 if err := client .WaitUntilStackDeleteCompleteWithContext (ctx , & cf.DescribeStacksInput {StackName : & stackName }); err != nil {
@@ -112,3 +142,23 @@ func (a *action) deleteCfStack(ctx context.Context, stackName string, client *cf
112142
113143 return nil
114144}
145+
146+ func (a * action ) canUpdateStack (stackStatus string ) bool {
147+ nonUpdatableStates := []string {
148+ cf .StackStatusCreateInProgress ,
149+ cf .StackStatusDeleteInProgress ,
150+ cf .StackStatusDeleteFailed ,
151+ cf .StackStatusDeleteComplete ,
152+ cf .StackStatusUpdateInProgress ,
153+ cf .StackStatusUpdateRollbackInProgress ,
154+ cf .StackStatusUpdateRollbackCompleteCleanupInProgress ,
155+ cf .StackStatusReviewInProgress ,
156+ }
157+
158+ for _ , state := range nonUpdatableStates {
159+ if stackStatus == state {
160+ return false
161+ }
162+ }
163+ return true
164+ }
0 commit comments