Skip to content

Commit 2af8309

Browse files
authored
fix(aws-cdk): Auto-delete stacks that failed creating before new attempt (#917)
Restore the previous behavior around stacks that failed creation, detecting the condition and automatically deleting the stack before making a new attempt. The stack is not deleted after the failure in order to allow for forensics to be performed. Also, deleting the stack on the next creation attempt is more robust.
1 parent f2b1048 commit 2af8309

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

packages/aws-cdk/lib/api/deploy-stack.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { prepareAssets } from '../assets';
77
import { debug, error } from '../logging';
88
import { Mode } from './aws-auth/credentials';
99
import { ToolkitInfo } from './toolkit-info';
10-
import { describeStack, stackExists, waitForChangeSet, waitForStack } from './util/cloudformation';
10+
import { describeStack, stackExists, stackFailedCreating, waitForChangeSet, waitForStack } from './util/cloudformation';
1111
import { StackActivityMonitor } from './util/cloudformation/stack-activity-monitor';
1212
import { StackStatus } from './util/cloudformation/stack-status';
1313
import { SDK } from './util/sdk';
@@ -43,6 +43,15 @@ export async function deployStack(stack: cxapi.SynthesizedStack,
4343
const cfn = await sdk.cloudFormation(stack.environment, Mode.ForWriting);
4444
const bodyParameter = await makeBodyParameter(stack, toolkitInfo);
4545

46+
if (await stackFailedCreating(cfn, deployName)) {
47+
debug(`Found existing stack ${deployName} that had previously failed creation. Deleting it before attempting to re-create it.`);
48+
await cfn.deleteStack({ StackName: deployName }).promise();
49+
const deletedStack = await waitForStack(cfn, deployName, false);
50+
if (deletedStack && deletedStack.StackStatus !== 'DELETE_COMPLETE') {
51+
throw new Error(`Failed deleting stack ${deployName} that had previously failed creation (current state: ${deletedStack.StackStatus})`);
52+
}
53+
}
54+
4655
const update = await stackExists(cfn, deployName);
4756

4857
const changeSetName = `CDK-${executionId}`;

packages/aws-cdk/lib/api/util/cloudformation.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,20 @@ export async function stackExists(cfn: CloudFormation, stackName: string): Promi
4949
return description !== undefined;
5050
}
5151

52+
/**
53+
* Checks whether a stack has failed creation in CloudFormation. This is identified by the current stack Status being
54+
* ``ROLLBACK_COMPLETE``.
55+
*
56+
* @param cfn a CloudFormation client
57+
* @param stackName the name of the stack to be checked for
58+
*
59+
* @returns +true+ if the stack exists and is in failed-creation state.
60+
*/
61+
export async function stackFailedCreating(cfn: CloudFormation, stackName: string): Promise<boolean> {
62+
const description = await describeStack(cfn, stackName);
63+
return description != null && description.StackStatus === 'ROLLBACK_COMPLETE';
64+
}
65+
5266
/**
5367
* Waits for a function to return non-+undefined+ before returning.
5468
*

0 commit comments

Comments
 (0)