shoc-frontend-new/infra/cdk/lib/retain-for-terraform-adoption.ts
Adam Moussa 82361e14b5
feat(cdk): add Terraform adoption retain mode
retainForTerraformAdoption=true adds the required ManageSiteInfrastructure
parameter, conditions the 13 transferred resources and the S3 auto-delete
custom resource on it, applies Retain policies, pins the live dev origin
ID, attaches the deploy boundary and HcpTerraformWorkspace tag, and
narrows the OIDC subject to StringEquals. Normal synthesis is unchanged;
template tests cover both modes.
2026-09-10 19:15:11 -04:00

63 lines
2.1 KiB
TypeScript

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;
}
}
}