@go-to-k/cdkd 0.12.0 → 0.13.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 +7 -0
- package/dist/cli.js +138 -9
- package/dist/cli.js.map +3 -3
- package/dist/go-to-k-cdkd-0.13.0.tgz +0 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/go-to-k-cdkd-0.12.0.tgz +0 -0
package/README.md
CHANGED
|
@@ -428,6 +428,13 @@ cdkd destroy --all --force
|
|
|
428
428
|
# Force-unlock a stale lock from interrupted deploy
|
|
429
429
|
cdkd force-unlock MyStack
|
|
430
430
|
|
|
431
|
+
# Inspect state-bucket info on demand (bucket name, region, source, schema version, stack count).
|
|
432
|
+
# Routine commands (deploy / destroy / etc.) no longer print the bucket banner by default —
|
|
433
|
+
# pass --verbose to surface it in their debug logs, or use this subcommand for an explicit answer.
|
|
434
|
+
cdkd state info
|
|
435
|
+
cdkd state info --json # JSON output for tooling
|
|
436
|
+
cdkd state info --state-bucket my-bucket # explicit bucket; reports Source: --state-bucket flag
|
|
437
|
+
|
|
431
438
|
# List stacks registered in the cdkd state bucket
|
|
432
439
|
cdkd state list
|
|
433
440
|
cdkd state ls --long # include resource count, last-modified, lock status
|
package/dist/cli.js
CHANGED
|
@@ -970,16 +970,18 @@ function resolveApp(cliApp) {
|
|
|
970
970
|
const cdkJson = loadCdkJson();
|
|
971
971
|
return cdkJson?.app ?? void 0;
|
|
972
972
|
}
|
|
973
|
-
function
|
|
973
|
+
function resolveStateBucketWithSource(cliBucket) {
|
|
974
974
|
if (cliBucket)
|
|
975
|
-
return cliBucket;
|
|
975
|
+
return { bucket: cliBucket, source: "cli-flag" };
|
|
976
976
|
const envBucket = process.env["CDKD_STATE_BUCKET"];
|
|
977
977
|
if (envBucket)
|
|
978
|
-
return envBucket;
|
|
978
|
+
return { bucket: envBucket, source: "env" };
|
|
979
979
|
const cdkJson = loadCdkJson();
|
|
980
980
|
const cdkdContext = cdkJson?.context?.["cdkd"];
|
|
981
981
|
const bucket = cdkdContext?.["stateBucket"];
|
|
982
|
-
|
|
982
|
+
if (typeof bucket === "string")
|
|
983
|
+
return { bucket, source: "cdk.json" };
|
|
984
|
+
return void 0;
|
|
983
985
|
}
|
|
984
986
|
function getDefaultStateBucketName(accountId) {
|
|
985
987
|
return `cdkd-state-${accountId}`;
|
|
@@ -988,7 +990,10 @@ function getLegacyStateBucketName(accountId, region) {
|
|
|
988
990
|
return `cdkd-state-${accountId}-${region}`;
|
|
989
991
|
}
|
|
990
992
|
async function resolveStateBucketWithDefault(cliBucket, region) {
|
|
991
|
-
|
|
993
|
+
return (await resolveStateBucketWithDefaultAndSource(cliBucket, region)).bucket;
|
|
994
|
+
}
|
|
995
|
+
async function resolveStateBucketWithDefaultAndSource(cliBucket, region) {
|
|
996
|
+
const syncResult = resolveStateBucketWithSource(cliBucket);
|
|
992
997
|
if (syncResult)
|
|
993
998
|
return syncResult;
|
|
994
999
|
const logger = getLogger();
|
|
@@ -1004,14 +1009,14 @@ async function resolveStateBucketWithDefault(cliBucket, region) {
|
|
|
1004
1009
|
const probe = new S3Client10({ region: "us-east-1" });
|
|
1005
1010
|
try {
|
|
1006
1011
|
if (await bucketExists(probe, newName)) {
|
|
1007
|
-
logger.
|
|
1008
|
-
return newName;
|
|
1012
|
+
logger.debug(`State bucket: ${newName}`);
|
|
1013
|
+
return { bucket: newName, source: "default" };
|
|
1009
1014
|
}
|
|
1010
1015
|
if (await bucketExists(probe, legacyName)) {
|
|
1011
1016
|
logger.warn(
|
|
1012
1017
|
`Using legacy state bucket name '${legacyName}'. The default has changed to '${newName}'. Future cdkd versions will drop legacy support; consider migrating with cdkd state migrate-bucket (coming in a future release).`
|
|
1013
1018
|
);
|
|
1014
|
-
return legacyName;
|
|
1019
|
+
return { bucket: legacyName, source: "default-legacy" };
|
|
1015
1020
|
}
|
|
1016
1021
|
throw new Error(
|
|
1017
1022
|
`No cdkd state bucket found for account ${accountId}. Looked for '${newName}' (current default) and '${legacyName}' (legacy default). Run 'cdkd bootstrap' to create '${newName}'.`
|
|
@@ -29548,6 +29553,11 @@ function createForceUnlockCommand() {
|
|
|
29548
29553
|
// src/cli/commands/state.ts
|
|
29549
29554
|
import * as readline2 from "node:readline/promises";
|
|
29550
29555
|
import { Command as Command9, Option as Option5 } from "commander";
|
|
29556
|
+
import {
|
|
29557
|
+
GetBucketLocationCommand as GetBucketLocationCommand2,
|
|
29558
|
+
GetObjectCommand as GetObjectCommand4,
|
|
29559
|
+
ListObjectsV2Command as ListObjectsV2Command3
|
|
29560
|
+
} from "@aws-sdk/client-s3";
|
|
29551
29561
|
init_aws_clients();
|
|
29552
29562
|
function formatStackRef(ref) {
|
|
29553
29563
|
return ref.region ? `${ref.stackName} (${ref.region})` : ref.stackName;
|
|
@@ -30106,8 +30116,127 @@ function createStateDestroyCommand() {
|
|
|
30106
30116
|
cmd.addOption(deprecatedRegionOption);
|
|
30107
30117
|
return cmd;
|
|
30108
30118
|
}
|
|
30119
|
+
function formatBucketSource(source) {
|
|
30120
|
+
switch (source) {
|
|
30121
|
+
case "cli-flag":
|
|
30122
|
+
return "--state-bucket flag";
|
|
30123
|
+
case "env":
|
|
30124
|
+
return "CDKD_STATE_BUCKET env";
|
|
30125
|
+
case "cdk.json":
|
|
30126
|
+
return "cdk.json (context.cdkd.stateBucket)";
|
|
30127
|
+
case "default":
|
|
30128
|
+
return "default (account ID from STS)";
|
|
30129
|
+
case "default-legacy":
|
|
30130
|
+
return "default (legacy region-suffixed name; cdkd state migrate-bucket recommended)";
|
|
30131
|
+
}
|
|
30132
|
+
}
|
|
30133
|
+
async function detectBucketRegion(awsClients, bucket) {
|
|
30134
|
+
try {
|
|
30135
|
+
const resp = await awsClients.s3.send(new GetBucketLocationCommand2({ Bucket: bucket }));
|
|
30136
|
+
const constraint = resp.LocationConstraint;
|
|
30137
|
+
if (!constraint)
|
|
30138
|
+
return "us-east-1";
|
|
30139
|
+
if (constraint === "EU")
|
|
30140
|
+
return "eu-west-1";
|
|
30141
|
+
return constraint;
|
|
30142
|
+
} catch {
|
|
30143
|
+
return void 0;
|
|
30144
|
+
}
|
|
30145
|
+
}
|
|
30146
|
+
async function listStateFileKeys(awsClients, bucket, prefix) {
|
|
30147
|
+
const keys = [];
|
|
30148
|
+
let continuationToken;
|
|
30149
|
+
const searchPrefix = `${prefix}/`;
|
|
30150
|
+
do {
|
|
30151
|
+
const resp = await awsClients.s3.send(
|
|
30152
|
+
new ListObjectsV2Command3({
|
|
30153
|
+
Bucket: bucket,
|
|
30154
|
+
Prefix: searchPrefix,
|
|
30155
|
+
...continuationToken && { ContinuationToken: continuationToken }
|
|
30156
|
+
})
|
|
30157
|
+
);
|
|
30158
|
+
for (const obj of resp.Contents ?? []) {
|
|
30159
|
+
const key = obj.Key;
|
|
30160
|
+
if (typeof key === "string" && key.endsWith("/state.json")) {
|
|
30161
|
+
keys.push(key);
|
|
30162
|
+
}
|
|
30163
|
+
}
|
|
30164
|
+
continuationToken = resp.NextContinuationToken;
|
|
30165
|
+
} while (continuationToken);
|
|
30166
|
+
return keys;
|
|
30167
|
+
}
|
|
30168
|
+
async function readSchemaVersion(awsClients, bucket, keys) {
|
|
30169
|
+
if (keys.length === 0)
|
|
30170
|
+
return "unknown";
|
|
30171
|
+
try {
|
|
30172
|
+
const resp = await awsClients.s3.send(new GetObjectCommand4({ Bucket: bucket, Key: keys[0] }));
|
|
30173
|
+
if (!resp.Body)
|
|
30174
|
+
return "unknown";
|
|
30175
|
+
const body = await resp.Body.transformToString();
|
|
30176
|
+
const parsed = JSON.parse(body);
|
|
30177
|
+
return typeof parsed.version === "number" ? parsed.version : "unknown";
|
|
30178
|
+
} catch {
|
|
30179
|
+
return "unknown";
|
|
30180
|
+
}
|
|
30181
|
+
}
|
|
30182
|
+
async function stateInfoCommand(options) {
|
|
30183
|
+
const logger = getLogger();
|
|
30184
|
+
if (options.verbose)
|
|
30185
|
+
logger.setLevel("debug");
|
|
30186
|
+
const awsClients = new AwsClients({
|
|
30187
|
+
...options.region && { region: options.region },
|
|
30188
|
+
...options.profile && { profile: options.profile }
|
|
30189
|
+
});
|
|
30190
|
+
setAwsClients(awsClients);
|
|
30191
|
+
try {
|
|
30192
|
+
const region = options.region || process.env["AWS_REGION"] || "us-east-1";
|
|
30193
|
+
const resolved = await resolveStateBucketWithDefaultAndSource(options.stateBucket, region);
|
|
30194
|
+
const bucket = resolved.bucket;
|
|
30195
|
+
const prefix = options.statePrefix;
|
|
30196
|
+
const stateBackend = new S3StateBackend(awsClients.s3, { bucket, prefix });
|
|
30197
|
+
await stateBackend.verifyBucketExists();
|
|
30198
|
+
const detectedRegion = await detectBucketRegion(awsClients, bucket);
|
|
30199
|
+
const stateFileKeys = await listStateFileKeys(awsClients, bucket, prefix);
|
|
30200
|
+
const schemaVersion = await readSchemaVersion(awsClients, bucket, stateFileKeys);
|
|
30201
|
+
if (options.json) {
|
|
30202
|
+
const json = {
|
|
30203
|
+
bucket,
|
|
30204
|
+
region: detectedRegion ?? null,
|
|
30205
|
+
regionSource: detectedRegion ? "auto-detected" : "unknown",
|
|
30206
|
+
bucketSource: resolved.source,
|
|
30207
|
+
schemaVersion,
|
|
30208
|
+
stackCount: stateFileKeys.length
|
|
30209
|
+
};
|
|
30210
|
+
process.stdout.write(`${JSON.stringify(json, null, 2)}
|
|
30211
|
+
`);
|
|
30212
|
+
return;
|
|
30213
|
+
}
|
|
30214
|
+
const lines = [];
|
|
30215
|
+
lines.push(`State bucket: ${bucket}`);
|
|
30216
|
+
if (detectedRegion) {
|
|
30217
|
+
lines.push(`Region: ${detectedRegion} (auto-detected via GetBucketLocation)`);
|
|
30218
|
+
} else {
|
|
30219
|
+
lines.push("Region: unknown (GetBucketLocation failed or denied)");
|
|
30220
|
+
}
|
|
30221
|
+
lines.push(`Source: ${formatBucketSource(resolved.source)}`);
|
|
30222
|
+
lines.push(`Schema version: ${schemaVersion}`);
|
|
30223
|
+
lines.push(`Stacks: ${stateFileKeys.length}`);
|
|
30224
|
+
process.stdout.write(`${lines.join("\n")}
|
|
30225
|
+
`);
|
|
30226
|
+
} finally {
|
|
30227
|
+
awsClients.destroy();
|
|
30228
|
+
}
|
|
30229
|
+
}
|
|
30230
|
+
function createStateInfoCommand() {
|
|
30231
|
+
const cmd = new Command9("info").description(
|
|
30232
|
+
"Show cdkd state bucket info (bucket name, region, source, schema version, stack count)"
|
|
30233
|
+
).option("--json", "Output as JSON", false).action(withErrorHandling(stateInfoCommand));
|
|
30234
|
+
[...commonOptions, ...stateOptions].forEach((opt) => cmd.addOption(opt));
|
|
30235
|
+
return cmd;
|
|
30236
|
+
}
|
|
30109
30237
|
function createStateCommand() {
|
|
30110
30238
|
const cmd = new Command9("state").description("Manage cdkd state stored in S3");
|
|
30239
|
+
cmd.addCommand(createStateInfoCommand());
|
|
30111
30240
|
cmd.addCommand(createStateListCommand());
|
|
30112
30241
|
cmd.addCommand(createStateResourcesCommand());
|
|
30113
30242
|
cmd.addCommand(createStateShowCommand());
|
|
@@ -30141,7 +30270,7 @@ function reorderArgs(argv) {
|
|
|
30141
30270
|
}
|
|
30142
30271
|
async function main() {
|
|
30143
30272
|
const program = new Command10();
|
|
30144
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.
|
|
30273
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.13.0");
|
|
30145
30274
|
program.addCommand(createBootstrapCommand());
|
|
30146
30275
|
program.addCommand(createSynthCommand());
|
|
30147
30276
|
program.addCommand(createListCommand());
|