Skip to content

Instantly share code, notes, and snippets.

@foriequal0
Last active March 7, 2024 05:05
Show Gist options
  • Save foriequal0/f1f4ea279fb64836e5fb38efefa133d7 to your computer and use it in GitHub Desktop.
Save foriequal0/f1f4ea279fb64836e5fb38efefa133d7 to your computer and use it in GitHub Desktop.
CDK StableNameStack
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;
}
@eladb
Copy link

eladb commented Dec 6, 2020

Got it, so what I would recommend is overriding Stack.allocateLogicalId.

@foriequal0
Copy link
Author

Thanks 👍

@acomagu
Copy link

acomagu commented Mar 15, 2022

I'll share my modification:

     if (typeof lookup === 'string') {
       if (lookup.startsWith('@')) {
         // path prefix rewrite
-        const path = lookup.slice(1).split("/");
+        const path = lookup.slice(1).split("/").filter(s => !!s);
         return makeUniqueId([...path, ...rest]);
       }
       return lookup;

to handle configuration like:

{
  "context": {
    "pinnedLogicalIds": {
      "Stack/A": "@"
    }
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment