@go-to-k/cdkd 0.17.0 → 0.18.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 +68 -14
- package/dist/cli.js +230 -38
- package/dist/cli.js.map +4 -4
- package/dist/go-to-k-cdkd-0.18.0.tgz +0 -0
- package/dist/index.js +9 -5
- package/dist/index.js.map +2 -2
- package/package.json +1 -1
- package/dist/go-to-k-cdkd-0.17.0.tgz +0 -0
package/README.md
CHANGED
|
@@ -458,10 +458,16 @@ cdkd state resources MyStack --json # full JSON array
|
|
|
458
458
|
cdkd state show MyStack
|
|
459
459
|
cdkd state show MyStack --json # raw {state, lock} JSON
|
|
460
460
|
|
|
461
|
-
#
|
|
462
|
-
|
|
463
|
-
cdkd
|
|
464
|
-
cdkd
|
|
461
|
+
# Orphan a stack from cdkd's state (does NOT delete AWS resources).
|
|
462
|
+
# Synth-driven — needs --app / cdk.json — same stack-pattern routing as deploy.
|
|
463
|
+
cdkd orphan MyStack # confirmation prompt (y/N)
|
|
464
|
+
cdkd orphan MyStack --yes
|
|
465
|
+
cdkd orphan 'MyStage/*' --yes # display-path wildcard
|
|
466
|
+
|
|
467
|
+
# State-driven counterpart (no CDK app needed — works against the bucket).
|
|
468
|
+
cdkd state orphan MyStack # confirmation prompt (y/N)
|
|
469
|
+
cdkd state orphan MyStack --yes # skip confirmation
|
|
470
|
+
cdkd state orphan StackA StackB --force # also bypass the locked-stack refusal
|
|
465
471
|
|
|
466
472
|
# Destroy a stack's AWS resources AND remove its state record, without
|
|
467
473
|
# requiring the CDK app (no synth — works from any working directory).
|
|
@@ -471,10 +477,12 @@ cdkd state destroy --all -y # every stack in the bucket
|
|
|
471
477
|
cdkd state destroy MyStack --region us-east-1
|
|
472
478
|
```
|
|
473
479
|
|
|
474
|
-
>
|
|
475
|
-
> AWS resources
|
|
476
|
-
> the
|
|
477
|
-
>
|
|
480
|
+
> **`destroy` vs `orphan`** (matches aws-cdk-cli's new `cdk orphan`):
|
|
481
|
+
> `destroy` deletes the AWS resources AND the state record. `orphan` deletes
|
|
482
|
+
> ONLY the state record — AWS resources remain intact, just no longer
|
|
483
|
+
> tracked by cdkd. Each has a synth-driven form (`cdkd destroy` / `cdkd
|
|
484
|
+
> orphan`, needs the CDK app) and a state-driven form (`cdkd state destroy`
|
|
485
|
+
> / `cdkd state orphan`, works on the bucket alone).
|
|
478
486
|
|
|
479
487
|
### Concurrency Options
|
|
480
488
|
|
|
@@ -561,14 +569,60 @@ s3://{state-bucket}/
|
|
|
561
569
|
> `env.region` between deploys silently overwrote the prior region's state
|
|
562
570
|
> and `cdkd destroy` ran against the wrong region. cdkd now treats the two
|
|
563
571
|
> regions as independent. Use `cdkd state list` to see both, and
|
|
564
|
-
> `cdkd state
|
|
572
|
+
> `cdkd state orphan <stack> --stack-region <region>` to prune one without
|
|
565
573
|
> touching the other.
|
|
566
574
|
>
|
|
567
|
-
> **Legacy layout migration
|
|
568
|
-
> layout (`version: 1`, flat
|
|
569
|
-
> readable. The next cdkd write
|
|
570
|
-
>
|
|
571
|
-
>
|
|
575
|
+
> **Legacy key-layout migration (within the same bucket):** state files
|
|
576
|
+
> written by cdkd before this layout (`version: 1`, flat
|
|
577
|
+
> `cdkd/{stackName}/state.json`) are still readable. The next cdkd write
|
|
578
|
+
> auto-migrates to the new region-prefixed key
|
|
579
|
+
> (`cdkd/{stackName}/{region}/state.json`) and removes the legacy file —
|
|
580
|
+
> no manual action required. An older cdkd binary reading a `version: 2`
|
|
581
|
+
> file fails with a clear "upgrade cdkd" error rather than silently
|
|
582
|
+
> mishandling it.
|
|
583
|
+
>
|
|
584
|
+
> Note: this only covers the **key layout inside an existing state
|
|
585
|
+
> bucket**. The separate **bucket-name migration** (legacy
|
|
586
|
+
> `cdkd-state-{accountId}-{region}` → new `cdkd-state-{accountId}`)
|
|
587
|
+
> is described below and does NOT auto-migrate.
|
|
588
|
+
|
|
589
|
+
### Bucket migration
|
|
590
|
+
|
|
591
|
+
The default state-bucket name changed in v0.11.0 from the region-suffixed
|
|
592
|
+
`cdkd-state-{accountId}-{region}` to the region-free
|
|
593
|
+
`cdkd-state-{accountId}`. The bucket name is region-free because S3 names
|
|
594
|
+
are globally unique, so teammates with different profile regions all
|
|
595
|
+
converge on the same bucket; the bucket's actual region is auto-detected
|
|
596
|
+
via `GetBucketLocation`.
|
|
597
|
+
|
|
598
|
+
Existing users keep working without doing anything: when only the legacy
|
|
599
|
+
bucket exists, cdkd transparently falls back to it and emits a
|
|
600
|
+
deprecation warning. To stop the warning (and consolidate state into the
|
|
601
|
+
new bucket) run:
|
|
602
|
+
|
|
603
|
+
```bash
|
|
604
|
+
# Per-region: copies all objects from cdkd-state-{accountId}-{region}
|
|
605
|
+
# into cdkd-state-{accountId}. Source bucket is kept by default.
|
|
606
|
+
cdkd state migrate --region us-east-1
|
|
607
|
+
|
|
608
|
+
# Optional: delete the legacy bucket once the copy is verified.
|
|
609
|
+
cdkd state migrate --region us-east-1 --remove-legacy
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
This migration is **account-wide / per-region**, not per-stack — running
|
|
613
|
+
it once per region clears the legacy bucket for that region in one shot.
|
|
614
|
+
For multi-region accounts, run it once per region (each invocation copies
|
|
615
|
+
into the same destination bucket).
|
|
616
|
+
|
|
617
|
+
`cdkd state migrate` refuses to run while any stack has an active
|
|
618
|
+
`lock.json` (an in-flight `cdkd deploy` / `destroy` would race the copy),
|
|
619
|
+
verifies object-count parity between source and destination before any
|
|
620
|
+
source cleanup, and only deletes the legacy bucket when
|
|
621
|
+
`--remove-legacy` is passed.
|
|
622
|
+
|
|
623
|
+
See the [Configuration](#configuration) table below for the full
|
|
624
|
+
precedence rules of the `--state-bucket` flag and its env-var / cdk.json
|
|
625
|
+
fallbacks.
|
|
572
626
|
|
|
573
627
|
### Configuration
|
|
574
628
|
|
package/dist/cli.js
CHANGED
|
@@ -447,7 +447,7 @@ var init_aws_clients = __esm({
|
|
|
447
447
|
});
|
|
448
448
|
|
|
449
449
|
// src/cli/index.ts
|
|
450
|
-
import { Command as
|
|
450
|
+
import { Command as Command13 } from "commander";
|
|
451
451
|
|
|
452
452
|
// src/cli/commands/bootstrap.ts
|
|
453
453
|
import { Command, Option as Option2 } from "commander";
|
|
@@ -3488,7 +3488,7 @@ var S3StateBackend = class {
|
|
|
3488
3488
|
*
|
|
3489
3489
|
* Returns true for either layout: the new region-scoped key, or the legacy
|
|
3490
3490
|
* key when its embedded `region` matches the requested region. This lets
|
|
3491
|
-
* `cdkd state
|
|
3491
|
+
* `cdkd state orphan <stack> --region X` and `cdkd destroy <stack>` see legacy
|
|
3492
3492
|
* state without forcing a write-through migration first.
|
|
3493
3493
|
*/
|
|
3494
3494
|
async stateExists(stackName, region) {
|
|
@@ -7766,13 +7766,15 @@ import {
|
|
|
7766
7766
|
init_aws_clients();
|
|
7767
7767
|
|
|
7768
7768
|
// src/provisioning/resource-name.ts
|
|
7769
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
7769
7770
|
import { createHash } from "node:crypto";
|
|
7770
|
-
var
|
|
7771
|
-
function
|
|
7772
|
-
|
|
7771
|
+
var stackNameStore = new AsyncLocalStorage();
|
|
7772
|
+
function withStackName(stackName, fn) {
|
|
7773
|
+
return stackNameStore.run(stackName, fn);
|
|
7773
7774
|
}
|
|
7774
7775
|
function generateResourceName(name, options) {
|
|
7775
7776
|
const { maxLength, lowercase = false, allowedPattern = /[^a-zA-Z0-9-]/g } = options;
|
|
7777
|
+
const currentStackName = stackNameStore.getStore();
|
|
7776
7778
|
const fullName = currentStackName ? `${currentStackName}-${name}` : name;
|
|
7777
7779
|
let sanitized = lowercase ? fullName.toLowerCase() : fullName;
|
|
7778
7780
|
sanitized = sanitized.replace(allowedPattern, "-");
|
|
@@ -28790,9 +28792,11 @@ var DeployEngine = class {
|
|
|
28790
28792
|
* Deploy a CloudFormation template
|
|
28791
28793
|
*/
|
|
28792
28794
|
async deploy(stackName, template) {
|
|
28795
|
+
return withStackName(stackName, () => this.doDeploy(stackName, template));
|
|
28796
|
+
}
|
|
28797
|
+
async doDeploy(stackName, template) {
|
|
28793
28798
|
const startTime = Date.now();
|
|
28794
28799
|
this.logger.debug(`Starting deployment for stack: ${stackName}`);
|
|
28795
|
-
setCurrentStackName(stackName);
|
|
28796
28800
|
await this.lockManager.acquireLockWithRetry(stackName, this.stackRegion, void 0, "deploy");
|
|
28797
28801
|
const renderer = getLiveRenderer();
|
|
28798
28802
|
renderer.start();
|
|
@@ -30626,7 +30630,7 @@ Preparing to destroy stack: ${stackName}`);
|
|
|
30626
30630
|
} else {
|
|
30627
30631
|
const regions = refs.map((r) => r.region ?? "(legacy)").join(", ");
|
|
30628
30632
|
throw new Error(
|
|
30629
|
-
`Stack '${stackName}' has state in multiple regions: ${regions}. Use 'cdkd state
|
|
30633
|
+
`Stack '${stackName}' has state in multiple regions: ${regions}. Use 'cdkd state orphan ${stackName} --region <region>' to remove cdkd's record for one region, or run destroy from a CDK app whose env.region matches one of them.`
|
|
30630
30634
|
);
|
|
30631
30635
|
}
|
|
30632
30636
|
const stateResult = await stateBackend.getState(stackName, stackTargetRegion);
|
|
@@ -30666,8 +30670,192 @@ function createDestroyCommand() {
|
|
|
30666
30670
|
return cmd;
|
|
30667
30671
|
}
|
|
30668
30672
|
|
|
30673
|
+
// src/cli/commands/orphan.ts
|
|
30674
|
+
import * as readline2 from "node:readline/promises";
|
|
30675
|
+
import { Command as Command7 } from "commander";
|
|
30676
|
+
init_aws_clients();
|
|
30677
|
+
async function orphanCommand(stackArgs, options) {
|
|
30678
|
+
const logger = getLogger();
|
|
30679
|
+
if (options.verbose)
|
|
30680
|
+
logger.setLevel("debug");
|
|
30681
|
+
warnIfDeprecatedRegion(options);
|
|
30682
|
+
const region = options.region || process.env["AWS_REGION"] || "us-east-1";
|
|
30683
|
+
const stateBucket = await resolveStateBucketWithDefault(options.stateBucket, region);
|
|
30684
|
+
logger.info("Starting stack orphan...");
|
|
30685
|
+
logger.debug("Options:", options);
|
|
30686
|
+
if (options.region) {
|
|
30687
|
+
process.env["AWS_REGION"] = options.region;
|
|
30688
|
+
process.env["AWS_DEFAULT_REGION"] = options.region;
|
|
30689
|
+
}
|
|
30690
|
+
const awsClients = new AwsClients({
|
|
30691
|
+
...options.region && { region: options.region },
|
|
30692
|
+
...options.profile && { profile: options.profile }
|
|
30693
|
+
});
|
|
30694
|
+
setAwsClients(awsClients);
|
|
30695
|
+
try {
|
|
30696
|
+
const stateConfig = {
|
|
30697
|
+
bucket: stateBucket,
|
|
30698
|
+
prefix: options.statePrefix
|
|
30699
|
+
};
|
|
30700
|
+
const stateBackend = new S3StateBackend(awsClients.s3, stateConfig, {
|
|
30701
|
+
...options.region && { region: options.region },
|
|
30702
|
+
...options.profile && { profile: options.profile }
|
|
30703
|
+
});
|
|
30704
|
+
await stateBackend.verifyBucketExists();
|
|
30705
|
+
const lockManager = new LockManager(awsClients.s3, stateConfig);
|
|
30706
|
+
const appCmd = options.app || resolveApp();
|
|
30707
|
+
let appStacks = [];
|
|
30708
|
+
if (appCmd) {
|
|
30709
|
+
try {
|
|
30710
|
+
const synthesizer = new Synthesizer();
|
|
30711
|
+
const context = parseContextOptions(options.context);
|
|
30712
|
+
const result = await synthesizer.synthesize({
|
|
30713
|
+
app: appCmd,
|
|
30714
|
+
output: options.output || "cdk.out",
|
|
30715
|
+
...Object.keys(context).length > 0 && { context }
|
|
30716
|
+
});
|
|
30717
|
+
appStacks = result.stacks.map((s) => ({
|
|
30718
|
+
stackName: s.stackName,
|
|
30719
|
+
displayName: s.displayName,
|
|
30720
|
+
...s.region && { region: s.region }
|
|
30721
|
+
}));
|
|
30722
|
+
} catch {
|
|
30723
|
+
logger.debug("Could not synthesize app, falling back to state-based stack list");
|
|
30724
|
+
}
|
|
30725
|
+
}
|
|
30726
|
+
const allStateRefs = await stateBackend.listStacks();
|
|
30727
|
+
let candidateStacks;
|
|
30728
|
+
if (appStacks.length > 0) {
|
|
30729
|
+
const stateNames = new Set(allStateRefs.map((r) => r.stackName));
|
|
30730
|
+
candidateStacks = appStacks.filter((s) => stateNames.has(s.stackName));
|
|
30731
|
+
} else if (stackArgs.length > 0 || options.stack || options.all) {
|
|
30732
|
+
const seen = /* @__PURE__ */ new Set();
|
|
30733
|
+
candidateStacks = [];
|
|
30734
|
+
for (const ref of allStateRefs) {
|
|
30735
|
+
if (seen.has(ref.stackName))
|
|
30736
|
+
continue;
|
|
30737
|
+
seen.add(ref.stackName);
|
|
30738
|
+
candidateStacks.push({ stackName: ref.stackName });
|
|
30739
|
+
}
|
|
30740
|
+
} else {
|
|
30741
|
+
throw new Error(
|
|
30742
|
+
"Could not determine which stacks belong to this app. Specify stack names explicitly, use --all, or ensure --app / cdk.json is configured."
|
|
30743
|
+
);
|
|
30744
|
+
}
|
|
30745
|
+
const stackPatterns = stackArgs.length > 0 ? stackArgs : options.stack ? [options.stack] : [];
|
|
30746
|
+
let stackNames;
|
|
30747
|
+
if (options.all) {
|
|
30748
|
+
stackNames = candidateStacks.map((s) => s.stackName);
|
|
30749
|
+
} else if (stackPatterns.length > 0) {
|
|
30750
|
+
stackNames = matchStacks(candidateStacks, stackPatterns).map((s) => s.stackName);
|
|
30751
|
+
} else if (candidateStacks.length === 1) {
|
|
30752
|
+
stackNames = candidateStacks.map((s) => s.stackName);
|
|
30753
|
+
} else if (candidateStacks.length === 0) {
|
|
30754
|
+
logger.info("No stacks found in state");
|
|
30755
|
+
return;
|
|
30756
|
+
} else {
|
|
30757
|
+
throw new Error(
|
|
30758
|
+
`Multiple stacks found: ${candidateStacks.map(describeStack).join(", ")}. Specify stack name(s) or use --all`
|
|
30759
|
+
);
|
|
30760
|
+
}
|
|
30761
|
+
if (stackNames.length === 0) {
|
|
30762
|
+
logger.info("No matching stacks found in state");
|
|
30763
|
+
return;
|
|
30764
|
+
}
|
|
30765
|
+
logger.info(`Found ${stackNames.length} stack(s) to orphan: ${stackNames.join(", ")}`);
|
|
30766
|
+
const stateRefsByName = /* @__PURE__ */ new Map();
|
|
30767
|
+
for (const ref of allStateRefs) {
|
|
30768
|
+
const arr = stateRefsByName.get(ref.stackName) ?? [];
|
|
30769
|
+
arr.push(ref);
|
|
30770
|
+
stateRefsByName.set(ref.stackName, arr);
|
|
30771
|
+
}
|
|
30772
|
+
const skipConfirmation = options.yes || options.force;
|
|
30773
|
+
for (const stackName of stackNames) {
|
|
30774
|
+
const refs = stateRefsByName.get(stackName) ?? [];
|
|
30775
|
+
if (refs.length === 0) {
|
|
30776
|
+
logger.info(`No state found for stack: ${stackName}, skipping`);
|
|
30777
|
+
continue;
|
|
30778
|
+
}
|
|
30779
|
+
const targets = options.stackRegion ? refs.filter((r) => r.region === options.stackRegion) : refs;
|
|
30780
|
+
if (targets.length === 0) {
|
|
30781
|
+
const seen = refs.map((r) => r.region ?? "(legacy)").join(", ");
|
|
30782
|
+
throw new Error(
|
|
30783
|
+
`No state found for stack '${stackName}' in region '${options.stackRegion}'. Available regions: ${seen}.`
|
|
30784
|
+
);
|
|
30785
|
+
}
|
|
30786
|
+
if (!options.force) {
|
|
30787
|
+
for (const target of targets) {
|
|
30788
|
+
const locked = await lockManager.isLocked(stackName, target.region);
|
|
30789
|
+
if (locked) {
|
|
30790
|
+
const where = target.region ?? "(legacy)";
|
|
30791
|
+
throw new Error(
|
|
30792
|
+
`Stack '${stackName}' (${where}) is locked. Run 'cdkd force-unlock ${stackName}${target.region ? ` --stack-region ${target.region}` : ""}' first, or pass --force to orphan anyway.`
|
|
30793
|
+
);
|
|
30794
|
+
}
|
|
30795
|
+
}
|
|
30796
|
+
}
|
|
30797
|
+
if (!skipConfirmation) {
|
|
30798
|
+
const targetList = targets.map((t) => t.region ? `${stackName} (${t.region})` : stackName).join(", ");
|
|
30799
|
+
process.stdout.write(
|
|
30800
|
+
`
|
|
30801
|
+
WARNING: This removes cdkd's state record for [${targetList}] only. AWS resources will NOT be deleted.
|
|
30802
|
+
Use 'cdkd destroy ${stackName}' if you want to delete the actual resources.
|
|
30803
|
+
|
|
30804
|
+
`
|
|
30805
|
+
);
|
|
30806
|
+
const rl = readline2.createInterface({
|
|
30807
|
+
input: process.stdin,
|
|
30808
|
+
output: process.stdout
|
|
30809
|
+
});
|
|
30810
|
+
const answer = await rl.question(
|
|
30811
|
+
`Orphan state for ${targetList} from s3://${stateBucket}/${options.statePrefix}/? (y/N): `
|
|
30812
|
+
);
|
|
30813
|
+
rl.close();
|
|
30814
|
+
const trimmed = answer.trim().toLowerCase();
|
|
30815
|
+
if (trimmed !== "y" && trimmed !== "yes") {
|
|
30816
|
+
logger.info(`Cancelled orphan of stack: ${stackName}`);
|
|
30817
|
+
continue;
|
|
30818
|
+
}
|
|
30819
|
+
}
|
|
30820
|
+
for (const target of targets) {
|
|
30821
|
+
if (target.region) {
|
|
30822
|
+
await stateBackend.deleteState(stackName, target.region);
|
|
30823
|
+
await lockManager.forceReleaseLock(stackName, target.region);
|
|
30824
|
+
} else {
|
|
30825
|
+
await lockManager.forceReleaseLock(stackName, void 0);
|
|
30826
|
+
}
|
|
30827
|
+
const label = target.region ? `${stackName} (${target.region})` : stackName;
|
|
30828
|
+
logger.info(`\u2713 Orphaned state for stack: ${label}`);
|
|
30829
|
+
}
|
|
30830
|
+
}
|
|
30831
|
+
} finally {
|
|
30832
|
+
awsClients.destroy();
|
|
30833
|
+
}
|
|
30834
|
+
}
|
|
30835
|
+
function createOrphanCommand() {
|
|
30836
|
+
const cmd = new Command7("orphan").description(
|
|
30837
|
+
"Remove cdkd's state record for one or more stacks (does NOT delete AWS resources). Synth-driven; for the CDK-app-free version use 'cdkd state orphan'."
|
|
30838
|
+
).argument(
|
|
30839
|
+
"[stacks...]",
|
|
30840
|
+
"Stack name(s) to orphan. Accepts physical CloudFormation names (e.g. 'MyStage-Api') or CDK display paths (e.g. 'MyStage/Api'). Supports wildcards (e.g. 'MyStage/*')."
|
|
30841
|
+
).option("--all", "Orphan all stacks in the current app", false).option(
|
|
30842
|
+
"--stack-region <region>",
|
|
30843
|
+
"Region of the stack record to operate on. Required when the same stack name has state in multiple regions."
|
|
30844
|
+
).action(withErrorHandling(orphanCommand));
|
|
30845
|
+
[
|
|
30846
|
+
...commonOptions,
|
|
30847
|
+
...appOptions,
|
|
30848
|
+
...stateOptions,
|
|
30849
|
+
...stackOptions,
|
|
30850
|
+
...destroyOptions,
|
|
30851
|
+
...contextOptions
|
|
30852
|
+
].forEach((opt) => cmd.addOption(opt));
|
|
30853
|
+
cmd.addOption(deprecatedRegionOption);
|
|
30854
|
+
return cmd;
|
|
30855
|
+
}
|
|
30856
|
+
|
|
30669
30857
|
// src/cli/commands/publish-assets.ts
|
|
30670
|
-
import { Option as Option3, Command as
|
|
30858
|
+
import { Option as Option3, Command as Command8 } from "commander";
|
|
30671
30859
|
async function publishAssetsCommand(options) {
|
|
30672
30860
|
const logger = getLogger();
|
|
30673
30861
|
if (options.verbose) {
|
|
@@ -30686,7 +30874,7 @@ async function publishAssetsCommand(options) {
|
|
|
30686
30874
|
logger.info("\u2705 Asset publishing complete");
|
|
30687
30875
|
}
|
|
30688
30876
|
function createPublishAssetsCommand() {
|
|
30689
|
-
const cmd = new
|
|
30877
|
+
const cmd = new Command8("publish-assets").description("Publish assets to S3/ECR from asset manifest").requiredOption("--path <path>", "Path to asset manifest file or directory").addOption(
|
|
30690
30878
|
new Option3(
|
|
30691
30879
|
"--asset-publish-concurrency <number>",
|
|
30692
30880
|
"Maximum concurrent asset publish operations"
|
|
@@ -30700,7 +30888,7 @@ function createPublishAssetsCommand() {
|
|
|
30700
30888
|
}
|
|
30701
30889
|
|
|
30702
30890
|
// src/cli/commands/force-unlock.ts
|
|
30703
|
-
import { Command as
|
|
30891
|
+
import { Command as Command9, Option as Option4 } from "commander";
|
|
30704
30892
|
init_aws_clients();
|
|
30705
30893
|
async function forceUnlockCommand(stackArgs, options) {
|
|
30706
30894
|
const logger = getLogger();
|
|
@@ -30760,7 +30948,7 @@ async function forceUnlockCommand(stackArgs, options) {
|
|
|
30760
30948
|
}
|
|
30761
30949
|
}
|
|
30762
30950
|
function createForceUnlockCommand() {
|
|
30763
|
-
const cmd = new
|
|
30951
|
+
const cmd = new Command9("force-unlock").description("Force-release a stale lock on a stack").argument("[stacks...]", "Stack name(s) to unlock").addOption(
|
|
30764
30952
|
new Option4(
|
|
30765
30953
|
"--stack-region <region>",
|
|
30766
30954
|
"Stack region whose lock to release (use when the same stack name has locks in multiple regions). Defaults to all regions where the stack has state."
|
|
@@ -30772,8 +30960,8 @@ function createForceUnlockCommand() {
|
|
|
30772
30960
|
}
|
|
30773
30961
|
|
|
30774
30962
|
// src/cli/commands/state.ts
|
|
30775
|
-
import * as
|
|
30776
|
-
import { Command as
|
|
30963
|
+
import * as readline4 from "node:readline/promises";
|
|
30964
|
+
import { Command as Command11, Option as Option5 } from "commander";
|
|
30777
30965
|
import {
|
|
30778
30966
|
GetBucketLocationCommand as GetBucketLocationCommand2,
|
|
30779
30967
|
GetObjectCommand as GetObjectCommand4,
|
|
@@ -30782,8 +30970,8 @@ import {
|
|
|
30782
30970
|
init_aws_clients();
|
|
30783
30971
|
|
|
30784
30972
|
// src/cli/commands/state-migrate.ts
|
|
30785
|
-
import * as
|
|
30786
|
-
import { Command as
|
|
30973
|
+
import * as readline3 from "node:readline/promises";
|
|
30974
|
+
import { Command as Command10 } from "commander";
|
|
30787
30975
|
import {
|
|
30788
30976
|
CopyObjectCommand,
|
|
30789
30977
|
CreateBucketCommand as CreateBucketCommand4,
|
|
@@ -31057,7 +31245,7 @@ async function emptyBucketAllVersions(s3, bucket) {
|
|
|
31057
31245
|
} while (keyMarker || versionIdMarker);
|
|
31058
31246
|
}
|
|
31059
31247
|
async function confirmPrompt(prompt) {
|
|
31060
|
-
const rl =
|
|
31248
|
+
const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
|
|
31061
31249
|
try {
|
|
31062
31250
|
const ans = await rl.question(`${prompt} [y/N] `);
|
|
31063
31251
|
return /^y(es)?$/i.test(ans.trim());
|
|
@@ -31066,7 +31254,7 @@ async function confirmPrompt(prompt) {
|
|
|
31066
31254
|
}
|
|
31067
31255
|
}
|
|
31068
31256
|
function createStateMigrateCommand() {
|
|
31069
|
-
const cmd = new
|
|
31257
|
+
const cmd = new Command10("migrate").description(
|
|
31070
31258
|
"Migrate state from the legacy region-suffixed bucket (cdkd-state-{account}-{region}) to the new region-free default (cdkd-state-{account}). Source bucket is kept by default; pass --remove-legacy to delete it after a successful migration."
|
|
31071
31259
|
).option(
|
|
31072
31260
|
"--region <region>",
|
|
@@ -31224,7 +31412,7 @@ async function stateListCommand(options) {
|
|
|
31224
31412
|
}
|
|
31225
31413
|
}
|
|
31226
31414
|
function createStateListCommand() {
|
|
31227
|
-
const cmd = new
|
|
31415
|
+
const cmd = new Command11("list").alias("ls").description("List stacks registered in the cdkd state bucket").option("-l, --long", "Show resource count, last-modified time, and lock status", false).option("--json", "Output as JSON", false).action(withErrorHandling(stateListCommand));
|
|
31228
31416
|
[...commonOptions, ...stateOptions].forEach((opt) => cmd.addOption(opt));
|
|
31229
31417
|
cmd.addOption(deprecatedRegionOption);
|
|
31230
31418
|
return cmd;
|
|
@@ -31328,7 +31516,7 @@ function formatLockSummary(lockInfo) {
|
|
|
31328
31516
|
return `locked by ${lockInfo.owner}${opStr}, ${expiresStr}`;
|
|
31329
31517
|
}
|
|
31330
31518
|
function createStateResourcesCommand() {
|
|
31331
|
-
const cmd = new
|
|
31519
|
+
const cmd = new Command11("resources").description("List resources recorded in a stack's state").argument("<stack>", "Stack name (physical CloudFormation name)").option("-l, --long", "Include dependencies and attributes per resource", false).option("--json", "Output as JSON", false).addOption(stackRegionOption()).action(withErrorHandling(stateResourcesCommand));
|
|
31332
31520
|
[...commonOptions, ...stateOptions].forEach((opt) => cmd.addOption(opt));
|
|
31333
31521
|
cmd.addOption(deprecatedRegionOption);
|
|
31334
31522
|
return cmd;
|
|
@@ -31416,17 +31604,17 @@ async function stateShowCommand(stackName, options) {
|
|
|
31416
31604
|
}
|
|
31417
31605
|
}
|
|
31418
31606
|
function createStateShowCommand() {
|
|
31419
|
-
const cmd = new
|
|
31607
|
+
const cmd = new Command11("show").description("Show the full cdkd state record for a stack (metadata, outputs, resources)").argument("<stack>", "Stack name (physical CloudFormation name)").option("--json", "Output the raw state and lock as JSON", false).addOption(stackRegionOption()).action(withErrorHandling(stateShowCommand));
|
|
31420
31608
|
[...commonOptions, ...stateOptions].forEach((opt) => cmd.addOption(opt));
|
|
31421
31609
|
cmd.addOption(deprecatedRegionOption);
|
|
31422
31610
|
return cmd;
|
|
31423
31611
|
}
|
|
31424
|
-
async function
|
|
31612
|
+
async function stateOrphanCommand(stackArgs, options) {
|
|
31425
31613
|
const logger = getLogger();
|
|
31426
31614
|
if (options.verbose)
|
|
31427
31615
|
logger.setLevel("debug");
|
|
31428
31616
|
if (stackArgs.length === 0) {
|
|
31429
|
-
throw new Error("Stack name is required. Usage: cdkd state
|
|
31617
|
+
throw new Error("Stack name is required. Usage: cdkd state orphan <stack> [<stack>...]");
|
|
31430
31618
|
}
|
|
31431
31619
|
const setup = await setupStateBackend(options);
|
|
31432
31620
|
try {
|
|
@@ -31464,7 +31652,7 @@ Use 'cdkd destroy ${stackName}' if you want to delete the actual resources.
|
|
|
31464
31652
|
|
|
31465
31653
|
`
|
|
31466
31654
|
);
|
|
31467
|
-
const rl =
|
|
31655
|
+
const rl = readline4.createInterface({
|
|
31468
31656
|
input: process.stdin,
|
|
31469
31657
|
output: process.stdout
|
|
31470
31658
|
});
|
|
@@ -31498,8 +31686,10 @@ function stackRegionOption() {
|
|
|
31498
31686
|
"Region of the stack record to operate on. Required when the same stack name has state in multiple regions."
|
|
31499
31687
|
);
|
|
31500
31688
|
}
|
|
31501
|
-
function
|
|
31502
|
-
const cmd = new
|
|
31689
|
+
function createStateOrphanCommand() {
|
|
31690
|
+
const cmd = new Command11("orphan").description(
|
|
31691
|
+
"Orphan one or more stacks from cdkd state (removes the state record; does NOT delete AWS resources)"
|
|
31692
|
+
).argument("<stacks...>", "Stack name(s) to orphan from state").option("-f, --force", "Skip confirmation and remove even if the stack is locked", false).addOption(stackRegionOption()).action(withErrorHandling(stateOrphanCommand));
|
|
31503
31693
|
[...commonOptions, ...stateOptions].forEach((opt) => cmd.addOption(opt));
|
|
31504
31694
|
cmd.addOption(deprecatedRegionOption);
|
|
31505
31695
|
return cmd;
|
|
@@ -31549,7 +31739,7 @@ WARNING: This destroys ${stackNames.length} stack(s) and removes their state rec
|
|
|
31549
31739
|
`);
|
|
31550
31740
|
}
|
|
31551
31741
|
process.stdout.write("\n");
|
|
31552
|
-
const rl =
|
|
31742
|
+
const rl = readline4.createInterface({
|
|
31553
31743
|
input: process.stdin,
|
|
31554
31744
|
output: process.stdout
|
|
31555
31745
|
});
|
|
@@ -31624,8 +31814,8 @@ Preparing to destroy stack: ${stackName}${ref.region ? ` (${ref.region})` : ""}`
|
|
|
31624
31814
|
}
|
|
31625
31815
|
}
|
|
31626
31816
|
function createStateDestroyCommand() {
|
|
31627
|
-
const cmd = new
|
|
31628
|
-
"Destroy a stack's AWS resources and remove its state record without requiring the CDK app. For removing only the state record (keeping AWS resources intact), use 'cdkd state
|
|
31817
|
+
const cmd = new Command11("destroy").description(
|
|
31818
|
+
"Destroy a stack's AWS resources and remove its state record without requiring the CDK app. For removing only the state record (keeping AWS resources intact), use 'cdkd state orphan'."
|
|
31629
31819
|
).argument("[stacks...]", "Stack name(s) to destroy (physical CloudFormation names)").option("--all", "Destroy every stack in the state bucket", false).addOption(stackRegionOption()).addHelpText(
|
|
31630
31820
|
"after",
|
|
31631
31821
|
[
|
|
@@ -31637,7 +31827,7 @@ function createStateDestroyCommand() {
|
|
|
31637
31827
|
" cdkd state destroy MyStack --state-bucket cdkd-state-test",
|
|
31638
31828
|
" cdkd state destroy MyStack --stack-region us-west-2",
|
|
31639
31829
|
"",
|
|
31640
|
-
"For removing only the state record (keeping AWS resources intact), use 'cdkd state
|
|
31830
|
+
"For removing only the state record (keeping AWS resources intact), use 'cdkd state orphan'."
|
|
31641
31831
|
].join("\n")
|
|
31642
31832
|
).action(withErrorHandling(stateDestroyCommand));
|
|
31643
31833
|
[...commonOptions, ...stateOptions].forEach((opt) => cmd.addOption(opt));
|
|
@@ -31756,19 +31946,19 @@ async function stateInfoCommand(options) {
|
|
|
31756
31946
|
}
|
|
31757
31947
|
}
|
|
31758
31948
|
function createStateInfoCommand() {
|
|
31759
|
-
const cmd = new
|
|
31949
|
+
const cmd = new Command11("info").description(
|
|
31760
31950
|
"Show cdkd state bucket info (bucket name, region, source, schema version, stack count)"
|
|
31761
31951
|
).option("--json", "Output as JSON", false).action(withErrorHandling(stateInfoCommand));
|
|
31762
31952
|
[...commonOptions, ...stateOptions].forEach((opt) => cmd.addOption(opt));
|
|
31763
31953
|
return cmd;
|
|
31764
31954
|
}
|
|
31765
31955
|
function createStateCommand() {
|
|
31766
|
-
const cmd = new
|
|
31956
|
+
const cmd = new Command11("state").description("Manage cdkd state stored in S3");
|
|
31767
31957
|
cmd.addCommand(createStateInfoCommand());
|
|
31768
31958
|
cmd.addCommand(createStateListCommand());
|
|
31769
31959
|
cmd.addCommand(createStateResourcesCommand());
|
|
31770
31960
|
cmd.addCommand(createStateShowCommand());
|
|
31771
|
-
cmd.addCommand(
|
|
31961
|
+
cmd.addCommand(createStateOrphanCommand());
|
|
31772
31962
|
cmd.addCommand(createStateDestroyCommand());
|
|
31773
31963
|
cmd.addCommand(createStateMigrateCommand());
|
|
31774
31964
|
return cmd;
|
|
@@ -31776,8 +31966,8 @@ function createStateCommand() {
|
|
|
31776
31966
|
|
|
31777
31967
|
// src/cli/commands/import.ts
|
|
31778
31968
|
import { readFileSync as readFileSync5 } from "node:fs";
|
|
31779
|
-
import * as
|
|
31780
|
-
import { Command as
|
|
31969
|
+
import * as readline5 from "node:readline/promises";
|
|
31970
|
+
import { Command as Command12 } from "commander";
|
|
31781
31971
|
init_aws_clients();
|
|
31782
31972
|
async function importCommand(stackArg, options) {
|
|
31783
31973
|
const logger = getLogger();
|
|
@@ -32073,7 +32263,7 @@ function formatOutcome(outcome) {
|
|
|
32073
32263
|
}
|
|
32074
32264
|
}
|
|
32075
32265
|
async function confirmPrompt2(prompt) {
|
|
32076
|
-
const rl =
|
|
32266
|
+
const rl = readline5.createInterface({ input: process.stdin, output: process.stdout });
|
|
32077
32267
|
try {
|
|
32078
32268
|
const ans = await rl.question(`${prompt} [y/N] `);
|
|
32079
32269
|
return /^y(es)?$/i.test(ans.trim());
|
|
@@ -32082,7 +32272,7 @@ async function confirmPrompt2(prompt) {
|
|
|
32082
32272
|
}
|
|
32083
32273
|
}
|
|
32084
32274
|
function createImportCommand() {
|
|
32085
|
-
const cmd = new
|
|
32275
|
+
const cmd = new Command12("import").description(
|
|
32086
32276
|
"Adopt already-deployed AWS resources into cdkd state. Reads the CDK app to find logical IDs, resource types, and dependencies; uses the aws:cdk:path tag (or explicit --resource overrides) to find each resource in AWS."
|
|
32087
32277
|
).argument(
|
|
32088
32278
|
"[stack]",
|
|
@@ -32118,6 +32308,7 @@ var SUBCOMMANDS = /* @__PURE__ */ new Set([
|
|
|
32118
32308
|
"deploy",
|
|
32119
32309
|
"diff",
|
|
32120
32310
|
"destroy",
|
|
32311
|
+
"orphan",
|
|
32121
32312
|
"import",
|
|
32122
32313
|
"publish-assets",
|
|
32123
32314
|
"force-unlock",
|
|
@@ -32134,14 +32325,15 @@ function reorderArgs(argv) {
|
|
|
32134
32325
|
return [...prefix, ...cmdAndAfter, ...beforeCmd];
|
|
32135
32326
|
}
|
|
32136
32327
|
async function main() {
|
|
32137
|
-
const program = new
|
|
32138
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.
|
|
32328
|
+
const program = new Command13();
|
|
32329
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.18.0");
|
|
32139
32330
|
program.addCommand(createBootstrapCommand());
|
|
32140
32331
|
program.addCommand(createSynthCommand());
|
|
32141
32332
|
program.addCommand(createListCommand());
|
|
32142
32333
|
program.addCommand(createDeployCommand());
|
|
32143
32334
|
program.addCommand(createDiffCommand());
|
|
32144
32335
|
program.addCommand(createDestroyCommand());
|
|
32336
|
+
program.addCommand(createOrphanCommand());
|
|
32145
32337
|
program.addCommand(createImportCommand());
|
|
32146
32338
|
program.addCommand(createPublishAssetsCommand());
|
|
32147
32339
|
program.addCommand(createForceUnlockCommand());
|