@go-to-k/cdkd 0.91.5 → 0.92.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -0
- package/dist/cli.js +73 -19
- package/dist/cli.js.map +2 -2
- package/dist/go-to-k-cdkd-0.92.0.tgz +0 -0
- package/dist/index.js +24 -6
- package/dist/index.js.map +2 -2
- package/package.json +1 -1
- package/dist/go-to-k-cdkd-0.91.5.tgz +0 -0
package/README.md
CHANGED
|
@@ -453,6 +453,47 @@ Two `orphan` variants at different granularities:
|
|
|
453
453
|
Both `cdkd destroy` (synth-driven) and `cdkd state destroy`
|
|
454
454
|
(state-driven, no synth) delete AWS resources + state.
|
|
455
455
|
|
|
456
|
+
## Stack-name prefix on physical names
|
|
457
|
+
|
|
458
|
+
cdkd prepends the **stack name** to physical names you declare in CDK
|
|
459
|
+
code: `new iam.Role(this, 'CRRole', { roleName: 'my-role' })` in stack
|
|
460
|
+
`MyStack` is created in AWS as `MyStack-my-role`. The prefix protects
|
|
461
|
+
cross-stack uniqueness (two stacks declaring `roleName: 'my-role'`
|
|
462
|
+
otherwise collide on a single AWS account). Pre-PR this behavior was
|
|
463
|
+
**inconsistent**: only IAM Role / User / Group / InstanceProfile and
|
|
464
|
+
ELBv2 LoadBalancer / TargetGroup actually got the prefix; Lambda, S3,
|
|
465
|
+
SNS, SQS, DynamoDB, etc. used the user's declared name as-is.
|
|
466
|
+
|
|
467
|
+
`cdkd deploy --no-prefix-user-supplied-names` opts in to skipping
|
|
468
|
+
the prefix on user-declared physical names, making cdkd consistent
|
|
469
|
+
across all resource types. Off by default for backward compatibility.
|
|
470
|
+
|
|
471
|
+
| | Default (no flag) | `--no-prefix-user-supplied-names` |
|
|
472
|
+
| --- | --- | --- |
|
|
473
|
+
| `new iam.Role({ roleName: 'my-role' })` | `MyStack-my-role` | `my-role` |
|
|
474
|
+
| `new s3.Bucket({ bucketName: 'my-bucket' })` | `my-bucket` (already no prefix — Pattern A) | `my-bucket` (unchanged) |
|
|
475
|
+
| `new iam.Role(...)` (no `roleName`) | `MyStack-CRRole-<hash>` (auto-generated, prefix kept for uniqueness) | `MyStack-CRRole-<hash>` (unchanged) |
|
|
476
|
+
|
|
477
|
+
Resolution chain (highest wins): `--no-prefix-user-supplied-names`
|
|
478
|
+
CLI flag → `CDKD_NO_PREFIX_USER_SUPPLIED_NAMES=true` env var →
|
|
479
|
+
`cdk.json` `context.cdkd.noPrefixUserSuppliedNames: true` → default
|
|
480
|
+
`false`.
|
|
481
|
+
|
|
482
|
+
Affects `cdkd deploy` only. Already-deployed stacks deployed under
|
|
483
|
+
the legacy prefixed-name scheme keep working — the flag only controls
|
|
484
|
+
what AWS resource cdkd creates on **future** deploys. Switching the
|
|
485
|
+
flag mid-flight on an existing stack would propose REPLACEMENT on
|
|
486
|
+
every Pattern B resource (the existing AWS resource has the prefixed
|
|
487
|
+
name; the new template intent has the un-prefixed name).
|
|
488
|
+
|
|
489
|
+
Surfaced by [PR #285 `cdkd export`](https://github.com/go-to-k/cdkd/pull/285)
|
|
490
|
+
where the CFn IMPORT changeset's identifier check would fail on a
|
|
491
|
+
synth `RoleName: 'my-role'` vs the AWS-deployed `MyStack-my-role`;
|
|
492
|
+
the export command currently overlays `ResourceIdentifier` onto
|
|
493
|
+
`Properties` to bridge the gap. A future major-version PR will flip
|
|
494
|
+
the default of `--no-prefix-user-supplied-names` to `true`, after
|
|
495
|
+
which the overlay can be dropped.
|
|
496
|
+
|
|
456
497
|
## `--remove-protection`: one-shot bypass for protected resources
|
|
457
498
|
|
|
458
499
|
CDK's `new Stack(app, 'X', { terminationProtection: true })` is honored
|
package/dist/cli.js
CHANGED
|
@@ -17823,10 +17823,23 @@ function withStackName(stackName, fn) {
|
|
|
17823
17823
|
function getCurrentStackName() {
|
|
17824
17824
|
return stackNameStore.getStore();
|
|
17825
17825
|
}
|
|
17826
|
+
var skipPrefixStore = new AsyncLocalStorage();
|
|
17827
|
+
function withSkipPrefix(skip, fn) {
|
|
17828
|
+
return skipPrefixStore.run(skip, fn);
|
|
17829
|
+
}
|
|
17830
|
+
function getCurrentSkipPrefix() {
|
|
17831
|
+
return skipPrefixStore.getStore() ?? false;
|
|
17832
|
+
}
|
|
17826
17833
|
function generateResourceName(name, options) {
|
|
17827
|
-
const {
|
|
17834
|
+
const {
|
|
17835
|
+
maxLength,
|
|
17836
|
+
lowercase = false,
|
|
17837
|
+
allowedPattern = /[^a-zA-Z0-9-]/g,
|
|
17838
|
+
userSupplied = false
|
|
17839
|
+
} = options;
|
|
17828
17840
|
const currentStackName = stackNameStore.getStore();
|
|
17829
|
-
const
|
|
17841
|
+
const shouldPrefix = currentStackName && !(userSupplied && getCurrentSkipPrefix());
|
|
17842
|
+
const fullName = shouldPrefix ? `${currentStackName}-${name}` : name;
|
|
17830
17843
|
let sanitized = lowercase ? fullName.toLowerCase() : fullName;
|
|
17831
17844
|
sanitized = sanitized.replace(allowedPattern, "-");
|
|
17832
17845
|
sanitized = sanitized.replace(/-{2,}/g, "-").replace(/^-+|-+$/g, "");
|
|
@@ -17838,6 +17851,12 @@ function generateResourceName(name, options) {
|
|
|
17838
17851
|
const prefix = sanitized.substring(0, maxPrefixLength).replace(/-+$/, "");
|
|
17839
17852
|
return `${prefix}-${hash}`;
|
|
17840
17853
|
}
|
|
17854
|
+
function generateResourceNameWithFallback(userSuppliedName, logicalId, options) {
|
|
17855
|
+
if (userSuppliedName !== void 0 && userSuppliedName !== "") {
|
|
17856
|
+
return generateResourceName(userSuppliedName, { ...options, userSupplied: true });
|
|
17857
|
+
}
|
|
17858
|
+
return generateResourceName(logicalId, { ...options, userSupplied: false });
|
|
17859
|
+
}
|
|
17841
17860
|
var FALLBACK_NAME_RULES = {
|
|
17842
17861
|
"AWS::S3::Bucket": { nameProperty: "BucketName", options: { maxLength: 63, lowercase: true } },
|
|
17843
17862
|
"AWS::SQS::Queue": { nameProperty: "QueueName", options: { maxLength: 80 } },
|
|
@@ -23368,6 +23387,10 @@ var deployOptions = [
|
|
|
23368
23387
|
"--no-capture-observed-state",
|
|
23369
23388
|
"Skip capturing AWS-current properties after each create/update (adds a fire-and-forget readCurrentState per resource so cdkd drift can compare against the real deploy-time AWS snapshot instead of the template). On by default. Disable when deploy speed matters more than rich drift detection \u2014 falls back to comparing against template properties (the pre-v3 behavior)."
|
|
23370
23389
|
),
|
|
23390
|
+
new Option(
|
|
23391
|
+
"--no-prefix-user-supplied-names",
|
|
23392
|
+
'Do NOT prepend the stack name to physical names the user explicitly supplied in their CDK code (e.g. `new iam.Role(this, "X", { roleName: "my-role" })` \u2192 AWS resource named `my-role` instead of `MyStack-my-role`). Auto-generated-name resources (where the user did not declare a physical name) keep the prefix unchanged. Off by default for backward compatibility; enable via this flag, CDKD_NO_PREFIX_USER_SUPPLIED_NAMES=true, or cdk.json context.cdkd.noPrefixUserSuppliedNames=true. Applies to `cdkd deploy` only.'
|
|
23393
|
+
),
|
|
23371
23394
|
noWaitOption,
|
|
23372
23395
|
aggressiveVpcParallelOption,
|
|
23373
23396
|
new Option(
|
|
@@ -23512,6 +23535,19 @@ function resolveCaptureObservedState(cliValue) {
|
|
|
23512
23535
|
return v;
|
|
23513
23536
|
return true;
|
|
23514
23537
|
}
|
|
23538
|
+
function resolveSkipPrefix(cliValue) {
|
|
23539
|
+
if (cliValue === false)
|
|
23540
|
+
return true;
|
|
23541
|
+
const envValue = process.env["CDKD_NO_PREFIX_USER_SUPPLIED_NAMES"];
|
|
23542
|
+
if (envValue === "true")
|
|
23543
|
+
return true;
|
|
23544
|
+
const cdkJson = loadCdkJson();
|
|
23545
|
+
const cdkdContext = cdkJson?.context?.["cdkd"];
|
|
23546
|
+
const v = cdkdContext?.["noPrefixUserSuppliedNames"];
|
|
23547
|
+
if (typeof v === "boolean" && v === true)
|
|
23548
|
+
return true;
|
|
23549
|
+
return false;
|
|
23550
|
+
}
|
|
23515
23551
|
function resolveStateBucketWithSource(cliBucket) {
|
|
23516
23552
|
if (cliBucket)
|
|
23517
23553
|
return { bucket: cliBucket, source: "cli-flag" };
|
|
@@ -27789,8 +27825,9 @@ var IAMRoleProvider = class {
|
|
|
27789
27825
|
*/
|
|
27790
27826
|
async create(logicalId, resourceType, properties) {
|
|
27791
27827
|
this.logger.debug(`Creating IAM role ${logicalId}`);
|
|
27792
|
-
const roleName =
|
|
27793
|
-
properties["RoleName"]
|
|
27828
|
+
const roleName = generateResourceNameWithFallback(
|
|
27829
|
+
properties["RoleName"],
|
|
27830
|
+
logicalId,
|
|
27794
27831
|
{ maxLength: 64 }
|
|
27795
27832
|
);
|
|
27796
27833
|
const assumeRolePolicyDocument = properties["AssumeRolePolicyDocument"];
|
|
@@ -27882,8 +27919,9 @@ var IAMRoleProvider = class {
|
|
|
27882
27919
|
*/
|
|
27883
27920
|
async update(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
27884
27921
|
this.logger.debug(`Updating IAM role ${logicalId}: ${physicalId}`);
|
|
27885
|
-
const newRoleName =
|
|
27886
|
-
properties["RoleName"]
|
|
27922
|
+
const newRoleName = generateResourceNameWithFallback(
|
|
27923
|
+
properties["RoleName"],
|
|
27924
|
+
logicalId,
|
|
27887
27925
|
{ maxLength: 64 }
|
|
27888
27926
|
);
|
|
27889
27927
|
const newPath = properties["Path"] || "/";
|
|
@@ -29004,8 +29042,9 @@ var IAMInstanceProfileProvider = class {
|
|
|
29004
29042
|
*/
|
|
29005
29043
|
async create(logicalId, resourceType, properties) {
|
|
29006
29044
|
this.logger.debug(`Creating IAM instance profile ${logicalId}`);
|
|
29007
|
-
const instanceProfileName =
|
|
29008
|
-
properties["InstanceProfileName"]
|
|
29045
|
+
const instanceProfileName = generateResourceNameWithFallback(
|
|
29046
|
+
properties["InstanceProfileName"],
|
|
29047
|
+
logicalId,
|
|
29009
29048
|
{ maxLength: 128 }
|
|
29010
29049
|
);
|
|
29011
29050
|
const path3 = properties["Path"] || "/";
|
|
@@ -29399,8 +29438,9 @@ var IAMUserGroupProvider = class {
|
|
|
29399
29438
|
// ─── AWS::IAM::User ──────────────────────────────────────────────
|
|
29400
29439
|
async createUser(logicalId, resourceType, properties) {
|
|
29401
29440
|
this.logger.debug(`Creating IAM user ${logicalId}`);
|
|
29402
|
-
const userName =
|
|
29403
|
-
properties["UserName"]
|
|
29441
|
+
const userName = generateResourceNameWithFallback(
|
|
29442
|
+
properties["UserName"],
|
|
29443
|
+
logicalId,
|
|
29404
29444
|
{ maxLength: 64 }
|
|
29405
29445
|
);
|
|
29406
29446
|
try {
|
|
@@ -29883,8 +29923,9 @@ var IAMUserGroupProvider = class {
|
|
|
29883
29923
|
// ─── AWS::IAM::Group ─────────────────────────────────────────────
|
|
29884
29924
|
async createGroup(logicalId, resourceType, properties) {
|
|
29885
29925
|
this.logger.debug(`Creating IAM group ${logicalId}`);
|
|
29886
|
-
const groupName =
|
|
29887
|
-
properties["GroupName"]
|
|
29926
|
+
const groupName = generateResourceNameWithFallback(
|
|
29927
|
+
properties["GroupName"],
|
|
29928
|
+
logicalId,
|
|
29888
29929
|
{ maxLength: 128 }
|
|
29889
29930
|
);
|
|
29890
29931
|
try {
|
|
@@ -48542,9 +48583,11 @@ var ELBv2Provider = class {
|
|
|
48542
48583
|
this.logger.debug(`Creating LoadBalancer ${logicalId}`);
|
|
48543
48584
|
try {
|
|
48544
48585
|
const tags = this.extractTags(properties);
|
|
48545
|
-
const lbName =
|
|
48546
|
-
|
|
48547
|
-
|
|
48586
|
+
const lbName = generateResourceNameWithFallback(
|
|
48587
|
+
properties["Name"],
|
|
48588
|
+
logicalId,
|
|
48589
|
+
{ maxLength: 32 }
|
|
48590
|
+
);
|
|
48548
48591
|
const response = await this.getClient().send(
|
|
48549
48592
|
new CreateLoadBalancerCommand({
|
|
48550
48593
|
Name: lbName,
|
|
@@ -48743,9 +48786,11 @@ var ELBv2Provider = class {
|
|
|
48743
48786
|
try {
|
|
48744
48787
|
const tags = this.extractTags(properties);
|
|
48745
48788
|
const matcher = properties["Matcher"];
|
|
48746
|
-
const tgName =
|
|
48747
|
-
|
|
48748
|
-
|
|
48789
|
+
const tgName = generateResourceNameWithFallback(
|
|
48790
|
+
properties["Name"],
|
|
48791
|
+
logicalId,
|
|
48792
|
+
{ maxLength: 32 }
|
|
48793
|
+
);
|
|
48749
48794
|
const response = await this.getClient().send(
|
|
48750
48795
|
new CreateTargetGroupCommand({
|
|
48751
48796
|
Name: tgName,
|
|
@@ -65438,6 +65483,12 @@ async function deployCommand(stacks, options) {
|
|
|
65438
65483
|
if (!options.wait) {
|
|
65439
65484
|
process.env["CDKD_NO_WAIT"] = "true";
|
|
65440
65485
|
}
|
|
65486
|
+
const skipPrefix = resolveSkipPrefix(options.prefixUserSuppliedNames);
|
|
65487
|
+
if (skipPrefix) {
|
|
65488
|
+
logger.debug(
|
|
65489
|
+
"Skipping stack-name prefix on user-supplied physical names (--no-prefix-user-supplied-names / CDKD_NO_PREFIX_USER_SUPPLIED_NAMES / cdk.json context.cdkd.noPrefixUserSuppliedNames)"
|
|
65490
|
+
);
|
|
65491
|
+
}
|
|
65441
65492
|
const app = resolveApp(options.app);
|
|
65442
65493
|
if (!app) {
|
|
65443
65494
|
throw new Error(
|
|
@@ -65597,6 +65648,9 @@ async function deployCommand(stacks, options) {
|
|
|
65597
65648
|
logger.debug(`Work graph: ${summary["asset-publish"]} asset(s), ${summary["stack"]} stack(s)`);
|
|
65598
65649
|
const bufferStackOutput = targetStacks.length > 1;
|
|
65599
65650
|
const runStack = async (stackInfo) => {
|
|
65651
|
+
return withSkipPrefix(skipPrefix, () => runStackInner(stackInfo));
|
|
65652
|
+
};
|
|
65653
|
+
const runStackInner = async (stackInfo) => {
|
|
65600
65654
|
const stackRegion = stackInfo.region || baseRegion;
|
|
65601
65655
|
logger.info(
|
|
65602
65656
|
`
|
|
@@ -80800,7 +80854,7 @@ function reorderArgs(argv) {
|
|
|
80800
80854
|
}
|
|
80801
80855
|
async function main() {
|
|
80802
80856
|
const program = new Command18();
|
|
80803
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.
|
|
80857
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.92.0");
|
|
80804
80858
|
program.addCommand(createBootstrapCommand());
|
|
80805
80859
|
program.addCommand(createSynthCommand());
|
|
80806
80860
|
program.addCommand(createListCommand());
|