@go-to-k/cdkd 0.84.0 → 0.86.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 +1 -1
- package/dist/cli.js +361 -24
- package/dist/cli.js.map +3 -3
- package/dist/go-to-k-cdkd-0.86.0.tgz +0 -0
- package/package.json +1 -1
- package/dist/go-to-k-cdkd-0.84.0.tgz +0 -0
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
- **Drop-in CDK compatible** — your existing CDK app code runs as-is.
|
|
6
6
|
- **Up to 15x faster deploys than the AWS CDK CLI (CloudFormation)**
|
|
7
|
-
- **Run AWS resources locally without deploying** — invoke Lambdas,
|
|
7
|
+
- **Run AWS resources locally without deploying** — invoke Lambdas, run ECS tasks, and serve API Gateway routes from Docker.
|
|
8
8
|
|
|
9
9
|

|
|
10
10
|
|
package/dist/cli.js
CHANGED
|
@@ -76798,6 +76798,13 @@ function inspectImageForSubstitutions(image, resources) {
|
|
|
76798
76798
|
return { pseudo: false, state: true };
|
|
76799
76799
|
}
|
|
76800
76800
|
}
|
|
76801
|
+
const join11 = obj["Fn::Join"];
|
|
76802
|
+
if (Array.isArray(join11) && join11.length === 2 && Array.isArray(join11[1])) {
|
|
76803
|
+
const scan = { pseudo: false, state: false };
|
|
76804
|
+
inspectIntrinsicNeeds(join11[1], resources, scan);
|
|
76805
|
+
if (scan.pseudo || scan.state)
|
|
76806
|
+
return scan;
|
|
76807
|
+
}
|
|
76801
76808
|
let sub;
|
|
76802
76809
|
const subRaw = obj["Fn::Sub"];
|
|
76803
76810
|
if (typeof subRaw === "string")
|
|
@@ -76823,6 +76830,42 @@ function inspectImageForSubstitutions(image, resources) {
|
|
|
76823
76830
|
}
|
|
76824
76831
|
return { pseudo, state };
|
|
76825
76832
|
}
|
|
76833
|
+
function inspectIntrinsicNeeds(node, resources, scan) {
|
|
76834
|
+
if (node === null || node === void 0)
|
|
76835
|
+
return;
|
|
76836
|
+
if (typeof node === "string" || typeof node === "number" || typeof node === "boolean")
|
|
76837
|
+
return;
|
|
76838
|
+
if (Array.isArray(node)) {
|
|
76839
|
+
for (const item of node)
|
|
76840
|
+
inspectIntrinsicNeeds(item, resources, scan);
|
|
76841
|
+
return;
|
|
76842
|
+
}
|
|
76843
|
+
if (typeof node !== "object")
|
|
76844
|
+
return;
|
|
76845
|
+
const obj = node;
|
|
76846
|
+
if (typeof obj["Ref"] === "string") {
|
|
76847
|
+
const target = obj["Ref"];
|
|
76848
|
+
if (target.startsWith("AWS::"))
|
|
76849
|
+
scan.pseudo = true;
|
|
76850
|
+
else if (resources[target]?.Type === "AWS::ECR::Repository")
|
|
76851
|
+
scan.state = true;
|
|
76852
|
+
return;
|
|
76853
|
+
}
|
|
76854
|
+
const getAtt = obj["Fn::GetAtt"];
|
|
76855
|
+
if (getAtt !== void 0) {
|
|
76856
|
+
let lid;
|
|
76857
|
+
if (Array.isArray(getAtt) && typeof getAtt[0] === "string")
|
|
76858
|
+
lid = getAtt[0];
|
|
76859
|
+
else if (typeof getAtt === "string")
|
|
76860
|
+
lid = getAtt.split(".")[0];
|
|
76861
|
+
if (lid && resources[lid]?.Type === "AWS::ECR::Repository")
|
|
76862
|
+
scan.state = true;
|
|
76863
|
+
return;
|
|
76864
|
+
}
|
|
76865
|
+
for (const value of Object.values(obj)) {
|
|
76866
|
+
inspectIntrinsicNeeds(value, resources, scan);
|
|
76867
|
+
}
|
|
76868
|
+
}
|
|
76826
76869
|
function parseEcsTarget(target) {
|
|
76827
76870
|
if (typeof target !== "string" || target.length === 0) {
|
|
76828
76871
|
throw new EcsTaskResolutionError(
|
|
@@ -77147,6 +77190,20 @@ function parseContainerImage(raw, containerName, taskLogicalId, resources, _stac
|
|
|
77147
77190
|
if (getAttImage) {
|
|
77148
77191
|
return classifyResolvedImage(getAttImage);
|
|
77149
77192
|
}
|
|
77193
|
+
const joinResolved = tryResolveImageFnJoin(raw, resources, context);
|
|
77194
|
+
if (joinResolved.kind === "resolved") {
|
|
77195
|
+
return classifyResolvedImage(joinResolved.uri);
|
|
77196
|
+
}
|
|
77197
|
+
if (joinResolved.kind === "needs-state") {
|
|
77198
|
+
throw new EcsTaskResolutionError(
|
|
77199
|
+
`Container '${containerName}' in task '${taskLogicalId}' references same-stack ECR repository '${joinResolved.repoLogicalId}' via Fn::Join. cdkd local run-task cannot resolve the repository URI without state \u2014 pass --from-state (the stack must have been deployed via cdkd deploy), build via ContainerImage.fromAsset, or pin a public image.`
|
|
77200
|
+
);
|
|
77201
|
+
}
|
|
77202
|
+
if (joinResolved.kind === "unsupported-join") {
|
|
77203
|
+
throw new EcsTaskResolutionError(
|
|
77204
|
+
`Container '${containerName}' in task '${taskLogicalId}' has an unsupported Fn::Join Image shape: ${joinResolved.reason}. cdkd local run-task recognizes the canonical CDK 2.x ContainerImage.fromEcrRepository Fn::Join shape (delimiter "" with nested Fn::Select/Fn::Split over an ECR Repository Arn GetAtt + Ref to the repo).`
|
|
77205
|
+
);
|
|
77206
|
+
}
|
|
77150
77207
|
const flat = extractImageString(raw);
|
|
77151
77208
|
if (!flat) {
|
|
77152
77209
|
throw new EcsTaskResolutionError(
|
|
@@ -77298,6 +77355,228 @@ function extractImageString(value) {
|
|
|
77298
77355
|
}
|
|
77299
77356
|
return void 0;
|
|
77300
77357
|
}
|
|
77358
|
+
function tryResolveImageFnJoin(raw, resources, context) {
|
|
77359
|
+
if (!raw || typeof raw !== "object")
|
|
77360
|
+
return { kind: "not-applicable" };
|
|
77361
|
+
const obj = raw;
|
|
77362
|
+
const arg = obj["Fn::Join"];
|
|
77363
|
+
if (arg === void 0)
|
|
77364
|
+
return { kind: "not-applicable" };
|
|
77365
|
+
if (!Array.isArray(arg) || arg.length !== 2 || !Array.isArray(arg[1])) {
|
|
77366
|
+
return { kind: "unsupported-join", reason: "Fn::Join must be [delimiter, [elements]]" };
|
|
77367
|
+
}
|
|
77368
|
+
const [delimiter, elements] = arg;
|
|
77369
|
+
if (typeof delimiter !== "string") {
|
|
77370
|
+
return {
|
|
77371
|
+
kind: "unsupported-join",
|
|
77372
|
+
reason: `Fn::Join delimiter must be a string, got ${typeof delimiter}`
|
|
77373
|
+
};
|
|
77374
|
+
}
|
|
77375
|
+
const repoLogicalId = findEcrRepositoryRefInTree(elements, resources);
|
|
77376
|
+
const stateResources = context?.stateResources;
|
|
77377
|
+
if (repoLogicalId && !stateResources) {
|
|
77378
|
+
return { kind: "needs-state", repoLogicalId };
|
|
77379
|
+
}
|
|
77380
|
+
const parts = [];
|
|
77381
|
+
for (const element of elements) {
|
|
77382
|
+
const r = resolveImageIntrinsic(element, resources, context);
|
|
77383
|
+
if (r === void 0) {
|
|
77384
|
+
if (!repoLogicalId)
|
|
77385
|
+
return { kind: "not-applicable" };
|
|
77386
|
+
return {
|
|
77387
|
+
kind: "unsupported-join",
|
|
77388
|
+
reason: "one or more Fn::Join elements could not be resolved"
|
|
77389
|
+
};
|
|
77390
|
+
}
|
|
77391
|
+
parts.push(r);
|
|
77392
|
+
}
|
|
77393
|
+
return { kind: "resolved", uri: parts.join(delimiter) };
|
|
77394
|
+
}
|
|
77395
|
+
function findEcrRepositoryRefInTree(node, resources) {
|
|
77396
|
+
if (node === null || node === void 0)
|
|
77397
|
+
return void 0;
|
|
77398
|
+
if (typeof node === "string" || typeof node === "number" || typeof node === "boolean") {
|
|
77399
|
+
return void 0;
|
|
77400
|
+
}
|
|
77401
|
+
if (Array.isArray(node)) {
|
|
77402
|
+
for (const item of node) {
|
|
77403
|
+
const hit = findEcrRepositoryRefInTree(item, resources);
|
|
77404
|
+
if (hit)
|
|
77405
|
+
return hit;
|
|
77406
|
+
}
|
|
77407
|
+
return void 0;
|
|
77408
|
+
}
|
|
77409
|
+
if (typeof node !== "object")
|
|
77410
|
+
return void 0;
|
|
77411
|
+
const obj = node;
|
|
77412
|
+
if (typeof obj["Ref"] === "string") {
|
|
77413
|
+
const target = obj["Ref"];
|
|
77414
|
+
if (resources[target]?.Type === "AWS::ECR::Repository")
|
|
77415
|
+
return target;
|
|
77416
|
+
return void 0;
|
|
77417
|
+
}
|
|
77418
|
+
const getAtt = obj["Fn::GetAtt"];
|
|
77419
|
+
if (getAtt !== void 0) {
|
|
77420
|
+
let lid;
|
|
77421
|
+
if (Array.isArray(getAtt) && typeof getAtt[0] === "string")
|
|
77422
|
+
lid = getAtt[0];
|
|
77423
|
+
else if (typeof getAtt === "string")
|
|
77424
|
+
lid = getAtt.split(".")[0];
|
|
77425
|
+
if (lid && resources[lid]?.Type === "AWS::ECR::Repository")
|
|
77426
|
+
return lid;
|
|
77427
|
+
return void 0;
|
|
77428
|
+
}
|
|
77429
|
+
for (const value of Object.values(obj)) {
|
|
77430
|
+
const hit = findEcrRepositoryRefInTree(value, resources);
|
|
77431
|
+
if (hit)
|
|
77432
|
+
return hit;
|
|
77433
|
+
}
|
|
77434
|
+
return void 0;
|
|
77435
|
+
}
|
|
77436
|
+
function resolveImageIntrinsic(node, resources, context) {
|
|
77437
|
+
const v = resolveImageIntrinsicAny(node, resources, context);
|
|
77438
|
+
if (typeof v === "string")
|
|
77439
|
+
return v;
|
|
77440
|
+
if (typeof v === "number" || typeof v === "boolean")
|
|
77441
|
+
return String(v);
|
|
77442
|
+
return void 0;
|
|
77443
|
+
}
|
|
77444
|
+
function resolveImageIntrinsicAny(node, resources, context) {
|
|
77445
|
+
if (node === null || node === void 0)
|
|
77446
|
+
return void 0;
|
|
77447
|
+
if (typeof node === "string" || typeof node === "number" || typeof node === "boolean") {
|
|
77448
|
+
return node;
|
|
77449
|
+
}
|
|
77450
|
+
if (Array.isArray(node)) {
|
|
77451
|
+
return void 0;
|
|
77452
|
+
}
|
|
77453
|
+
if (typeof node !== "object")
|
|
77454
|
+
return void 0;
|
|
77455
|
+
const obj = node;
|
|
77456
|
+
const keys = Object.keys(obj);
|
|
77457
|
+
if (keys.length !== 1)
|
|
77458
|
+
return void 0;
|
|
77459
|
+
const intrinsic = keys[0];
|
|
77460
|
+
const arg = obj[intrinsic];
|
|
77461
|
+
if (intrinsic === "Ref") {
|
|
77462
|
+
if (typeof arg !== "string")
|
|
77463
|
+
return void 0;
|
|
77464
|
+
if (arg.startsWith("AWS::")) {
|
|
77465
|
+
const p = context?.pseudoParameters;
|
|
77466
|
+
if (!p)
|
|
77467
|
+
return void 0;
|
|
77468
|
+
if (arg === "AWS::URLSuffix")
|
|
77469
|
+
return p.urlSuffix;
|
|
77470
|
+
if (arg === "AWS::Partition")
|
|
77471
|
+
return p.partition;
|
|
77472
|
+
if (arg === "AWS::Region")
|
|
77473
|
+
return p.region;
|
|
77474
|
+
if (arg === "AWS::AccountId")
|
|
77475
|
+
return p.accountId;
|
|
77476
|
+
return void 0;
|
|
77477
|
+
}
|
|
77478
|
+
const refResource = resources[arg];
|
|
77479
|
+
if (refResource?.Type !== "AWS::ECR::Repository")
|
|
77480
|
+
return void 0;
|
|
77481
|
+
const stateEntry = context?.stateResources?.[arg];
|
|
77482
|
+
if (!stateEntry)
|
|
77483
|
+
return void 0;
|
|
77484
|
+
return stateEntry.physicalId;
|
|
77485
|
+
}
|
|
77486
|
+
if (intrinsic === "Fn::GetAtt") {
|
|
77487
|
+
let logicalId;
|
|
77488
|
+
let attr;
|
|
77489
|
+
if (Array.isArray(arg) && arg.length === 2 && typeof arg[0] === "string" && typeof arg[1] === "string") {
|
|
77490
|
+
logicalId = arg[0];
|
|
77491
|
+
attr = arg[1];
|
|
77492
|
+
} else if (typeof arg === "string") {
|
|
77493
|
+
const dot = arg.indexOf(".");
|
|
77494
|
+
if (dot > 0 && dot < arg.length - 1) {
|
|
77495
|
+
logicalId = arg.slice(0, dot);
|
|
77496
|
+
attr = arg.slice(dot + 1);
|
|
77497
|
+
}
|
|
77498
|
+
}
|
|
77499
|
+
if (!logicalId || !attr)
|
|
77500
|
+
return void 0;
|
|
77501
|
+
if (resources[logicalId]?.Type !== "AWS::ECR::Repository")
|
|
77502
|
+
return void 0;
|
|
77503
|
+
const cached = context?.stateResources?.[logicalId]?.attributes?.[attr];
|
|
77504
|
+
if (typeof cached === "string" && cached.length > 0)
|
|
77505
|
+
return cached;
|
|
77506
|
+
return void 0;
|
|
77507
|
+
}
|
|
77508
|
+
if (intrinsic === "Fn::Split") {
|
|
77509
|
+
if (!Array.isArray(arg) || arg.length !== 2)
|
|
77510
|
+
return void 0;
|
|
77511
|
+
const argArr = arg;
|
|
77512
|
+
const delim = argArr[0];
|
|
77513
|
+
if (typeof delim !== "string")
|
|
77514
|
+
return void 0;
|
|
77515
|
+
const src = resolveImageIntrinsicAny(argArr[1], resources, context);
|
|
77516
|
+
if (typeof src !== "string")
|
|
77517
|
+
return void 0;
|
|
77518
|
+
return src.split(delim);
|
|
77519
|
+
}
|
|
77520
|
+
if (intrinsic === "Fn::Select") {
|
|
77521
|
+
if (!Array.isArray(arg) || arg.length !== 2)
|
|
77522
|
+
return void 0;
|
|
77523
|
+
const argArr = arg;
|
|
77524
|
+
const rawIndex = argArr[0];
|
|
77525
|
+
let index;
|
|
77526
|
+
if (typeof rawIndex === "number") {
|
|
77527
|
+
index = rawIndex;
|
|
77528
|
+
} else if (typeof rawIndex === "string" && /^-?\d+$/.test(rawIndex)) {
|
|
77529
|
+
index = Number.parseInt(rawIndex, 10);
|
|
77530
|
+
}
|
|
77531
|
+
if (index === void 0 || !Number.isFinite(index))
|
|
77532
|
+
return void 0;
|
|
77533
|
+
const list = resolveImageIntrinsicAny(argArr[1], resources, context);
|
|
77534
|
+
if (Array.isArray(list)) {
|
|
77535
|
+
if (index < 0 || index >= list.length)
|
|
77536
|
+
return void 0;
|
|
77537
|
+
const picked = list[index];
|
|
77538
|
+
if (typeof picked === "string")
|
|
77539
|
+
return picked;
|
|
77540
|
+
return void 0;
|
|
77541
|
+
}
|
|
77542
|
+
if (Array.isArray(argArr[1])) {
|
|
77543
|
+
const listLiteral = argArr[1];
|
|
77544
|
+
if (index < 0 || index >= listLiteral.length)
|
|
77545
|
+
return void 0;
|
|
77546
|
+
return resolveImageIntrinsic(listLiteral[index], resources, context);
|
|
77547
|
+
}
|
|
77548
|
+
return void 0;
|
|
77549
|
+
}
|
|
77550
|
+
if (intrinsic === "Fn::Join") {
|
|
77551
|
+
if (!Array.isArray(arg) || arg.length !== 2)
|
|
77552
|
+
return void 0;
|
|
77553
|
+
const [delim, parts] = arg;
|
|
77554
|
+
if (typeof delim !== "string" || !Array.isArray(parts))
|
|
77555
|
+
return void 0;
|
|
77556
|
+
const resolved = [];
|
|
77557
|
+
for (const part of parts) {
|
|
77558
|
+
const r = resolveImageIntrinsic(part, resources, context);
|
|
77559
|
+
if (r === void 0)
|
|
77560
|
+
return void 0;
|
|
77561
|
+
resolved.push(r);
|
|
77562
|
+
}
|
|
77563
|
+
return resolved.join(delim);
|
|
77564
|
+
}
|
|
77565
|
+
if (intrinsic === "Fn::Sub") {
|
|
77566
|
+
let template;
|
|
77567
|
+
if (typeof arg === "string")
|
|
77568
|
+
template = arg;
|
|
77569
|
+
else if (Array.isArray(arg) && typeof arg[0] === "string")
|
|
77570
|
+
template = arg[0];
|
|
77571
|
+
if (template === void 0)
|
|
77572
|
+
return void 0;
|
|
77573
|
+
const out = substituteImagePlaceholders(template, resources, context);
|
|
77574
|
+
if (out.includes("${"))
|
|
77575
|
+
return void 0;
|
|
77576
|
+
return out;
|
|
77577
|
+
}
|
|
77578
|
+
return void 0;
|
|
77579
|
+
}
|
|
77301
77580
|
function parseVolume(raw, idx, taskLogicalId) {
|
|
77302
77581
|
if (!raw || typeof raw !== "object") {
|
|
77303
77582
|
throw new EcsTaskResolutionError(`Task '${taskLogicalId}' Volumes[${idx}] is not an object.`);
|
|
@@ -79038,6 +79317,38 @@ var PRIMARY_IDENTIFIER_FALLBACK = {
|
|
|
79038
79317
|
"AWS::Cognito::UserPool": "UserPoolId",
|
|
79039
79318
|
"AWS::ECR::Repository": "RepositoryName"
|
|
79040
79319
|
};
|
|
79320
|
+
var COMPOSITE_ID_SPLITTERS = {
|
|
79321
|
+
// cdkd stores `restApiId|resourceId|httpMethod` (apigateway-provider.ts);
|
|
79322
|
+
// CFn primary identifier is [RestApiId, ResourceId, HttpMethod] — same order.
|
|
79323
|
+
"AWS::ApiGateway::Method": (id) => {
|
|
79324
|
+
const parts = id.split("|");
|
|
79325
|
+
if (parts.length !== 3) {
|
|
79326
|
+
throw new Error(
|
|
79327
|
+
`expected 3 parts (restApiId|resourceId|httpMethod), got ${parts.length}: '${id}'`
|
|
79328
|
+
);
|
|
79329
|
+
}
|
|
79330
|
+
return { RestApiId: parts[0], ResourceId: parts[1], HttpMethod: parts[2] };
|
|
79331
|
+
},
|
|
79332
|
+
// cdkd stores `restApiId|resourceId` (apigateway-provider.ts);
|
|
79333
|
+
// CFn primary identifier is [RestApiId, ResourceId].
|
|
79334
|
+
"AWS::ApiGateway::Resource": (id) => {
|
|
79335
|
+
const parts = id.split("|");
|
|
79336
|
+
if (parts.length !== 2) {
|
|
79337
|
+
throw new Error(`expected 2 parts (restApiId|resourceId), got ${parts.length}: '${id}'`);
|
|
79338
|
+
}
|
|
79339
|
+
return { RestApiId: parts[0], ResourceId: parts[1] };
|
|
79340
|
+
},
|
|
79341
|
+
// cdkd stores `IGW|VpcId` (ec2-provider.ts);
|
|
79342
|
+
// CFn primary identifier is [VpcId, InternetGatewayId] — DIFFERENT order
|
|
79343
|
+
// from cdkd. Splitter reorders explicitly.
|
|
79344
|
+
"AWS::EC2::VPCGatewayAttachment": (id) => {
|
|
79345
|
+
const parts = id.split("|");
|
|
79346
|
+
if (parts.length !== 2) {
|
|
79347
|
+
throw new Error(`expected 2 parts (IGW|VpcId), got ${parts.length}: '${id}'`);
|
|
79348
|
+
}
|
|
79349
|
+
return { VpcId: parts[1], InternetGatewayId: parts[0] };
|
|
79350
|
+
}
|
|
79351
|
+
};
|
|
79041
79352
|
async function exportCommand(stackArg, options) {
|
|
79042
79353
|
const logger = getLogger();
|
|
79043
79354
|
if (options.verbose) {
|
|
@@ -79308,14 +79619,19 @@ async function buildImportPlan(state, template, cfnClient) {
|
|
|
79308
79619
|
});
|
|
79309
79620
|
continue;
|
|
79310
79621
|
}
|
|
79311
|
-
let
|
|
79622
|
+
let resourceIdentifier;
|
|
79312
79623
|
try {
|
|
79313
|
-
|
|
79624
|
+
resourceIdentifier = await resolveResourceIdentifier(
|
|
79625
|
+
resourceType,
|
|
79626
|
+
stateEntry.physicalId,
|
|
79627
|
+
cfnClient,
|
|
79628
|
+
identifierCache
|
|
79629
|
+
);
|
|
79314
79630
|
} catch (err) {
|
|
79315
79631
|
skipped.push({
|
|
79316
79632
|
logicalId,
|
|
79317
79633
|
resourceType,
|
|
79318
|
-
reason: "could not resolve
|
|
79634
|
+
reason: "could not resolve resource identifier: " + (err instanceof Error ? err.message : String(err))
|
|
79319
79635
|
});
|
|
79320
79636
|
continue;
|
|
79321
79637
|
}
|
|
@@ -79323,15 +79639,44 @@ async function buildImportPlan(state, template, cfnClient) {
|
|
|
79323
79639
|
logicalId,
|
|
79324
79640
|
resourceType,
|
|
79325
79641
|
physicalId: stateEntry.physicalId,
|
|
79326
|
-
|
|
79642
|
+
resourceIdentifier
|
|
79327
79643
|
});
|
|
79328
79644
|
}
|
|
79329
79645
|
return { plan, skipped };
|
|
79330
79646
|
}
|
|
79331
|
-
async function
|
|
79332
|
-
|
|
79333
|
-
if (
|
|
79334
|
-
|
|
79647
|
+
async function resolveResourceIdentifier(resourceType, physicalId, cfnClient, cache2) {
|
|
79648
|
+
let entry = cache2.get(resourceType);
|
|
79649
|
+
if (entry === void 0) {
|
|
79650
|
+
entry = await fetchPrimaryIdentifier(resourceType, cfnClient);
|
|
79651
|
+
cache2.set(resourceType, entry);
|
|
79652
|
+
}
|
|
79653
|
+
if (entry.fields.length === 1) {
|
|
79654
|
+
return { [entry.fields[0]]: physicalId };
|
|
79655
|
+
}
|
|
79656
|
+
const splitter = COMPOSITE_ID_SPLITTERS[resourceType];
|
|
79657
|
+
if (!splitter) {
|
|
79658
|
+
throw new Error(
|
|
79659
|
+
`resource type uses a composite primary identifier (${entry.fields.length} fields: ${entry.fields.join(", ")}); add an entry to COMPOSITE_ID_SPLITTERS in src/cli/commands/export.ts that parses cdkd's physicalId for this type, or destroy the resource first and let CFn create it fresh`
|
|
79660
|
+
);
|
|
79661
|
+
}
|
|
79662
|
+
let split;
|
|
79663
|
+
try {
|
|
79664
|
+
split = splitter(physicalId);
|
|
79665
|
+
} catch (err) {
|
|
79666
|
+
throw new Error(
|
|
79667
|
+
`composite-id splitter for ${resourceType} failed: ` + (err instanceof Error ? err.message : String(err))
|
|
79668
|
+
);
|
|
79669
|
+
}
|
|
79670
|
+
for (const f of entry.fields) {
|
|
79671
|
+
if (!(f in split)) {
|
|
79672
|
+
throw new Error(
|
|
79673
|
+
`composite-id splitter for ${resourceType} did not produce field '${f}' (produced: ${Object.keys(split).join(", ")})`
|
|
79674
|
+
);
|
|
79675
|
+
}
|
|
79676
|
+
}
|
|
79677
|
+
return split;
|
|
79678
|
+
}
|
|
79679
|
+
async function fetchPrimaryIdentifier(resourceType, cfnClient) {
|
|
79335
79680
|
try {
|
|
79336
79681
|
const resp = await cfnClient.send(
|
|
79337
79682
|
new DescribeTypeCommand({ Type: "RESOURCE", TypeName: resourceType })
|
|
@@ -79339,15 +79684,9 @@ async function resolvePrimaryIdentifier(resourceType, cfnClient, cache2) {
|
|
|
79339
79684
|
if (resp.Schema) {
|
|
79340
79685
|
const parsed = JSON.parse(resp.Schema);
|
|
79341
79686
|
const primary = parsed.primaryIdentifier;
|
|
79342
|
-
if (Array.isArray(primary) && primary.length
|
|
79343
|
-
const
|
|
79344
|
-
|
|
79345
|
-
return propName;
|
|
79346
|
-
}
|
|
79347
|
-
if (Array.isArray(primary) && primary.length > 1) {
|
|
79348
|
-
throw new Error(
|
|
79349
|
-
`resource type uses a composite primary identifier (${primary.length} fields); cdkd does not yet support composite identifiers for cdkd export`
|
|
79350
|
-
);
|
|
79687
|
+
if (Array.isArray(primary) && primary.length > 0 && primary.every((p) => typeof p === "string")) {
|
|
79688
|
+
const fields = primary.map((p) => p.replace(/^\/properties\//, ""));
|
|
79689
|
+
return { fields };
|
|
79351
79690
|
}
|
|
79352
79691
|
}
|
|
79353
79692
|
} catch (err) {
|
|
@@ -79356,8 +79695,7 @@ async function resolvePrimaryIdentifier(resourceType, cfnClient, cache2) {
|
|
|
79356
79695
|
}
|
|
79357
79696
|
const fallback = PRIMARY_IDENTIFIER_FALLBACK[resourceType];
|
|
79358
79697
|
if (fallback) {
|
|
79359
|
-
|
|
79360
|
-
return fallback;
|
|
79698
|
+
return { fields: [fallback] };
|
|
79361
79699
|
}
|
|
79362
79700
|
throw new Error(
|
|
79363
79701
|
`primary identifier unknown (DescribeType returned no usable schema and no fallback is registered). Add ${resourceType} to PRIMARY_IDENTIFIER_FALLBACK in export.ts, or open an issue.`
|
|
@@ -79417,9 +79755,8 @@ function printPlan(plan, cfnStackName) {
|
|
|
79417
79755
|
logger.info("");
|
|
79418
79756
|
logger.info(`Import plan for CloudFormation stack '${cfnStackName}':`);
|
|
79419
79757
|
for (const entry of plan) {
|
|
79420
|
-
|
|
79421
|
-
|
|
79422
|
-
);
|
|
79758
|
+
const idStr = Object.entries(entry.resourceIdentifier).map(([k, v]) => `${k}=${v}`).join(", ");
|
|
79759
|
+
logger.info(` ${entry.logicalId} (${entry.resourceType}) \u2190 ${idStr}`);
|
|
79423
79760
|
}
|
|
79424
79761
|
logger.info("");
|
|
79425
79762
|
}
|
|
@@ -79430,7 +79767,7 @@ async function executeImportChangeSet(cfnClient, stackName, template, plan) {
|
|
|
79430
79767
|
const resourcesToImport = plan.map((entry) => ({
|
|
79431
79768
|
ResourceType: entry.resourceType,
|
|
79432
79769
|
LogicalResourceId: entry.logicalId,
|
|
79433
|
-
ResourceIdentifier:
|
|
79770
|
+
ResourceIdentifier: entry.resourceIdentifier
|
|
79434
79771
|
}));
|
|
79435
79772
|
logger.info(
|
|
79436
79773
|
`Creating IMPORT changeset '${changeSetName}' for stack '${stackName}' (${plan.length} resource(s), ${templateBody.length} bytes)...`
|
|
@@ -79601,7 +79938,7 @@ function reorderArgs(argv) {
|
|
|
79601
79938
|
}
|
|
79602
79939
|
async function main() {
|
|
79603
79940
|
const program = new Command18();
|
|
79604
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.
|
|
79941
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.86.0");
|
|
79605
79942
|
program.addCommand(createBootstrapCommand());
|
|
79606
79943
|
program.addCommand(createSynthCommand());
|
|
79607
79944
|
program.addCommand(createListCommand());
|