Last active
November 21, 2024 07:59
-
-
Save foriequal0/f1f4ea279fb64836e5fb38efefa133d7 to your computer and use it in GitHub Desktop.
CDK StableNameStack
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { CfnElement, CfnResource, Stack } from "@aws-cdk/core"; | |
import { makeUniqueId } from "@aws-cdk/core/lib/private/uniqueid"; | |
import { Node } from "constructs"; | |
import * as assert from "assert"; | |
const PINNED_RESOURCE_NAMES_CONTEXT_KEY = "pinnedLogicalIds"; | |
type PinnedLogicalIds = { [segment: string]: PinnedLogicalIds | string }; | |
export class StableNameStack extends Stack { | |
protected allocateLogicalId(element: CfnElement): string { | |
const pinnedLogicalIds: PinnedLogicalIds = Node.of(this).tryGetContext(PINNED_RESOURCE_NAMES_CONTEXT_KEY) ?? {}; | |
if (CfnResource.isCfnResource(element)) { | |
const path = element.node.path; | |
const found = find(pinnedLogicalIds, path.split("/"), element); | |
if (found) { | |
return found; | |
} | |
} | |
return super.allocateLogicalId(element); | |
} | |
} | |
function find(pinnedLogicalIds: PinnedLogicalIds, pathSegments: string[], resource: CfnResource): string | undefined { | |
// You can match type with "!AWS::EC2::VPC", or "!EC2::VPC", or "!VPC", if it is not ambiguous | |
const typeSegments = resource.cfnResourceType.split("::"); | |
for (let i = typeSegments.length - 1; i >= 0; i--) { | |
const tails = typeSegments.slice(i).join("::"); | |
const findByType = pinnedLogicalIds[`!${tails}`]; | |
if (findByType !== undefined) { | |
assert(typeof findByType === "string"); | |
return findByType; | |
} | |
} | |
for (let i = pathSegments.length; i > 0; i--) { | |
const prefix = pathSegments.slice(0, i).join("/"); | |
const rest = pathSegments.slice(i); | |
const lookup = pinnedLogicalIds[prefix]; | |
if (typeof lookup === "string") { | |
if (lookup.startsWith("@")) { | |
// path prefix rewrite | |
const path = lookup.slice(1).split("/"); | |
return makeUniqueId([...path, ...rest]); | |
} | |
return lookup; | |
} else if (lookup !== undefined) { | |
const found = find(lookup, rest, resource); | |
if (found) { | |
return found; | |
} | |
} | |
} | |
return undefined; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
CDK v2 version: