Skip to content

Commit

Permalink
feat: Add support for RemovalPolicy in config (#306)
Browse files Browse the repository at this point in the history
* Support Removal Policy

* fix condition

* fixing type
  • Loading branch information
malachi-constant committed Apr 17, 2023
1 parent 98bd743 commit 8799d19
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 2 deletions.
23 changes: 21 additions & 2 deletions src/config/configurator.ts
Expand Up @@ -34,6 +34,17 @@ function readConfigFile(path: string): object {
throw TypeError("Config file must be in YAML or JSON format");
}
}
function setRemovalPolicy(value: string, node: cdk.CfnResource): void {
if (value.toLowerCase() == "destroy") {
node.applyRemovalPolicy(cdk.RemovalPolicy.DESTROY);
} else if (value.toLowerCase() == "retain") {
node.applyRemovalPolicy(cdk.RemovalPolicy.RETAIN);
} else if (value.toLowerCase() == "snapshot") {
node.applyRemovalPolicy(cdk.RemovalPolicy.SNAPSHOT);
} else {
throw new Error(`${value} is not a valid removal policy type. Must be one of ['DESTROY', 'RETAIN', & 'SNAPSHOT']`);
}
}
interface getConfigProps {
readonly config?: string | object;
}
Expand Down Expand Up @@ -125,13 +136,21 @@ class ConfiguratorAspect implements cdk.IAspect {
}
public visit(node: constructs.IConstruct): void {
if (this.resourceType && cdk.CfnResource.isCfnResource(node) && node.cfnResourceType == this.resourceType) {
node.addPropertyOverride(this.propertyName, this.propertyValue);
if (this.propertyName == "RemovalPolicy") {
setRemovalPolicy(this.propertyValue, node);
} else {
node.addPropertyOverride(this.propertyName, this.propertyValue);
}
}

const nodePathItemRegex = new RegExp(`^(.*\/)?(${this.resourceId}\/Resource)(\/.*)?$`);

if (this.resourceId && cdk.CfnResource.isCfnResource(node) && nodePathItemRegex.test(node.node.path)) {
node.addPropertyOverride(this.propertyName, this.propertyValue);
if (this.propertyName == "RemovalPolicy") {
setRemovalPolicy(this.propertyValue, node);
} else {
node.addPropertyOverride(this.propertyName, this.propertyValue);
}
}
}
}
Expand Down
61 changes: 61 additions & 0 deletions test/config.test.ts
Expand Up @@ -497,3 +497,64 @@ test("Get Tags", () => {
assert(prodTags.CostCenter === "2015");
assert(globalTags["global:foo"] === "bar");
});

test("Config Removal Policy", () => {
const sampleConfig = {
environments: {
dev: {
resources: {
MyBucket: {
RemovalPolicy: cdk.RemovalPolicy.DESTROY,
},
MyOtherBucket: {
RemovalPolicy: cdk.RemovalPolicy.RETAIN,
},
},
},
},
};
const stack = new cdk.Stack();
new s3.Bucket(stack, "MyBucket");
new s3.Bucket(stack, "MyOtherBucket");
new Configurator(stack, sampleConfig, "dev");
const template = Template.fromStack(stack);
template.hasResource("AWS::S3::Bucket", {
DeletionPolicy: "Delete",
UpdateReplacePolicy: "Delete",
});
template.hasResource("AWS::S3::Bucket", {
DeletionPolicy: "Retain",
UpdateReplacePolicy: "Retain",
});
});

test("Config Removal Policy Invalid", () => {
const sampleConfig = {
environments: {
dev: {
resources: {
MyBucket: {
RemovalPolicy: "foobar",
},
},
},
},
};
const stack = new cdk.Stack();
new s3.Bucket(stack, "MyBucket");
new Configurator(stack, sampleConfig, "dev");
expect(() => {
Template.fromStack(stack);
}).toThrowError("foobar is not a valid removal policy type. Must be one of ['DESTROY', 'RETAIN', & 'SNAPSHOT']");
});

test("Config Removal Policy JSON Config", () => {
const stack = new cdk.Stack();
new s3.Bucket(stack, "MyBucket");
new Configurator(stack, "./test/test-config.json", "dev");
const template = Template.fromStack(stack);
template.hasResource("AWS::S3::Bucket", {
DeletionPolicy: "Delete",
UpdateReplacePolicy: "Delete",
});
});
3 changes: 3 additions & 0 deletions test/test-config.json
Expand Up @@ -12,6 +12,9 @@
"AWS::Lambda::Function": {
"MemorySize": 128,
"Runtime": "python3.8"
},
"AWS::S3::Bucket": {
"RemovalPolicy": "DESTROY"
}
},
"tags": {"CostCenter": "2014"}
Expand Down

0 comments on commit 8799d19

Please sign in to comment.