@go-to-k/cdkd 0.33.0 → 0.35.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 +6 -1
- package/dist/cli.js +457 -43
- package/dist/cli.js.map +4 -4
- package/dist/go-to-k-cdkd-0.35.0.tgz +0 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +2 -2
- package/package.json +1 -1
- package/dist/go-to-k-cdkd-0.33.0.tgz +0 -0
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 Command14 } from "commander";
|
|
451
451
|
|
|
452
452
|
// src/cli/commands/bootstrap.ts
|
|
453
453
|
import { Command, Option as Option2 } from "commander";
|
|
@@ -477,6 +477,10 @@ function parseContextOptions(contextArgs) {
|
|
|
477
477
|
var commonOptions = [
|
|
478
478
|
new Option("--verbose", "Enable verbose logging").default(false),
|
|
479
479
|
new Option("--profile <profile>", "AWS profile"),
|
|
480
|
+
new Option(
|
|
481
|
+
"--role-arn <arn>",
|
|
482
|
+
"IAM role ARN to assume for AWS API calls (env: CDKD_ROLE_ARN); the role MUST have admin-equivalent permissions because cdkd issues raw service API calls and does not route through CloudFormation, so CDK CLI deploy-roles will NOT work"
|
|
483
|
+
),
|
|
480
484
|
new Option(
|
|
481
485
|
"-y, --yes",
|
|
482
486
|
"Automatically answer interactive prompts with the recommended response (e.g. confirm destroy)"
|
|
@@ -1202,7 +1206,10 @@ Caused by: ${error.cause.message}`;
|
|
|
1202
1206
|
}
|
|
1203
1207
|
function handleError(error) {
|
|
1204
1208
|
const logger = getLogger();
|
|
1205
|
-
|
|
1209
|
+
const silent = error instanceof CdkdError && error.silent;
|
|
1210
|
+
if (!silent) {
|
|
1211
|
+
logger.error(formatError(error));
|
|
1212
|
+
}
|
|
1206
1213
|
if (error instanceof Error && error.stack) {
|
|
1207
1214
|
logger.debug("Stack trace:", error.stack);
|
|
1208
1215
|
}
|
|
@@ -1256,6 +1263,41 @@ function normalizeAwsError(err, context = {}) {
|
|
|
1256
1263
|
// src/cli/commands/bootstrap.ts
|
|
1257
1264
|
init_aws_clients();
|
|
1258
1265
|
|
|
1266
|
+
// src/utils/role-arn.ts
|
|
1267
|
+
import { STSClient as STSClient2, AssumeRoleCommand } from "@aws-sdk/client-sts";
|
|
1268
|
+
async function applyRoleArnIfSet(opts) {
|
|
1269
|
+
const roleArn = opts.roleArn || process.env["CDKD_ROLE_ARN"];
|
|
1270
|
+
if (!roleArn)
|
|
1271
|
+
return;
|
|
1272
|
+
const logger = getLogger().child("role-arn");
|
|
1273
|
+
logger.debug(`Assuming role ${roleArn}...`);
|
|
1274
|
+
const sts = new STSClient2({ ...opts.region && { region: opts.region } });
|
|
1275
|
+
try {
|
|
1276
|
+
const response = await sts.send(
|
|
1277
|
+
new AssumeRoleCommand({
|
|
1278
|
+
RoleArn: roleArn,
|
|
1279
|
+
RoleSessionName: `cdkd-${Date.now()}`,
|
|
1280
|
+
DurationSeconds: 3600
|
|
1281
|
+
})
|
|
1282
|
+
);
|
|
1283
|
+
if (!response.Credentials) {
|
|
1284
|
+
throw new Error(`AssumeRole returned no credentials for role ${roleArn}`);
|
|
1285
|
+
}
|
|
1286
|
+
const { AccessKeyId, SecretAccessKey, SessionToken, Expiration } = response.Credentials;
|
|
1287
|
+
if (!AccessKeyId || !SecretAccessKey || !SessionToken) {
|
|
1288
|
+
throw new Error(`AssumeRole response missing credentials fields for role ${roleArn}`);
|
|
1289
|
+
}
|
|
1290
|
+
process.env["AWS_ACCESS_KEY_ID"] = AccessKeyId;
|
|
1291
|
+
process.env["AWS_SECRET_ACCESS_KEY"] = SecretAccessKey;
|
|
1292
|
+
process.env["AWS_SESSION_TOKEN"] = SessionToken;
|
|
1293
|
+
logger.info(
|
|
1294
|
+
`Assumed role ${roleArn} (session expires ${Expiration?.toISOString() ?? "unknown"})`
|
|
1295
|
+
);
|
|
1296
|
+
} finally {
|
|
1297
|
+
sts.destroy();
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1259
1301
|
// src/cli/config-loader.ts
|
|
1260
1302
|
import { readFileSync, existsSync } from "node:fs";
|
|
1261
1303
|
import { resolve, join } from "node:path";
|
|
@@ -1409,6 +1451,7 @@ async function bootstrapCommand(options) {
|
|
|
1409
1451
|
}
|
|
1410
1452
|
logger.info("Starting cdkd bootstrap...");
|
|
1411
1453
|
logger.debug("Options:", options);
|
|
1454
|
+
await applyRoleArnIfSet({ roleArn: options.roleArn, region: options.region });
|
|
1412
1455
|
const awsClients = new AwsClients({
|
|
1413
1456
|
...options.region && { region: options.region },
|
|
1414
1457
|
...options.profile && { profile: options.profile }
|
|
@@ -1553,7 +1596,7 @@ import { join as join4 } from "path";
|
|
|
1553
1596
|
// src/synthesis/synthesizer.ts
|
|
1554
1597
|
import { existsSync as existsSync3, mkdirSync, statSync } from "node:fs";
|
|
1555
1598
|
import { resolve as resolve3 } from "node:path";
|
|
1556
|
-
import { GetCallerIdentityCommand as GetCallerIdentityCommand2, STSClient as
|
|
1599
|
+
import { GetCallerIdentityCommand as GetCallerIdentityCommand2, STSClient as STSClient3 } from "@aws-sdk/client-sts";
|
|
1557
1600
|
|
|
1558
1601
|
// src/synthesis/app-executor.ts
|
|
1559
1602
|
import { spawn } from "node:child_process";
|
|
@@ -2744,7 +2787,7 @@ var Synthesizer = class {
|
|
|
2744
2787
|
const region = options.region || process.env["AWS_REGION"] || process.env["AWS_DEFAULT_REGION"];
|
|
2745
2788
|
let accountId;
|
|
2746
2789
|
try {
|
|
2747
|
-
const stsClient = new
|
|
2790
|
+
const stsClient = new STSClient3({ ...region && { region } });
|
|
2748
2791
|
const identity = await stsClient.send(new GetCallerIdentityCommand2({}));
|
|
2749
2792
|
accountId = identity.Account;
|
|
2750
2793
|
stsClient.destroy();
|
|
@@ -2876,6 +2919,7 @@ async function synthCommand(options) {
|
|
|
2876
2919
|
logger.setLevel("debug");
|
|
2877
2920
|
}
|
|
2878
2921
|
warnIfDeprecatedRegion(options);
|
|
2922
|
+
await applyRoleArnIfSet({ roleArn: options.roleArn, region: options.region });
|
|
2879
2923
|
const app = resolveApp(options.app);
|
|
2880
2924
|
if (!app) {
|
|
2881
2925
|
throw new Error(
|
|
@@ -3007,6 +3051,7 @@ async function listCommand(patterns, options) {
|
|
|
3007
3051
|
logger.setLevel("debug");
|
|
3008
3052
|
}
|
|
3009
3053
|
warnIfDeprecatedRegion(options);
|
|
3054
|
+
await applyRoleArnIfSet({ roleArn: options.roleArn, region: options.region });
|
|
3010
3055
|
const app = resolveApp(options.app);
|
|
3011
3056
|
if (!app) {
|
|
3012
3057
|
throw new Error(
|
|
@@ -3597,8 +3642,8 @@ var AssetPublisher = class {
|
|
|
3597
3642
|
const region = options.region || process.env["AWS_REGION"] || "us-east-1";
|
|
3598
3643
|
let accountId = options.accountId;
|
|
3599
3644
|
if (!accountId) {
|
|
3600
|
-
const { STSClient:
|
|
3601
|
-
const stsClient = new
|
|
3645
|
+
const { STSClient: STSClient10, GetCallerIdentityCommand: GetCallerIdentityCommand11 } = await import("@aws-sdk/client-sts");
|
|
3646
|
+
const stsClient = new STSClient10({ region });
|
|
3602
3647
|
const identity = await stsClient.send(new GetCallerIdentityCommand11({}));
|
|
3603
3648
|
accountId = identity.Account;
|
|
3604
3649
|
stsClient.destroy();
|
|
@@ -7537,6 +7582,50 @@ Error: ${err.message || "Unknown error"}`,
|
|
|
7537
7582
|
}
|
|
7538
7583
|
return resourceType.startsWith("AWS::");
|
|
7539
7584
|
}
|
|
7585
|
+
/**
|
|
7586
|
+
* Read the AWS-current properties of a resource managed via Cloud Control
|
|
7587
|
+
* API, for `cdkd drift` comparison.
|
|
7588
|
+
*
|
|
7589
|
+
* Strategy: `GetResource(TypeName, Identifier)` returns `ResourceModel` as
|
|
7590
|
+
* a JSON string of every property AWS reports for the resource. Parse and
|
|
7591
|
+
* surface it as the AWS-current snapshot — the drift command intersects
|
|
7592
|
+
* this against the keys present in cdkd state, so AWS-only keys (timestamps,
|
|
7593
|
+
* generated ids, etc.) are filtered out at compare time.
|
|
7594
|
+
*
|
|
7595
|
+
* Returns `undefined` for the unique cases that mean "drift unknown" (the
|
|
7596
|
+
* resource was deleted out from under cdkd, or the response had no
|
|
7597
|
+
* Properties field). Re-throws on any other error so the drift command can
|
|
7598
|
+
* surface throttling / access-denied issues to the user.
|
|
7599
|
+
*
|
|
7600
|
+
* This single CC API implementation gives drift detection coverage to every
|
|
7601
|
+
* resource type that goes through CC API — the majority of cdkd's surface.
|
|
7602
|
+
* SDK Providers add their own `readCurrentState` incrementally (PR D).
|
|
7603
|
+
*/
|
|
7604
|
+
async readCurrentState(physicalId, _logicalId, resourceType) {
|
|
7605
|
+
try {
|
|
7606
|
+
const response = await this.cloudControlClient.send(
|
|
7607
|
+
new GetResourceCommand2({
|
|
7608
|
+
TypeName: resourceType,
|
|
7609
|
+
Identifier: physicalId
|
|
7610
|
+
})
|
|
7611
|
+
);
|
|
7612
|
+
const raw = response.ResourceDescription?.Properties;
|
|
7613
|
+
if (typeof raw !== "string" || raw.length === 0) {
|
|
7614
|
+
return void 0;
|
|
7615
|
+
}
|
|
7616
|
+
const parsed = JSON.parse(raw);
|
|
7617
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
7618
|
+
return void 0;
|
|
7619
|
+
}
|
|
7620
|
+
return parsed;
|
|
7621
|
+
} catch (error) {
|
|
7622
|
+
const err = error;
|
|
7623
|
+
if (err.name === "ResourceNotFoundException") {
|
|
7624
|
+
return void 0;
|
|
7625
|
+
}
|
|
7626
|
+
throw error;
|
|
7627
|
+
}
|
|
7628
|
+
}
|
|
7540
7629
|
/**
|
|
7541
7630
|
* Adopt an already-deployed resource into cdkd state via Cloud Control API.
|
|
7542
7631
|
*
|
|
@@ -25556,7 +25645,7 @@ import {
|
|
|
25556
25645
|
ModifyCacheClusterCommand,
|
|
25557
25646
|
ListTagsForResourceCommand as ListTagsForResourceCommand14
|
|
25558
25647
|
} from "@aws-sdk/client-elasticache";
|
|
25559
|
-
import { STSClient as
|
|
25648
|
+
import { STSClient as STSClient6, GetCallerIdentityCommand as GetCallerIdentityCommand6 } from "@aws-sdk/client-sts";
|
|
25560
25649
|
var ElastiCacheProvider = class {
|
|
25561
25650
|
client;
|
|
25562
25651
|
stsClient;
|
|
@@ -26079,7 +26168,7 @@ var ElastiCacheProvider = class {
|
|
|
26079
26168
|
if (this.cachedAccountId)
|
|
26080
26169
|
return this.cachedAccountId;
|
|
26081
26170
|
if (!this.stsClient) {
|
|
26082
|
-
this.stsClient = new
|
|
26171
|
+
this.stsClient = new STSClient6(this.providerRegion ? { region: this.providerRegion } : {});
|
|
26083
26172
|
}
|
|
26084
26173
|
const identity = await this.stsClient.send(new GetCallerIdentityCommand6({}));
|
|
26085
26174
|
if (!identity.Account) {
|
|
@@ -26106,7 +26195,7 @@ import {
|
|
|
26106
26195
|
NamespaceNotFound,
|
|
26107
26196
|
ServiceNotFound
|
|
26108
26197
|
} from "@aws-sdk/client-servicediscovery";
|
|
26109
|
-
import { STSClient as
|
|
26198
|
+
import { STSClient as STSClient7, GetCallerIdentityCommand as GetCallerIdentityCommand7 } from "@aws-sdk/client-sts";
|
|
26110
26199
|
var ServiceDiscoveryProvider = class {
|
|
26111
26200
|
client;
|
|
26112
26201
|
stsClient;
|
|
@@ -26138,7 +26227,7 @@ var ServiceDiscoveryProvider = class {
|
|
|
26138
26227
|
}
|
|
26139
26228
|
getStsClient() {
|
|
26140
26229
|
if (!this.stsClient) {
|
|
26141
|
-
this.stsClient = new
|
|
26230
|
+
this.stsClient = new STSClient7(this.providerRegion ? { region: this.providerRegion } : {});
|
|
26142
26231
|
}
|
|
26143
26232
|
return this.stsClient;
|
|
26144
26233
|
}
|
|
@@ -27121,7 +27210,7 @@ import {
|
|
|
27121
27210
|
GetTagsCommand,
|
|
27122
27211
|
EntityNotFoundException
|
|
27123
27212
|
} from "@aws-sdk/client-glue";
|
|
27124
|
-
import { STSClient as
|
|
27213
|
+
import { STSClient as STSClient8, GetCallerIdentityCommand as GetCallerIdentityCommand8 } from "@aws-sdk/client-sts";
|
|
27125
27214
|
var GlueProvider = class {
|
|
27126
27215
|
client;
|
|
27127
27216
|
stsClient;
|
|
@@ -27648,7 +27737,7 @@ var GlueProvider = class {
|
|
|
27648
27737
|
if (this.cachedAccountId)
|
|
27649
27738
|
return this.cachedAccountId;
|
|
27650
27739
|
if (!this.stsClient) {
|
|
27651
|
-
this.stsClient = new
|
|
27740
|
+
this.stsClient = new STSClient8(this.providerRegion ? { region: this.providerRegion } : {});
|
|
27652
27741
|
}
|
|
27653
27742
|
const identity = await this.stsClient.send(new GetCallerIdentityCommand8({}));
|
|
27654
27743
|
if (!identity.Account) {
|
|
@@ -32919,6 +33008,7 @@ async function deployCommand(stacks, options) {
|
|
|
32919
33008
|
...options.resourceWarnAfter && { resourceWarnAfter: options.resourceWarnAfter },
|
|
32920
33009
|
...options.resourceTimeout && { resourceTimeout: options.resourceTimeout }
|
|
32921
33010
|
});
|
|
33011
|
+
await applyRoleArnIfSet({ roleArn: options.roleArn, region: options.region });
|
|
32922
33012
|
if (!options.wait) {
|
|
32923
33013
|
process.env["CDKD_NO_WAIT"] = "true";
|
|
32924
33014
|
}
|
|
@@ -33020,8 +33110,8 @@ async function deployCommand(stacks, options) {
|
|
|
33020
33110
|
addDependencies(stack.stackName);
|
|
33021
33111
|
}
|
|
33022
33112
|
}
|
|
33023
|
-
const { STSClient:
|
|
33024
|
-
const stsClient = new
|
|
33113
|
+
const { STSClient: STSClient10, GetCallerIdentityCommand: GetCallerIdentityCommand11 } = await import("@aws-sdk/client-sts");
|
|
33114
|
+
const stsClient = new STSClient10({
|
|
33025
33115
|
region: options.region || process.env["AWS_REGION"] || "us-east-1"
|
|
33026
33116
|
});
|
|
33027
33117
|
const callerIdentity = await stsClient.send(new GetCallerIdentityCommand11({}));
|
|
@@ -33265,6 +33355,7 @@ async function diffCommand(stacks, options) {
|
|
|
33265
33355
|
logger.setLevel("debug");
|
|
33266
33356
|
}
|
|
33267
33357
|
warnIfDeprecatedRegion(options);
|
|
33358
|
+
await applyRoleArnIfSet({ roleArn: options.roleArn, region: options.region });
|
|
33268
33359
|
const app = resolveApp(options.app);
|
|
33269
33360
|
if (!app) {
|
|
33270
33361
|
throw new Error(
|
|
@@ -33412,8 +33503,321 @@ function createDiffCommand() {
|
|
|
33412
33503
|
return cmd;
|
|
33413
33504
|
}
|
|
33414
33505
|
|
|
33506
|
+
// src/cli/commands/drift.ts
|
|
33507
|
+
import { Command as Command6, Option as Option3 } from "commander";
|
|
33508
|
+
init_aws_clients();
|
|
33509
|
+
|
|
33510
|
+
// src/analyzer/drift-calculator.ts
|
|
33511
|
+
function calculateResourceDrift(stateProperties, awsProperties) {
|
|
33512
|
+
const drifts = [];
|
|
33513
|
+
for (const key of Object.keys(stateProperties)) {
|
|
33514
|
+
diffAt(key, stateProperties[key], awsProperties[key], drifts);
|
|
33515
|
+
}
|
|
33516
|
+
return drifts;
|
|
33517
|
+
}
|
|
33518
|
+
function diffAt(path, stateValue, awsValue, out) {
|
|
33519
|
+
if (deepEqual(stateValue, awsValue))
|
|
33520
|
+
return;
|
|
33521
|
+
if (isPlainObject(stateValue) && isPlainObject(awsValue) && !Array.isArray(stateValue) && !Array.isArray(awsValue)) {
|
|
33522
|
+
for (const key of Object.keys(stateValue)) {
|
|
33523
|
+
diffAt(`${path}.${key}`, stateValue[key], awsValue[key], out);
|
|
33524
|
+
}
|
|
33525
|
+
return;
|
|
33526
|
+
}
|
|
33527
|
+
out.push({ path, stateValue, awsValue });
|
|
33528
|
+
}
|
|
33529
|
+
function deepEqual(a, b) {
|
|
33530
|
+
if (a === b)
|
|
33531
|
+
return true;
|
|
33532
|
+
if (a === null || b === null || a === void 0 || b === void 0) {
|
|
33533
|
+
return a === b;
|
|
33534
|
+
}
|
|
33535
|
+
if (typeof a !== typeof b)
|
|
33536
|
+
return false;
|
|
33537
|
+
if (typeof a !== "object")
|
|
33538
|
+
return false;
|
|
33539
|
+
if (Array.isArray(a) || Array.isArray(b)) {
|
|
33540
|
+
if (!Array.isArray(a) || !Array.isArray(b))
|
|
33541
|
+
return false;
|
|
33542
|
+
if (a.length !== b.length)
|
|
33543
|
+
return false;
|
|
33544
|
+
return a.every((v, i) => deepEqual(v, b[i]));
|
|
33545
|
+
}
|
|
33546
|
+
const aObj = a;
|
|
33547
|
+
const bObj = b;
|
|
33548
|
+
const aKeys = Object.keys(aObj);
|
|
33549
|
+
const bKeys = Object.keys(bObj);
|
|
33550
|
+
if (aKeys.length !== bKeys.length)
|
|
33551
|
+
return false;
|
|
33552
|
+
for (const key of aKeys) {
|
|
33553
|
+
if (!Object.prototype.hasOwnProperty.call(bObj, key))
|
|
33554
|
+
return false;
|
|
33555
|
+
if (!deepEqual(aObj[key], bObj[key]))
|
|
33556
|
+
return false;
|
|
33557
|
+
}
|
|
33558
|
+
return true;
|
|
33559
|
+
}
|
|
33560
|
+
function isPlainObject(value) {
|
|
33561
|
+
return typeof value === "object" && value !== null;
|
|
33562
|
+
}
|
|
33563
|
+
|
|
33564
|
+
// src/cli/commands/drift.ts
|
|
33565
|
+
var DriftDetectedError = class _DriftDetectedError extends CdkdError {
|
|
33566
|
+
silent = true;
|
|
33567
|
+
constructor() {
|
|
33568
|
+
super("drift detected", "DRIFT_DETECTED");
|
|
33569
|
+
this.name = "DriftDetectedError";
|
|
33570
|
+
Object.setPrototypeOf(this, _DriftDetectedError.prototype);
|
|
33571
|
+
}
|
|
33572
|
+
};
|
|
33573
|
+
async function driftCommand(stacks, options) {
|
|
33574
|
+
const logger = getLogger();
|
|
33575
|
+
if (options.verbose) {
|
|
33576
|
+
logger.setLevel("debug");
|
|
33577
|
+
}
|
|
33578
|
+
warnIfDeprecatedRegion(options);
|
|
33579
|
+
if (!options.all && stacks.length === 0) {
|
|
33580
|
+
throw new Error("Stack name is required. Usage: cdkd drift <stack> [<stack>...] | --all");
|
|
33581
|
+
}
|
|
33582
|
+
await applyRoleArnIfSet({ roleArn: options.roleArn, region: options.region });
|
|
33583
|
+
const awsClients = new AwsClients({
|
|
33584
|
+
...options.region && { region: options.region },
|
|
33585
|
+
...options.profile && { profile: options.profile }
|
|
33586
|
+
});
|
|
33587
|
+
setAwsClients(awsClients);
|
|
33588
|
+
try {
|
|
33589
|
+
const region = options.region || process.env["AWS_REGION"] || "us-east-1";
|
|
33590
|
+
const bucket = await resolveStateBucketWithDefault(options.stateBucket, region);
|
|
33591
|
+
const prefix = options.statePrefix;
|
|
33592
|
+
const stateBackend = new S3StateBackend(
|
|
33593
|
+
awsClients.s3,
|
|
33594
|
+
{ bucket, prefix },
|
|
33595
|
+
{
|
|
33596
|
+
region,
|
|
33597
|
+
...options.profile && { profile: options.profile }
|
|
33598
|
+
}
|
|
33599
|
+
);
|
|
33600
|
+
await stateBackend.verifyBucketExists();
|
|
33601
|
+
const providerRegistry = new ProviderRegistry();
|
|
33602
|
+
registerAllProviders(providerRegistry);
|
|
33603
|
+
providerRegistry.setCustomResourceResponseBucket(bucket);
|
|
33604
|
+
const stateRefs = await stateBackend.listStacks();
|
|
33605
|
+
const targetRefs = resolveTargetRefs(stacks, stateRefs, options);
|
|
33606
|
+
const reports = [];
|
|
33607
|
+
for (const ref of targetRefs) {
|
|
33608
|
+
if (!ref.region) {
|
|
33609
|
+
throw new Error(
|
|
33610
|
+
`Stack '${ref.stackName}' has only a legacy state record without a region. Run 'cdkd deploy ${ref.stackName}' (or any cdkd write) to migrate it to the region-scoped layout, then re-run drift detection.`
|
|
33611
|
+
);
|
|
33612
|
+
}
|
|
33613
|
+
const report = await runDriftForStack(
|
|
33614
|
+
ref.stackName,
|
|
33615
|
+
ref.region,
|
|
33616
|
+
stateBackend,
|
|
33617
|
+
providerRegistry
|
|
33618
|
+
);
|
|
33619
|
+
reports.push(report);
|
|
33620
|
+
}
|
|
33621
|
+
if (options.json) {
|
|
33622
|
+
writeJsonReport(reports);
|
|
33623
|
+
} else {
|
|
33624
|
+
writeHumanReport(reports);
|
|
33625
|
+
}
|
|
33626
|
+
const drifted = reports.some((r) => r.outcomes.some((o) => o.kind === "drifted"));
|
|
33627
|
+
if (drifted) {
|
|
33628
|
+
throw new DriftDetectedError();
|
|
33629
|
+
}
|
|
33630
|
+
} finally {
|
|
33631
|
+
awsClients.destroy();
|
|
33632
|
+
}
|
|
33633
|
+
}
|
|
33634
|
+
function resolveTargetRefs(stacks, stateRefs, options) {
|
|
33635
|
+
if (options.all) {
|
|
33636
|
+
if (stateRefs.length === 0) {
|
|
33637
|
+
throw new Error("No stacks found in state bucket.");
|
|
33638
|
+
}
|
|
33639
|
+
if (options.stackRegion) {
|
|
33640
|
+
return stateRefs.filter((r) => r.region === options.stackRegion);
|
|
33641
|
+
}
|
|
33642
|
+
return stateRefs;
|
|
33643
|
+
}
|
|
33644
|
+
const out = [];
|
|
33645
|
+
for (const stackName of stacks) {
|
|
33646
|
+
const matches = stateRefs.filter((r) => r.stackName === stackName);
|
|
33647
|
+
if (matches.length === 0) {
|
|
33648
|
+
throw new Error(
|
|
33649
|
+
`No state found for stack '${stackName}'. Run 'cdkd state list' to see available stacks.`
|
|
33650
|
+
);
|
|
33651
|
+
}
|
|
33652
|
+
if (options.stackRegion) {
|
|
33653
|
+
const ref = matches.find((r) => r.region === options.stackRegion);
|
|
33654
|
+
if (!ref) {
|
|
33655
|
+
const seen = matches.map((r) => r.region ?? "(legacy)").join(", ");
|
|
33656
|
+
throw new Error(
|
|
33657
|
+
`No state found for stack '${stackName}' in region '${options.stackRegion}'. Available regions: ${seen}.`
|
|
33658
|
+
);
|
|
33659
|
+
}
|
|
33660
|
+
out.push(ref);
|
|
33661
|
+
continue;
|
|
33662
|
+
}
|
|
33663
|
+
if (matches.length === 1) {
|
|
33664
|
+
out.push(matches[0]);
|
|
33665
|
+
continue;
|
|
33666
|
+
}
|
|
33667
|
+
const regions = matches.map((r) => r.region ?? "(legacy)").join(", ");
|
|
33668
|
+
throw new Error(
|
|
33669
|
+
`Stack '${stackName}' has state in multiple regions: ${regions}. Re-run with --stack-region <region> to disambiguate.`
|
|
33670
|
+
);
|
|
33671
|
+
}
|
|
33672
|
+
return out;
|
|
33673
|
+
}
|
|
33674
|
+
async function runDriftForStack(stackName, region, stateBackend, providerRegistry) {
|
|
33675
|
+
const result = await stateBackend.getState(stackName, region);
|
|
33676
|
+
if (!result) {
|
|
33677
|
+
throw new Error(
|
|
33678
|
+
`No state found for stack '${stackName}' (${region}). Run 'cdkd state list' to see available stacks.`
|
|
33679
|
+
);
|
|
33680
|
+
}
|
|
33681
|
+
return await withStackName(stackName, async () => {
|
|
33682
|
+
const outcomes = [];
|
|
33683
|
+
const state = result.state;
|
|
33684
|
+
const entries = Object.entries(state.resources ?? {}).sort(([a], [b]) => a.localeCompare(b));
|
|
33685
|
+
for (const [logicalId, resource] of entries) {
|
|
33686
|
+
if (providerRegistry.shouldSkipResource(resource.resourceType)) {
|
|
33687
|
+
continue;
|
|
33688
|
+
}
|
|
33689
|
+
let provider;
|
|
33690
|
+
try {
|
|
33691
|
+
provider = providerRegistry.getProvider(resource.resourceType);
|
|
33692
|
+
} catch {
|
|
33693
|
+
outcomes.push({
|
|
33694
|
+
kind: "unsupported",
|
|
33695
|
+
logicalId,
|
|
33696
|
+
resourceType: resource.resourceType
|
|
33697
|
+
});
|
|
33698
|
+
continue;
|
|
33699
|
+
}
|
|
33700
|
+
if (!provider.readCurrentState) {
|
|
33701
|
+
outcomes.push({
|
|
33702
|
+
kind: "unsupported",
|
|
33703
|
+
logicalId,
|
|
33704
|
+
resourceType: resource.resourceType
|
|
33705
|
+
});
|
|
33706
|
+
continue;
|
|
33707
|
+
}
|
|
33708
|
+
const aws = await provider.readCurrentState(
|
|
33709
|
+
resource.physicalId,
|
|
33710
|
+
logicalId,
|
|
33711
|
+
resource.resourceType
|
|
33712
|
+
);
|
|
33713
|
+
if (aws === void 0) {
|
|
33714
|
+
outcomes.push({
|
|
33715
|
+
kind: "unsupported",
|
|
33716
|
+
logicalId,
|
|
33717
|
+
resourceType: resource.resourceType
|
|
33718
|
+
});
|
|
33719
|
+
continue;
|
|
33720
|
+
}
|
|
33721
|
+
const changes = calculateResourceDrift(resource.properties ?? {}, aws);
|
|
33722
|
+
if (changes.length === 0) {
|
|
33723
|
+
outcomes.push({ kind: "clean", logicalId, resourceType: resource.resourceType });
|
|
33724
|
+
} else {
|
|
33725
|
+
outcomes.push({
|
|
33726
|
+
kind: "drifted",
|
|
33727
|
+
logicalId,
|
|
33728
|
+
resourceType: resource.resourceType,
|
|
33729
|
+
changes
|
|
33730
|
+
});
|
|
33731
|
+
}
|
|
33732
|
+
}
|
|
33733
|
+
return { stackName, region, outcomes };
|
|
33734
|
+
});
|
|
33735
|
+
}
|
|
33736
|
+
function writeJsonReport(reports) {
|
|
33737
|
+
const payload = reports.map((r) => {
|
|
33738
|
+
const drifted = r.outcomes.filter((o) => o.kind === "drifted").map((o) => ({ logicalId: o.logicalId, type: o.resourceType, changes: o.changes }));
|
|
33739
|
+
const clean = r.outcomes.filter((o) => o.kind === "clean").map((o) => ({ logicalId: o.logicalId, type: o.resourceType }));
|
|
33740
|
+
const notSupported = r.outcomes.filter((o) => o.kind === "unsupported").map((o) => ({ logicalId: o.logicalId, type: o.resourceType }));
|
|
33741
|
+
return { stack: r.stackName, region: r.region, drifted, clean, notSupported };
|
|
33742
|
+
});
|
|
33743
|
+
process.stdout.write(`${JSON.stringify(payload, null, 2)}
|
|
33744
|
+
`);
|
|
33745
|
+
}
|
|
33746
|
+
function writeHumanReport(reports) {
|
|
33747
|
+
for (const report of reports) {
|
|
33748
|
+
const drifted = report.outcomes.filter(
|
|
33749
|
+
(o) => o.kind === "drifted"
|
|
33750
|
+
);
|
|
33751
|
+
const unsupported = report.outcomes.filter(
|
|
33752
|
+
(o) => o.kind === "unsupported"
|
|
33753
|
+
);
|
|
33754
|
+
const total = report.outcomes.length;
|
|
33755
|
+
if (drifted.length === 0) {
|
|
33756
|
+
process.stdout.write(
|
|
33757
|
+
`\u2713 ${report.stackName} (${report.region}): no drift detected (${total} resource${total === 1 ? "" : "s"} checked, ${unsupported.length} unsupported)
|
|
33758
|
+
`
|
|
33759
|
+
);
|
|
33760
|
+
} else {
|
|
33761
|
+
const word = drifted.length === 1 ? "resource" : "resources";
|
|
33762
|
+
process.stdout.write(
|
|
33763
|
+
`
|
|
33764
|
+
\u26A0 ${report.stackName} (${report.region}): drift detected on ${drifted.length} ${word}
|
|
33765
|
+
|
|
33766
|
+
`
|
|
33767
|
+
);
|
|
33768
|
+
for (const o of drifted) {
|
|
33769
|
+
process.stdout.write(` ~ ${o.logicalId} (${o.resourceType})
|
|
33770
|
+
`);
|
|
33771
|
+
for (const change of o.changes) {
|
|
33772
|
+
process.stdout.write(` - ${change.path}: ${formatScalar(change.stateValue)}
|
|
33773
|
+
`);
|
|
33774
|
+
process.stdout.write(` + ${change.path}: ${formatScalar(change.awsValue)}
|
|
33775
|
+
`);
|
|
33776
|
+
}
|
|
33777
|
+
process.stdout.write("\n");
|
|
33778
|
+
}
|
|
33779
|
+
}
|
|
33780
|
+
if (unsupported.length > 0) {
|
|
33781
|
+
process.stdout.write(
|
|
33782
|
+
`
|
|
33783
|
+
${unsupported.length} resource(s) reported as drift unknown \u2014 provider does not yet support drift detection:
|
|
33784
|
+
`
|
|
33785
|
+
);
|
|
33786
|
+
for (const o of unsupported) {
|
|
33787
|
+
process.stdout.write(` ? ${o.logicalId} (${o.resourceType})
|
|
33788
|
+
`);
|
|
33789
|
+
}
|
|
33790
|
+
}
|
|
33791
|
+
}
|
|
33792
|
+
}
|
|
33793
|
+
function formatScalar(value) {
|
|
33794
|
+
if (value === null)
|
|
33795
|
+
return "null";
|
|
33796
|
+
if (value === void 0)
|
|
33797
|
+
return "undefined";
|
|
33798
|
+
if (typeof value === "string")
|
|
33799
|
+
return value;
|
|
33800
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
33801
|
+
return String(value);
|
|
33802
|
+
return JSON.stringify(value);
|
|
33803
|
+
}
|
|
33804
|
+
function stackRegionOption() {
|
|
33805
|
+
return new Option3(
|
|
33806
|
+
"--stack-region <region>",
|
|
33807
|
+
"Region of the stack record to inspect. Required when the same stack name has state in multiple regions."
|
|
33808
|
+
);
|
|
33809
|
+
}
|
|
33810
|
+
function createDriftCommand() {
|
|
33811
|
+
const cmd = new Command6("drift").description(
|
|
33812
|
+
"Detect drift between cdkd state and AWS reality. Exits 0 when no drift, 1 when drift is detected."
|
|
33813
|
+
).argument("[stacks...]", "Stack name(s) to check (physical CloudFormation names)").option("--all", "Check every stack in the state bucket", false).option("--json", "Output as JSON", false).addOption(stackRegionOption()).action(withErrorHandling(driftCommand));
|
|
33814
|
+
[...commonOptions, ...stateOptions].forEach((opt) => cmd.addOption(opt));
|
|
33815
|
+
cmd.addOption(deprecatedRegionOption);
|
|
33816
|
+
return cmd;
|
|
33817
|
+
}
|
|
33818
|
+
|
|
33415
33819
|
// src/cli/commands/destroy.ts
|
|
33416
|
-
import { Command as
|
|
33820
|
+
import { Command as Command7 } from "commander";
|
|
33417
33821
|
init_aws_clients();
|
|
33418
33822
|
|
|
33419
33823
|
// src/cli/commands/destroy-runner.ts
|
|
@@ -33677,6 +34081,7 @@ async function destroyCommand(stackArgs, options) {
|
|
|
33677
34081
|
...options.resourceWarnAfter && { resourceWarnAfter: options.resourceWarnAfter },
|
|
33678
34082
|
...options.resourceTimeout && { resourceTimeout: options.resourceTimeout }
|
|
33679
34083
|
});
|
|
34084
|
+
await applyRoleArnIfSet({ roleArn: options.roleArn, region: options.region });
|
|
33680
34085
|
const region = options.region || process.env["AWS_REGION"] || "us-east-1";
|
|
33681
34086
|
const stateBucket = await resolveStateBucketWithDefault(options.stateBucket, region);
|
|
33682
34087
|
logger.info("Starting stack destruction...");
|
|
@@ -33835,7 +34240,7 @@ Preparing to destroy stack: ${stackName}`);
|
|
|
33835
34240
|
}
|
|
33836
34241
|
}
|
|
33837
34242
|
function createDestroyCommand() {
|
|
33838
|
-
const cmd = new
|
|
34243
|
+
const cmd = new Command7("destroy").description("Destroy all resources in the stack").argument(
|
|
33839
34244
|
"[stacks...]",
|
|
33840
34245
|
"Stack name(s) to destroy. Accepts physical CloudFormation names (e.g. 'MyStage-Api') or CDK display paths (e.g. 'MyStage/Api'). Supports wildcards (e.g. 'MyStage/*')."
|
|
33841
34246
|
).option("--all", "Destroy all stacks", false).action(withErrorHandling(destroyCommand));
|
|
@@ -33854,7 +34259,7 @@ function createDestroyCommand() {
|
|
|
33854
34259
|
|
|
33855
34260
|
// src/cli/commands/orphan.ts
|
|
33856
34261
|
import * as readline2 from "node:readline/promises";
|
|
33857
|
-
import { Command as
|
|
34262
|
+
import { Command as Command8 } from "commander";
|
|
33858
34263
|
init_aws_clients();
|
|
33859
34264
|
|
|
33860
34265
|
// src/cli/cdk-path.ts
|
|
@@ -34278,6 +34683,7 @@ async function orphanCommand(pathArgs, options) {
|
|
|
34278
34683
|
if (options.verbose)
|
|
34279
34684
|
logger.setLevel("debug");
|
|
34280
34685
|
warnIfDeprecatedRegion(options);
|
|
34686
|
+
await applyRoleArnIfSet({ roleArn: options.roleArn, region: options.region });
|
|
34281
34687
|
if (pathArgs.length === 0) {
|
|
34282
34688
|
throw new Error(
|
|
34283
34689
|
"'cdkd orphan' requires at least one construct path, e.g. 'cdkd orphan MyStack/MyTable'.\n To remove a stack's state record (the previous behavior), use:\n cdkd state orphan MyStack"
|
|
@@ -34534,7 +34940,7 @@ async function confirmPrompt(prompt) {
|
|
|
34534
34940
|
}
|
|
34535
34941
|
}
|
|
34536
34942
|
function createOrphanCommand() {
|
|
34537
|
-
const cmd = new
|
|
34943
|
+
const cmd = new Command8("orphan").description(
|
|
34538
34944
|
"Remove one or more resources from cdkd state by construct path (does NOT delete AWS resources). Mirrors aws-cdk-cli's 'cdk orphan --unstable=orphan'. Synth-driven; for the previous whole-stack-orphan behavior, use 'cdkd state orphan <stack>'."
|
|
34539
34945
|
).argument(
|
|
34540
34946
|
"<paths...>",
|
|
@@ -34560,13 +34966,14 @@ function createOrphanCommand() {
|
|
|
34560
34966
|
}
|
|
34561
34967
|
|
|
34562
34968
|
// src/cli/commands/publish-assets.ts
|
|
34563
|
-
import { Option as
|
|
34969
|
+
import { Option as Option4, Command as Command9 } from "commander";
|
|
34564
34970
|
async function publishAssetsCommand(options) {
|
|
34565
34971
|
const logger = getLogger();
|
|
34566
34972
|
if (options.verbose) {
|
|
34567
34973
|
logger.setLevel("debug");
|
|
34568
34974
|
}
|
|
34569
34975
|
warnIfDeprecatedRegion(options);
|
|
34976
|
+
await applyRoleArnIfSet({ roleArn: options.roleArn, region: options.region });
|
|
34570
34977
|
logger.info("Publishing assets...");
|
|
34571
34978
|
logger.debug("Asset manifest path:", options.path);
|
|
34572
34979
|
const publisher = new AssetPublisher();
|
|
@@ -34579,13 +34986,13 @@ async function publishAssetsCommand(options) {
|
|
|
34579
34986
|
logger.info("\u2705 Asset publishing complete");
|
|
34580
34987
|
}
|
|
34581
34988
|
function createPublishAssetsCommand() {
|
|
34582
|
-
const cmd = new
|
|
34583
|
-
new
|
|
34989
|
+
const cmd = new Command9("publish-assets").description("Publish assets to S3/ECR from asset manifest").requiredOption("--path <path>", "Path to asset manifest file or directory").addOption(
|
|
34990
|
+
new Option4(
|
|
34584
34991
|
"--asset-publish-concurrency <number>",
|
|
34585
34992
|
"Maximum concurrent asset publish operations"
|
|
34586
34993
|
).default(8).argParser((value) => parseInt(value, 10))
|
|
34587
34994
|
).addOption(
|
|
34588
|
-
new
|
|
34995
|
+
new Option4("--image-build-concurrency <number>", "Maximum concurrent Docker image builds").default(4).argParser((value) => parseInt(value, 10))
|
|
34589
34996
|
).action(withErrorHandling(publishAssetsCommand));
|
|
34590
34997
|
commonOptions.forEach((opt) => cmd.addOption(opt));
|
|
34591
34998
|
cmd.addOption(deprecatedRegionOption);
|
|
@@ -34593,7 +35000,7 @@ function createPublishAssetsCommand() {
|
|
|
34593
35000
|
}
|
|
34594
35001
|
|
|
34595
35002
|
// src/cli/commands/force-unlock.ts
|
|
34596
|
-
import { Command as
|
|
35003
|
+
import { Command as Command10, Option as Option5 } from "commander";
|
|
34597
35004
|
init_aws_clients();
|
|
34598
35005
|
async function forceUnlockCommand(stackArgs, options) {
|
|
34599
35006
|
const logger = getLogger();
|
|
@@ -34601,6 +35008,7 @@ async function forceUnlockCommand(stackArgs, options) {
|
|
|
34601
35008
|
logger.setLevel("debug");
|
|
34602
35009
|
}
|
|
34603
35010
|
warnIfDeprecatedRegion(options);
|
|
35011
|
+
await applyRoleArnIfSet({ roleArn: options.roleArn, region: options.region });
|
|
34604
35012
|
const stackPatterns = stackArgs.length > 0 ? stackArgs : options.stack ? [options.stack] : [];
|
|
34605
35013
|
if (stackPatterns.length === 0) {
|
|
34606
35014
|
throw new Error("Stack name is required. Usage: cdkd force-unlock <stack-name>");
|
|
@@ -34653,8 +35061,8 @@ async function forceUnlockCommand(stackArgs, options) {
|
|
|
34653
35061
|
}
|
|
34654
35062
|
}
|
|
34655
35063
|
function createForceUnlockCommand() {
|
|
34656
|
-
const cmd = new
|
|
34657
|
-
new
|
|
35064
|
+
const cmd = new Command10("force-unlock").description("Force-release a stale lock on a stack").argument("[stacks...]", "Stack name(s) to unlock").addOption(
|
|
35065
|
+
new Option5(
|
|
34658
35066
|
"--stack-region <region>",
|
|
34659
35067
|
"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."
|
|
34660
35068
|
)
|
|
@@ -34666,7 +35074,7 @@ function createForceUnlockCommand() {
|
|
|
34666
35074
|
|
|
34667
35075
|
// src/cli/commands/state.ts
|
|
34668
35076
|
import * as readline4 from "node:readline/promises";
|
|
34669
|
-
import { Command as
|
|
35077
|
+
import { Command as Command12, Option as Option6 } from "commander";
|
|
34670
35078
|
import {
|
|
34671
35079
|
GetBucketLocationCommand as GetBucketLocationCommand2,
|
|
34672
35080
|
GetObjectCommand as GetObjectCommand4,
|
|
@@ -34676,7 +35084,7 @@ init_aws_clients();
|
|
|
34676
35084
|
|
|
34677
35085
|
// src/cli/commands/state-migrate.ts
|
|
34678
35086
|
import * as readline3 from "node:readline/promises";
|
|
34679
|
-
import { Command as
|
|
35087
|
+
import { Command as Command11 } from "commander";
|
|
34680
35088
|
import {
|
|
34681
35089
|
CopyObjectCommand,
|
|
34682
35090
|
CreateBucketCommand as CreateBucketCommand4,
|
|
@@ -34696,6 +35104,7 @@ async function stateMigrateCommand(options) {
|
|
|
34696
35104
|
const logger = getLogger();
|
|
34697
35105
|
if (options.verbose)
|
|
34698
35106
|
logger.setLevel("debug");
|
|
35107
|
+
await applyRoleArnIfSet({ roleArn: options.roleArn, region: options.region });
|
|
34699
35108
|
const region = options.region || process.env["AWS_REGION"] || "us-east-1";
|
|
34700
35109
|
const awsClients = new AwsClients({
|
|
34701
35110
|
region,
|
|
@@ -34959,7 +35368,7 @@ async function confirmPrompt2(prompt) {
|
|
|
34959
35368
|
}
|
|
34960
35369
|
}
|
|
34961
35370
|
function createStateMigrateCommand() {
|
|
34962
|
-
const cmd = new
|
|
35371
|
+
const cmd = new Command11("migrate").description(
|
|
34963
35372
|
"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."
|
|
34964
35373
|
).option(
|
|
34965
35374
|
"--region <region>",
|
|
@@ -35009,6 +35418,7 @@ function resolveSingleRegion(stackName, refs, requestedRegion) {
|
|
|
35009
35418
|
}
|
|
35010
35419
|
async function setupStateBackend(options) {
|
|
35011
35420
|
warnIfDeprecatedRegion(options);
|
|
35421
|
+
await applyRoleArnIfSet({ roleArn: options.roleArn, region: options.region });
|
|
35012
35422
|
const awsClients = new AwsClients({
|
|
35013
35423
|
...options.region && { region: options.region },
|
|
35014
35424
|
...options.profile && { profile: options.profile }
|
|
@@ -35117,7 +35527,7 @@ async function stateListCommand(options) {
|
|
|
35117
35527
|
}
|
|
35118
35528
|
}
|
|
35119
35529
|
function createStateListCommand() {
|
|
35120
|
-
const cmd = new
|
|
35530
|
+
const cmd = new Command12("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));
|
|
35121
35531
|
[...commonOptions, ...stateOptions].forEach((opt) => cmd.addOption(opt));
|
|
35122
35532
|
cmd.addOption(deprecatedRegionOption);
|
|
35123
35533
|
return cmd;
|
|
@@ -35221,7 +35631,7 @@ function formatLockSummary(lockInfo) {
|
|
|
35221
35631
|
return `locked by ${lockInfo.owner}${opStr}, ${expiresStr}`;
|
|
35222
35632
|
}
|
|
35223
35633
|
function createStateResourcesCommand() {
|
|
35224
|
-
const cmd = new
|
|
35634
|
+
const cmd = new Command12("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(stackRegionOption2()).action(withErrorHandling(stateResourcesCommand));
|
|
35225
35635
|
[...commonOptions, ...stateOptions].forEach((opt) => cmd.addOption(opt));
|
|
35226
35636
|
cmd.addOption(deprecatedRegionOption);
|
|
35227
35637
|
return cmd;
|
|
@@ -35309,7 +35719,7 @@ async function stateShowCommand(stackName, options) {
|
|
|
35309
35719
|
}
|
|
35310
35720
|
}
|
|
35311
35721
|
function createStateShowCommand() {
|
|
35312
|
-
const cmd = new
|
|
35722
|
+
const cmd = new Command12("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(stackRegionOption2()).action(withErrorHandling(stateShowCommand));
|
|
35313
35723
|
[...commonOptions, ...stateOptions].forEach((opt) => cmd.addOption(opt));
|
|
35314
35724
|
cmd.addOption(deprecatedRegionOption);
|
|
35315
35725
|
return cmd;
|
|
@@ -35385,16 +35795,16 @@ Use 'cdkd destroy ${stackName}' if you want to delete the actual resources.
|
|
|
35385
35795
|
setup.dispose();
|
|
35386
35796
|
}
|
|
35387
35797
|
}
|
|
35388
|
-
function
|
|
35389
|
-
return new
|
|
35798
|
+
function stackRegionOption2() {
|
|
35799
|
+
return new Option6(
|
|
35390
35800
|
"--stack-region <region>",
|
|
35391
35801
|
"Region of the stack record to operate on. Required when the same stack name has state in multiple regions."
|
|
35392
35802
|
);
|
|
35393
35803
|
}
|
|
35394
35804
|
function createStateOrphanCommand() {
|
|
35395
|
-
const cmd = new
|
|
35805
|
+
const cmd = new Command12("orphan").description(
|
|
35396
35806
|
"Orphan one or more stacks from cdkd state (removes the state record; does NOT delete AWS resources)"
|
|
35397
|
-
).argument("<stacks...>", "Stack name(s) to orphan from state").option("-f, --force", "Skip confirmation and remove even if the stack is locked", false).addOption(
|
|
35807
|
+
).argument("<stacks...>", "Stack name(s) to orphan from state").option("-f, --force", "Skip confirmation and remove even if the stack is locked", false).addOption(stackRegionOption2()).action(withErrorHandling(stateOrphanCommand));
|
|
35398
35808
|
[...commonOptions, ...stateOptions].forEach((opt) => cmd.addOption(opt));
|
|
35399
35809
|
cmd.addOption(deprecatedRegionOption);
|
|
35400
35810
|
return cmd;
|
|
@@ -35535,9 +35945,9 @@ Preparing to destroy stack: ${stackName}${ref.region ? ` (${ref.region})` : ""}`
|
|
|
35535
35945
|
}
|
|
35536
35946
|
}
|
|
35537
35947
|
function createStateDestroyCommand() {
|
|
35538
|
-
const cmd = new
|
|
35948
|
+
const cmd = new Command12("destroy").description(
|
|
35539
35949
|
"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'."
|
|
35540
|
-
).argument("[stacks...]", "Stack name(s) to destroy (physical CloudFormation names)").option("--all", "Destroy every stack in the state bucket", false).addOption(
|
|
35950
|
+
).argument("[stacks...]", "Stack name(s) to destroy (physical CloudFormation names)").option("--all", "Destroy every stack in the state bucket", false).addOption(stackRegionOption2()).addHelpText(
|
|
35541
35951
|
"after",
|
|
35542
35952
|
[
|
|
35543
35953
|
"",
|
|
@@ -35624,6 +36034,7 @@ async function stateInfoCommand(options) {
|
|
|
35624
36034
|
const logger = getLogger();
|
|
35625
36035
|
if (options.verbose)
|
|
35626
36036
|
logger.setLevel("debug");
|
|
36037
|
+
await applyRoleArnIfSet({ roleArn: options.roleArn, region: options.region });
|
|
35627
36038
|
const awsClients = new AwsClients({
|
|
35628
36039
|
...options.region && { region: options.region },
|
|
35629
36040
|
...options.profile && { profile: options.profile }
|
|
@@ -35669,14 +36080,14 @@ async function stateInfoCommand(options) {
|
|
|
35669
36080
|
}
|
|
35670
36081
|
}
|
|
35671
36082
|
function createStateInfoCommand() {
|
|
35672
|
-
const cmd = new
|
|
36083
|
+
const cmd = new Command12("info").description(
|
|
35673
36084
|
"Show cdkd state bucket info (bucket name, region, source, schema version, stack count)"
|
|
35674
36085
|
).option("--json", "Output as JSON", false).action(withErrorHandling(stateInfoCommand));
|
|
35675
36086
|
[...commonOptions, ...stateOptions].forEach((opt) => cmd.addOption(opt));
|
|
35676
36087
|
return cmd;
|
|
35677
36088
|
}
|
|
35678
36089
|
function createStateCommand() {
|
|
35679
|
-
const cmd = new
|
|
36090
|
+
const cmd = new Command12("state").description("Manage cdkd state stored in S3");
|
|
35680
36091
|
cmd.addCommand(createStateInfoCommand());
|
|
35681
36092
|
cmd.addCommand(createStateListCommand());
|
|
35682
36093
|
cmd.addCommand(createStateResourcesCommand());
|
|
@@ -35690,7 +36101,7 @@ function createStateCommand() {
|
|
|
35690
36101
|
// src/cli/commands/import.ts
|
|
35691
36102
|
import { readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "node:fs";
|
|
35692
36103
|
import * as readline6 from "node:readline/promises";
|
|
35693
|
-
import { Command as
|
|
36104
|
+
import { Command as Command13 } from "commander";
|
|
35694
36105
|
init_aws_clients();
|
|
35695
36106
|
|
|
35696
36107
|
// src/cli/commands/retire-cfn-stack.ts
|
|
@@ -35916,6 +36327,7 @@ async function importCommand(stackArg, options) {
|
|
|
35916
36327
|
logger.setLevel("debug");
|
|
35917
36328
|
process.env["CDKD_NO_LIVE"] = "1";
|
|
35918
36329
|
}
|
|
36330
|
+
await applyRoleArnIfSet({ roleArn: options.roleArn, region: options.region });
|
|
35919
36331
|
const region = options.region || process.env["AWS_REGION"] || "us-east-1";
|
|
35920
36332
|
const stateBucket = await resolveStateBucketWithDefault(options.stateBucket, region);
|
|
35921
36333
|
if (options.region) {
|
|
@@ -36369,7 +36781,7 @@ async function confirmPrompt4(prompt) {
|
|
|
36369
36781
|
}
|
|
36370
36782
|
}
|
|
36371
36783
|
function createImportCommand() {
|
|
36372
|
-
const cmd = new
|
|
36784
|
+
const cmd = new Command13("import").description(
|
|
36373
36785
|
"Adopt already-deployed AWS resources into cdkd state. Reads the CDK app to find logical IDs, resource types, and dependencies. With no flags, imports every resource via the aws:cdk:path tag. With --resource / --resource-mapping, only the listed resources are imported (CDK CLI parity); pass --auto to also tag-import the rest."
|
|
36374
36786
|
).argument(
|
|
36375
36787
|
"[stack]",
|
|
@@ -36417,6 +36829,7 @@ var SUBCOMMANDS = /* @__PURE__ */ new Set([
|
|
|
36417
36829
|
"ls",
|
|
36418
36830
|
"deploy",
|
|
36419
36831
|
"diff",
|
|
36832
|
+
"drift",
|
|
36420
36833
|
"destroy",
|
|
36421
36834
|
"orphan",
|
|
36422
36835
|
"import",
|
|
@@ -36435,13 +36848,14 @@ function reorderArgs(argv) {
|
|
|
36435
36848
|
return [...prefix, ...cmdAndAfter, ...beforeCmd];
|
|
36436
36849
|
}
|
|
36437
36850
|
async function main() {
|
|
36438
|
-
const program = new
|
|
36439
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.
|
|
36851
|
+
const program = new Command14();
|
|
36852
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.35.0");
|
|
36440
36853
|
program.addCommand(createBootstrapCommand());
|
|
36441
36854
|
program.addCommand(createSynthCommand());
|
|
36442
36855
|
program.addCommand(createListCommand());
|
|
36443
36856
|
program.addCommand(createDeployCommand());
|
|
36444
36857
|
program.addCommand(createDiffCommand());
|
|
36858
|
+
program.addCommand(createDriftCommand());
|
|
36445
36859
|
program.addCommand(createDestroyCommand());
|
|
36446
36860
|
program.addCommand(createOrphanCommand());
|
|
36447
36861
|
program.addCommand(createImportCommand());
|