shoc-frontend-new/infra/cdk/lib/retain-for-terraform-adoption.ts

64 lines
2.1 KiB
TypeScript
Raw Normal View History

import { CfnCondition, CfnDeletionPolicy, CfnResource, IAspect } from "aws-cdk-lib";
import { IConstruct } from "constructs";
const TRANSFERRED_RESOURCE_TYPES = new Set([
"AWS::S3::Bucket",
"AWS::S3::BucketPolicy",
"AWS::CloudFront::Distribution",
"AWS::CloudFront::Function",
"AWS::CloudFront::OriginAccessControl",
"AWS::Route53::RecordSet",
]);
function isTransferredResource(resource: CfnResource): boolean {
if (TRANSFERRED_RESOURCE_TYPES.has(resource.cfnResourceType)) {
return true;
}
if (
resource.cfnResourceType === "Custom::S3AutoDeleteObjects" &&
resource.node.path.includes("/SiteBucket/AutoDeleteObjectsCustomResource")
) {
return true;
}
return (
(resource.cfnResourceType === "AWS::IAM::Role" ||
resource.cfnResourceType === "AWS::IAM::Policy") &&
resource.node.path.includes("/GithubDeployRole")
);
}
/**
* Retains only the resources in the approved Terraform transfer set.
*
* The bucket auto-delete custom resource is intentionally retained while the
* generated provider Lambda, role, log group, and CDK metadata remain excluded.
* When a management condition is supplied, those same resources share it so
* CloudFormation can later relinquish them without deleting them.
*/
export class RetainForTerraformAdoption implements IAspect {
constructor(private readonly manageCondition?: CfnCondition) {}
public visit(node: IConstruct): void {
if (!(node instanceof CfnResource) || !isTransferredResource(node)) {
return;
}
// Keep the L2 bucket's configured DESTROY policy visible to its
// AutoDeleteObjects validator while overriding the emitted CloudFormation
// resource. This preserves the custom resource and retains both together.
if (node.cfnResourceType === "AWS::S3::Bucket") {
node.addOverride("DeletionPolicy", "Retain");
node.addOverride("UpdateReplacePolicy", "Retain");
} else {
node.cfnOptions.deletionPolicy = CfnDeletionPolicy.RETAIN;
node.cfnOptions.updateReplacePolicy = CfnDeletionPolicy.RETAIN;
}
if (this.manageCondition) {
node.cfnOptions.condition = this.manageCondition;
}
}
}