Skip to content

Commit c84666c

Browse files
authored
feat(core): new RemovalPolicy.RETAIN_EXCEPT_ON_CREATE to only retain resources that have been successfully created (#26602)
Adds support for the RetainExceptOnCreate DeletionPolicy. When `applyToUpdateReplacePolicy` is set, this uses the 'Retain' UpdateReplacePolicy. https://aws.amazon.com/about-aws/whats-new/2023/07/aws-cloudformation-deletion-policies-dev-test-cycle/ https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html#aws-attribute-deletionpolicy-options Closes #26570 Replaces #26595 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 300989a commit c84666c

File tree

4 files changed

+81
-1
lines changed

4 files changed

+81
-1
lines changed

packages/aws-cdk-lib/core/lib/cfn-resource-policy.ts

+8
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,14 @@ export enum CfnDeletionPolicy {
9191
*/
9292
RETAIN = 'Retain',
9393

94+
/**
95+
* RetainExceptOnCreate behaves like Retain for stack operations, except for the stack operation that initially created the resource.
96+
* If the stack operation that created the resource is rolled back, CloudFormation deletes the resource. For all other stack operations,
97+
* such as stack deletion, CloudFormation retains the resource and its contents. The result is that new, empty, and unused resources are deleted,
98+
* while in-use resources and their data are retained.
99+
*/
100+
RETAIN_EXCEPT_ON_CREATE = 'RetainExceptOnCreate',
101+
94102
/**
95103
* For resources that support snapshots (AWS::EC2::Volume, AWS::ElastiCache::CacheCluster, AWS::ElastiCache::ReplicationGroup,
96104
* AWS::RDS::DBInstance, AWS::RDS::DBCluster, and AWS::Redshift::Cluster), AWS CloudFormation creates a snapshot for the

packages/aws-cdk-lib/core/lib/cfn-resource.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -120,14 +120,22 @@ export class CfnResource extends CfnRefElement {
120120
policy = policy || options.default || RemovalPolicy.RETAIN;
121121

122122
let deletionPolicy;
123+
let updateReplacePolicy;
123124

124125
switch (policy) {
125126
case RemovalPolicy.DESTROY:
126127
deletionPolicy = CfnDeletionPolicy.DELETE;
128+
updateReplacePolicy = CfnDeletionPolicy.DELETE;
127129
break;
128130

129131
case RemovalPolicy.RETAIN:
130132
deletionPolicy = CfnDeletionPolicy.RETAIN;
133+
updateReplacePolicy = CfnDeletionPolicy.RETAIN;
134+
break;
135+
136+
case RemovalPolicy.RETAIN_ON_UPDATE_OR_DELETE:
137+
deletionPolicy = CfnDeletionPolicy.RETAIN_EXCEPT_ON_CREATE;
138+
updateReplacePolicy = CfnDeletionPolicy.RETAIN;
131139
break;
132140

133141
case RemovalPolicy.SNAPSHOT:
@@ -153,6 +161,7 @@ export class CfnResource extends CfnRefElement {
153161
}
154162

155163
deletionPolicy = CfnDeletionPolicy.SNAPSHOT;
164+
updateReplacePolicy = CfnDeletionPolicy.SNAPSHOT;
156165
break;
157166

158167
default:
@@ -161,7 +170,7 @@ export class CfnResource extends CfnRefElement {
161170

162171
this.cfnOptions.deletionPolicy = deletionPolicy;
163172
if (options.applyToUpdateReplacePolicy !== false) {
164-
this.cfnOptions.updateReplacePolicy = deletionPolicy;
173+
this.cfnOptions.updateReplacePolicy = updateReplacePolicy;
165174
}
166175
}
167176

packages/aws-cdk-lib/core/lib/removal-policy.ts

+15
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,21 @@ export enum RemovalPolicy {
4848
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html#aws-attribute-deletionpolicy-options
4949
*/
5050
SNAPSHOT = 'snapshot',
51+
52+
/**
53+
* Resource will be retained when they are requested to be deleted during a stack delete request
54+
* or need to be replaced due to a stack update request.
55+
* Resource are not retained, if the creation is rolled back.
56+
*
57+
* The result is that new, empty, and unused resources are deleted,
58+
* while in-use resources and their data are retained.
59+
*
60+
* This uses the 'RetainExceptOnCreate' DeletionPolicy,
61+
* and the 'Retain' UpdateReplacePolicy, when `applyToUpdateReplacePolicy` is set.
62+
*
63+
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html#aws-attribute-deletionpolicy-options
64+
*/
65+
RETAIN_ON_UPDATE_OR_DELETE = 'retain-on-update-or-delete',
5166
}
5267

5368
export interface RemovalPolicyOptions {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { toCloudFormation } from './util';
2+
import { CfnResource, Stack, RemovalPolicy } from '../lib';
3+
4+
describe('removal policy', () => {
5+
test.each([
6+
[RemovalPolicy.RETAIN, 'Retain'],
7+
[RemovalPolicy.DESTROY, 'Delete'],
8+
[RemovalPolicy.SNAPSHOT, 'Snapshot'],
9+
[RemovalPolicy.RETAIN_ON_UPDATE_OR_DELETE, 'RetainExceptOnCreate'],
10+
])('should set correct DeletionPolicy for RemovalPolicy.%s', (removalPolicy: RemovalPolicy, deletionPolicy: string) => {
11+
const stack = new Stack();
12+
13+
const resource = new CfnResource(stack, 'Resource', { type: 'MOCK' });
14+
resource.applyRemovalPolicy(removalPolicy);
15+
16+
expect(toCloudFormation(stack)).toEqual({
17+
Resources: {
18+
Resource: expect.objectContaining({
19+
Type: 'MOCK',
20+
DeletionPolicy: deletionPolicy,
21+
}),
22+
},
23+
});
24+
});
25+
26+
test.each([
27+
[RemovalPolicy.RETAIN, 'Retain'],
28+
[RemovalPolicy.DESTROY, 'Delete'],
29+
[RemovalPolicy.SNAPSHOT, 'Snapshot'],
30+
[RemovalPolicy.RETAIN_ON_UPDATE_OR_DELETE, 'Retain'],
31+
])('should set correct UpdateReplacePolicy for RemovalPolicy.%s', (removalPolicy: RemovalPolicy, updateReplacePolicy: string) => {
32+
const stack = new Stack();
33+
34+
const resource = new CfnResource(stack, 'Resource', { type: 'MOCK' });
35+
resource.applyRemovalPolicy(removalPolicy, {
36+
applyToUpdateReplacePolicy: true,
37+
});
38+
39+
expect(toCloudFormation(stack)).toEqual({
40+
Resources: {
41+
Resource: expect.objectContaining({
42+
Type: 'MOCK',
43+
UpdateReplacePolicy: updateReplacePolicy,
44+
}),
45+
},
46+
});
47+
});
48+
});

0 commit comments

Comments
 (0)