Skip to content
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
33 changes: 33 additions & 0 deletions src/deployments/cdk/toolkit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ export class CdkToolkit {

async deployStack(stack: CloudFormationStackArtifact): Promise<StackOutput[]> {
const stackExists = await this.cloudFormation.stackExists({ stack });
console.log(`Is ${stack.displayName} stack exists`, stackExists);

const resources = Object.keys(stack.template.Resources || {});
if (resources.length === 0) {
Expand All @@ -166,6 +167,32 @@ export class CdkToolkit {
this.destroyStack(stack);
}
return [];
} else if (stackExists) {
const sdk = await this.props.sdkProvider.forEnvironment(stack.environment, Mode.ForWriting);
const cfn = sdk.cloudFormation();
console.log(`Calling describeStacks API for ${stack.displayName} stack`);
const existingStack = await cfn
.describeStacks({
StackName: stack.id,
})
.promise();
console.log(`Finding status of ${stack.displayName} stack`);
const stackStatus = existingStack.Stacks[0].StackStatus;
console.log(`${stack.displayName} stack status`, stackStatus);
try {
if (stackStatus === 'ROLLBACK_COMPLETE') {
console.log(`Calling updateTerminationProtection API on ${stack.displayName} stack`);
await cfn
.updateTerminationProtection({
StackName: stack.id,
EnableTerminationProtection: false,
})
.promise();
console.log(`Successfully disabled termination protection on ${stack.displayName}`);
}
} catch (e) {
console.warn(`Failed to disable termination protection for ${stack.displayName}: ${e}`);
}
}

try {
Expand All @@ -174,6 +201,7 @@ export class CdkToolkit {
const tags = [...tagsForStack(stack)];
console.log(tags.length);

console.log(`Calling deployStack API on ${stack.displayName} stack`);
const result = await this.cloudFormation.deployStack({
stack,
deployName: stack.stackName,
Expand Down Expand Up @@ -215,25 +243,30 @@ export class CdkToolkit {
* Destroy the given stack. It skips deletion when stack termination is turned on.
*/
private async destroyStack(stack: CloudFormationStackArtifact): Promise<void> {
console.log(`Destroying stack ${stack.displayName}`);
try {
const sdk = await this.props.sdkProvider.forEnvironment(stack.environment, Mode.ForWriting);
const cfn = sdk.cloudFormation();
console.log(`Trying to disable termination protection before destroying ${stack.displayName} stack`);
await cfn
.updateTerminationProtection({
StackName: stack.id,
EnableTerminationProtection: false,
})
.promise();
console.log(`Successfully disabled termination protection on ${stack.displayName} stack`);
} catch (e) {
console.warn(`${stack.displayName}: cannot disable stack termination protection`);
}
try {
console.log(`Calling destroyStack API on ${stack.displayName} stack`);
await this.cloudFormation.destroyStack({
stack,
deployName: stack.stackName,
roleArn: undefined,
force: true,
});
console.log(`Successfully destroyed/deleted the ${stack.displayName} stack`);
} catch (e) {
const errorMessage = `${e}`;
if (errorMessage.includes('it may need to be manually deleted')) {
Expand Down
7 changes: 7 additions & 0 deletions src/lib/custom-resources/runtime-cfn-response/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ export async function send(event: CloudFormationCustomResourceEvent, context: Co
reject(error);
});

request.on('response', response => {
if (response.statusCode! >= 400) {
console.log(`Found status code ${response.statusCode} - retrying: ` + response.statusMessage);
reject(response.statusMessage);
}
});

request.write(responseBody);
request.end();
});
Expand Down