@go-to-k/cdkd 0.68.0 → 0.70.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 +18 -0
- package/dist/cli.js +976 -146
- package/dist/cli.js.map +4 -4
- package/dist/go-to-k-cdkd-0.70.0.tgz +0 -0
- package/dist/index.js +56 -34
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
- package/dist/go-to-k-cdkd-0.68.0.tgz +0 -0
package/dist/cli.js
CHANGED
|
@@ -4374,16 +4374,16 @@ var require_printer = __commonJS({
|
|
|
4374
4374
|
},
|
|
4375
4375
|
// Document
|
|
4376
4376
|
Document: {
|
|
4377
|
-
leave: (node) =>
|
|
4377
|
+
leave: (node) => join8(node.definitions, "\n\n")
|
|
4378
4378
|
},
|
|
4379
4379
|
OperationDefinition: {
|
|
4380
4380
|
leave(node) {
|
|
4381
|
-
const varDefs = hasMultilineItems(node.variableDefinitions) ? wrap("(\n",
|
|
4382
|
-
const prefix = wrap("", node.description, "\n") +
|
|
4381
|
+
const varDefs = hasMultilineItems(node.variableDefinitions) ? wrap("(\n", join8(node.variableDefinitions, "\n"), "\n)") : wrap("(", join8(node.variableDefinitions, ", "), ")");
|
|
4382
|
+
const prefix = wrap("", node.description, "\n") + join8(
|
|
4383
4383
|
[
|
|
4384
4384
|
node.operation,
|
|
4385
|
-
|
|
4386
|
-
|
|
4385
|
+
join8([node.name, varDefs]),
|
|
4386
|
+
join8(node.directives, " ")
|
|
4387
4387
|
],
|
|
4388
4388
|
" "
|
|
4389
4389
|
);
|
|
@@ -4391,7 +4391,7 @@ var require_printer = __commonJS({
|
|
|
4391
4391
|
}
|
|
4392
4392
|
},
|
|
4393
4393
|
VariableDefinition: {
|
|
4394
|
-
leave: ({ variable, type, defaultValue, directives, description }) => wrap("", description, "\n") + variable + ": " + type + wrap(" = ", defaultValue) + wrap(" ",
|
|
4394
|
+
leave: ({ variable, type, defaultValue, directives, description }) => wrap("", description, "\n") + variable + ": " + type + wrap(" = ", defaultValue) + wrap(" ", join8(directives, " "))
|
|
4395
4395
|
},
|
|
4396
4396
|
SelectionSet: {
|
|
4397
4397
|
leave: ({ selections }) => block(selections)
|
|
@@ -4399,11 +4399,11 @@ var require_printer = __commonJS({
|
|
|
4399
4399
|
Field: {
|
|
4400
4400
|
leave({ alias, name, arguments: args, directives, selectionSet }) {
|
|
4401
4401
|
const prefix = wrap("", alias, ": ") + name;
|
|
4402
|
-
let argsLine = prefix + wrap("(",
|
|
4402
|
+
let argsLine = prefix + wrap("(", join8(args, ", "), ")");
|
|
4403
4403
|
if (argsLine.length > MAX_LINE_LENGTH) {
|
|
4404
|
-
argsLine = prefix + wrap("(\n", indent(
|
|
4404
|
+
argsLine = prefix + wrap("(\n", indent(join8(args, "\n")), "\n)");
|
|
4405
4405
|
}
|
|
4406
|
-
return
|
|
4406
|
+
return join8([argsLine, join8(directives, " "), selectionSet], " ");
|
|
4407
4407
|
}
|
|
4408
4408
|
},
|
|
4409
4409
|
Argument: {
|
|
@@ -4411,14 +4411,14 @@ var require_printer = __commonJS({
|
|
|
4411
4411
|
},
|
|
4412
4412
|
// Fragments
|
|
4413
4413
|
FragmentSpread: {
|
|
4414
|
-
leave: ({ name, directives }) => "..." + name + wrap(" ",
|
|
4414
|
+
leave: ({ name, directives }) => "..." + name + wrap(" ", join8(directives, " "))
|
|
4415
4415
|
},
|
|
4416
4416
|
InlineFragment: {
|
|
4417
|
-
leave: ({ typeCondition, directives, selectionSet }) =>
|
|
4417
|
+
leave: ({ typeCondition, directives, selectionSet }) => join8(
|
|
4418
4418
|
[
|
|
4419
4419
|
"...",
|
|
4420
4420
|
wrap("on ", typeCondition),
|
|
4421
|
-
|
|
4421
|
+
join8(directives, " "),
|
|
4422
4422
|
selectionSet
|
|
4423
4423
|
],
|
|
4424
4424
|
" "
|
|
@@ -4434,7 +4434,7 @@ var require_printer = __commonJS({
|
|
|
4434
4434
|
description
|
|
4435
4435
|
}) => wrap("", description, "\n") + // Note: fragment variable definitions are experimental and may be changed
|
|
4436
4436
|
// or removed in the future.
|
|
4437
|
-
`fragment ${name}${wrap("(",
|
|
4437
|
+
`fragment ${name}${wrap("(", join8(variableDefinitions, ", "), ")")} on ${typeCondition} ${wrap("", join8(directives, " "), " ")}` + selectionSet
|
|
4438
4438
|
},
|
|
4439
4439
|
// Value
|
|
4440
4440
|
IntValue: {
|
|
@@ -4456,17 +4456,17 @@ var require_printer = __commonJS({
|
|
|
4456
4456
|
leave: ({ value }) => value
|
|
4457
4457
|
},
|
|
4458
4458
|
ListValue: {
|
|
4459
|
-
leave: ({ values }) => "[" +
|
|
4459
|
+
leave: ({ values }) => "[" + join8(values, ", ") + "]"
|
|
4460
4460
|
},
|
|
4461
4461
|
ObjectValue: {
|
|
4462
|
-
leave: ({ fields }) => "{" +
|
|
4462
|
+
leave: ({ fields }) => "{" + join8(fields, ", ") + "}"
|
|
4463
4463
|
},
|
|
4464
4464
|
ObjectField: {
|
|
4465
4465
|
leave: ({ name, value }) => name + ": " + value
|
|
4466
4466
|
},
|
|
4467
4467
|
// Directive
|
|
4468
4468
|
Directive: {
|
|
4469
|
-
leave: ({ name, arguments: args }) => "@" + name + wrap("(",
|
|
4469
|
+
leave: ({ name, arguments: args }) => "@" + name + wrap("(", join8(args, ", "), ")")
|
|
4470
4470
|
},
|
|
4471
4471
|
// Type
|
|
4472
4472
|
NamedType: {
|
|
@@ -4480,61 +4480,61 @@ var require_printer = __commonJS({
|
|
|
4480
4480
|
},
|
|
4481
4481
|
// Type System Definitions
|
|
4482
4482
|
SchemaDefinition: {
|
|
4483
|
-
leave: ({ description, directives, operationTypes }) => wrap("", description, "\n") +
|
|
4483
|
+
leave: ({ description, directives, operationTypes }) => wrap("", description, "\n") + join8(["schema", join8(directives, " "), block(operationTypes)], " ")
|
|
4484
4484
|
},
|
|
4485
4485
|
OperationTypeDefinition: {
|
|
4486
4486
|
leave: ({ operation, type }) => operation + ": " + type
|
|
4487
4487
|
},
|
|
4488
4488
|
ScalarTypeDefinition: {
|
|
4489
|
-
leave: ({ description, name, directives }) => wrap("", description, "\n") +
|
|
4489
|
+
leave: ({ description, name, directives }) => wrap("", description, "\n") + join8(["scalar", name, join8(directives, " ")], " ")
|
|
4490
4490
|
},
|
|
4491
4491
|
ObjectTypeDefinition: {
|
|
4492
|
-
leave: ({ description, name, interfaces, directives, fields }) => wrap("", description, "\n") +
|
|
4492
|
+
leave: ({ description, name, interfaces, directives, fields }) => wrap("", description, "\n") + join8(
|
|
4493
4493
|
[
|
|
4494
4494
|
"type",
|
|
4495
4495
|
name,
|
|
4496
|
-
wrap("implements ",
|
|
4497
|
-
|
|
4496
|
+
wrap("implements ", join8(interfaces, " & ")),
|
|
4497
|
+
join8(directives, " "),
|
|
4498
4498
|
block(fields)
|
|
4499
4499
|
],
|
|
4500
4500
|
" "
|
|
4501
4501
|
)
|
|
4502
4502
|
},
|
|
4503
4503
|
FieldDefinition: {
|
|
4504
|
-
leave: ({ description, name, arguments: args, type, directives }) => wrap("", description, "\n") + name + (hasMultilineItems(args) ? wrap("(\n", indent(
|
|
4504
|
+
leave: ({ description, name, arguments: args, type, directives }) => wrap("", description, "\n") + name + (hasMultilineItems(args) ? wrap("(\n", indent(join8(args, "\n")), "\n)") : wrap("(", join8(args, ", "), ")")) + ": " + type + wrap(" ", join8(directives, " "))
|
|
4505
4505
|
},
|
|
4506
4506
|
InputValueDefinition: {
|
|
4507
|
-
leave: ({ description, name, type, defaultValue, directives }) => wrap("", description, "\n") +
|
|
4508
|
-
[name + ": " + type, wrap("= ", defaultValue),
|
|
4507
|
+
leave: ({ description, name, type, defaultValue, directives }) => wrap("", description, "\n") + join8(
|
|
4508
|
+
[name + ": " + type, wrap("= ", defaultValue), join8(directives, " ")],
|
|
4509
4509
|
" "
|
|
4510
4510
|
)
|
|
4511
4511
|
},
|
|
4512
4512
|
InterfaceTypeDefinition: {
|
|
4513
|
-
leave: ({ description, name, interfaces, directives, fields }) => wrap("", description, "\n") +
|
|
4513
|
+
leave: ({ description, name, interfaces, directives, fields }) => wrap("", description, "\n") + join8(
|
|
4514
4514
|
[
|
|
4515
4515
|
"interface",
|
|
4516
4516
|
name,
|
|
4517
|
-
wrap("implements ",
|
|
4518
|
-
|
|
4517
|
+
wrap("implements ", join8(interfaces, " & ")),
|
|
4518
|
+
join8(directives, " "),
|
|
4519
4519
|
block(fields)
|
|
4520
4520
|
],
|
|
4521
4521
|
" "
|
|
4522
4522
|
)
|
|
4523
4523
|
},
|
|
4524
4524
|
UnionTypeDefinition: {
|
|
4525
|
-
leave: ({ description, name, directives, types }) => wrap("", description, "\n") +
|
|
4526
|
-
["union", name,
|
|
4525
|
+
leave: ({ description, name, directives, types }) => wrap("", description, "\n") + join8(
|
|
4526
|
+
["union", name, join8(directives, " "), wrap("= ", join8(types, " | "))],
|
|
4527
4527
|
" "
|
|
4528
4528
|
)
|
|
4529
4529
|
},
|
|
4530
4530
|
EnumTypeDefinition: {
|
|
4531
|
-
leave: ({ description, name, directives, values }) => wrap("", description, "\n") +
|
|
4531
|
+
leave: ({ description, name, directives, values }) => wrap("", description, "\n") + join8(["enum", name, join8(directives, " "), block(values)], " ")
|
|
4532
4532
|
},
|
|
4533
4533
|
EnumValueDefinition: {
|
|
4534
|
-
leave: ({ description, name, directives }) => wrap("", description, "\n") +
|
|
4534
|
+
leave: ({ description, name, directives }) => wrap("", description, "\n") + join8([name, join8(directives, " ")], " ")
|
|
4535
4535
|
},
|
|
4536
4536
|
InputObjectTypeDefinition: {
|
|
4537
|
-
leave: ({ description, name, directives, fields }) => wrap("", description, "\n") +
|
|
4537
|
+
leave: ({ description, name, directives, fields }) => wrap("", description, "\n") + join8(["input", name, join8(directives, " "), block(fields)], " ")
|
|
4538
4538
|
},
|
|
4539
4539
|
DirectiveDefinition: {
|
|
4540
4540
|
leave: ({
|
|
@@ -4544,84 +4544,84 @@ var require_printer = __commonJS({
|
|
|
4544
4544
|
directives,
|
|
4545
4545
|
repeatable,
|
|
4546
4546
|
locations
|
|
4547
|
-
}) => wrap("", description, "\n") + "directive @" + name + (hasMultilineItems(args) ? wrap("(\n", indent(
|
|
4547
|
+
}) => wrap("", description, "\n") + "directive @" + name + (hasMultilineItems(args) ? wrap("(\n", indent(join8(args, "\n")), "\n)") : wrap("(", join8(args, ", "), ")")) + wrap(" ", join8(directives, " ")) + (repeatable ? " repeatable" : "") + " on " + join8(locations, " | ")
|
|
4548
4548
|
},
|
|
4549
4549
|
SchemaExtension: {
|
|
4550
|
-
leave: ({ directives, operationTypes }) =>
|
|
4551
|
-
["extend schema",
|
|
4550
|
+
leave: ({ directives, operationTypes }) => join8(
|
|
4551
|
+
["extend schema", join8(directives, " "), block(operationTypes)],
|
|
4552
4552
|
" "
|
|
4553
4553
|
)
|
|
4554
4554
|
},
|
|
4555
4555
|
ScalarTypeExtension: {
|
|
4556
|
-
leave: ({ name, directives }) =>
|
|
4556
|
+
leave: ({ name, directives }) => join8(["extend scalar", name, join8(directives, " ")], " ")
|
|
4557
4557
|
},
|
|
4558
4558
|
ObjectTypeExtension: {
|
|
4559
|
-
leave: ({ name, interfaces, directives, fields }) =>
|
|
4559
|
+
leave: ({ name, interfaces, directives, fields }) => join8(
|
|
4560
4560
|
[
|
|
4561
4561
|
"extend type",
|
|
4562
4562
|
name,
|
|
4563
|
-
wrap("implements ",
|
|
4564
|
-
|
|
4563
|
+
wrap("implements ", join8(interfaces, " & ")),
|
|
4564
|
+
join8(directives, " "),
|
|
4565
4565
|
block(fields)
|
|
4566
4566
|
],
|
|
4567
4567
|
" "
|
|
4568
4568
|
)
|
|
4569
4569
|
},
|
|
4570
4570
|
InterfaceTypeExtension: {
|
|
4571
|
-
leave: ({ name, interfaces, directives, fields }) =>
|
|
4571
|
+
leave: ({ name, interfaces, directives, fields }) => join8(
|
|
4572
4572
|
[
|
|
4573
4573
|
"extend interface",
|
|
4574
4574
|
name,
|
|
4575
|
-
wrap("implements ",
|
|
4576
|
-
|
|
4575
|
+
wrap("implements ", join8(interfaces, " & ")),
|
|
4576
|
+
join8(directives, " "),
|
|
4577
4577
|
block(fields)
|
|
4578
4578
|
],
|
|
4579
4579
|
" "
|
|
4580
4580
|
)
|
|
4581
4581
|
},
|
|
4582
4582
|
UnionTypeExtension: {
|
|
4583
|
-
leave: ({ name, directives, types }) =>
|
|
4583
|
+
leave: ({ name, directives, types }) => join8(
|
|
4584
4584
|
[
|
|
4585
4585
|
"extend union",
|
|
4586
4586
|
name,
|
|
4587
|
-
|
|
4588
|
-
wrap("= ",
|
|
4587
|
+
join8(directives, " "),
|
|
4588
|
+
wrap("= ", join8(types, " | "))
|
|
4589
4589
|
],
|
|
4590
4590
|
" "
|
|
4591
4591
|
)
|
|
4592
4592
|
},
|
|
4593
4593
|
EnumTypeExtension: {
|
|
4594
|
-
leave: ({ name, directives, values }) =>
|
|
4594
|
+
leave: ({ name, directives, values }) => join8(["extend enum", name, join8(directives, " "), block(values)], " ")
|
|
4595
4595
|
},
|
|
4596
4596
|
InputObjectTypeExtension: {
|
|
4597
|
-
leave: ({ name, directives, fields }) =>
|
|
4597
|
+
leave: ({ name, directives, fields }) => join8(["extend input", name, join8(directives, " "), block(fields)], " ")
|
|
4598
4598
|
},
|
|
4599
4599
|
DirectiveExtension: {
|
|
4600
|
-
leave: ({ name, directives }) =>
|
|
4600
|
+
leave: ({ name, directives }) => join8(["extend directive @" + name, join8(directives, " ")], " ")
|
|
4601
4601
|
},
|
|
4602
4602
|
// Schema Coordinates
|
|
4603
4603
|
TypeCoordinate: {
|
|
4604
4604
|
leave: ({ name }) => name
|
|
4605
4605
|
},
|
|
4606
4606
|
MemberCoordinate: {
|
|
4607
|
-
leave: ({ name, memberName }) =>
|
|
4607
|
+
leave: ({ name, memberName }) => join8([name, wrap(".", memberName)])
|
|
4608
4608
|
},
|
|
4609
4609
|
ArgumentCoordinate: {
|
|
4610
|
-
leave: ({ name, fieldName, argumentName }) =>
|
|
4610
|
+
leave: ({ name, fieldName, argumentName }) => join8([name, wrap(".", fieldName), wrap("(", argumentName, ":)")])
|
|
4611
4611
|
},
|
|
4612
4612
|
DirectiveCoordinate: {
|
|
4613
|
-
leave: ({ name }) =>
|
|
4613
|
+
leave: ({ name }) => join8(["@", name])
|
|
4614
4614
|
},
|
|
4615
4615
|
DirectiveArgumentCoordinate: {
|
|
4616
|
-
leave: ({ name, argumentName }) =>
|
|
4616
|
+
leave: ({ name, argumentName }) => join8(["@", name, wrap("(", argumentName, ":)")])
|
|
4617
4617
|
}
|
|
4618
4618
|
};
|
|
4619
|
-
function
|
|
4619
|
+
function join8(maybeArray, separator = "") {
|
|
4620
4620
|
var _maybeArray$filter$jo;
|
|
4621
4621
|
return (_maybeArray$filter$jo = maybeArray === null || maybeArray === void 0 ? void 0 : maybeArray.filter((x) => x).join(separator)) !== null && _maybeArray$filter$jo !== void 0 ? _maybeArray$filter$jo : "";
|
|
4622
4622
|
}
|
|
4623
4623
|
function block(array) {
|
|
4624
|
-
return wrap("{\n", indent(
|
|
4624
|
+
return wrap("{\n", indent(join8(array, "\n")), "\n}");
|
|
4625
4625
|
}
|
|
4626
4626
|
function wrap(start, maybeString, end = "") {
|
|
4627
4627
|
return maybeString != null && maybeString !== "" ? start + maybeString + end : "";
|
|
@@ -18319,6 +18319,13 @@ var AssetError = class _AssetError extends CdkdError {
|
|
|
18319
18319
|
Object.setPrototypeOf(this, _AssetError.prototype);
|
|
18320
18320
|
}
|
|
18321
18321
|
};
|
|
18322
|
+
var LocalInvokeBuildError = class _LocalInvokeBuildError extends CdkdError {
|
|
18323
|
+
constructor(message, cause) {
|
|
18324
|
+
super(message, "LOCAL_INVOKE_BUILD_ERROR", cause);
|
|
18325
|
+
this.name = "LocalInvokeBuildError";
|
|
18326
|
+
Object.setPrototypeOf(this, _LocalInvokeBuildError.prototype);
|
|
18327
|
+
}
|
|
18328
|
+
};
|
|
18322
18329
|
var ProvisioningError = class _ProvisioningError extends CdkdError {
|
|
18323
18330
|
constructor(message, resourceType, logicalId, physicalId, cause) {
|
|
18324
18331
|
super(message, "PROVISIONING_ERROR", cause);
|
|
@@ -23436,11 +23443,11 @@ async function resolveStateBucketWithDefaultAndSource(cliBucket, region) {
|
|
|
23436
23443
|
return syncResult;
|
|
23437
23444
|
const logger = getLogger();
|
|
23438
23445
|
logger.debug("No state bucket specified, resolving default from account...");
|
|
23439
|
-
const { GetCallerIdentityCommand:
|
|
23446
|
+
const { GetCallerIdentityCommand: GetCallerIdentityCommand12 } = await import("@aws-sdk/client-sts");
|
|
23440
23447
|
const { S3Client: S3Client12 } = await import("@aws-sdk/client-s3");
|
|
23441
23448
|
const { getAwsClients: getAwsClients2 } = await Promise.resolve().then(() => (init_aws_clients(), aws_clients_exports));
|
|
23442
23449
|
const awsClients = getAwsClients2();
|
|
23443
|
-
const identity = await awsClients.sts.send(new
|
|
23450
|
+
const identity = await awsClients.sts.send(new GetCallerIdentityCommand12({}));
|
|
23444
23451
|
const accountId = identity.Account;
|
|
23445
23452
|
const newName = getDefaultStateBucketName(accountId);
|
|
23446
23453
|
const legacyName = getLegacyStateBucketName(accountId, region);
|
|
@@ -25322,14 +25329,57 @@ var FileAssetPublisher = class {
|
|
|
25322
25329
|
};
|
|
25323
25330
|
|
|
25324
25331
|
// src/assets/docker-asset-publisher.ts
|
|
25325
|
-
import { execFile, spawn as spawn2 } from "node:child_process";
|
|
25326
|
-
import { promisify } from "node:util";
|
|
25332
|
+
import { execFile as execFile2, spawn as spawn2 } from "node:child_process";
|
|
25333
|
+
import { promisify as promisify2 } from "node:util";
|
|
25327
25334
|
import {
|
|
25328
25335
|
ECRClient,
|
|
25329
25336
|
GetAuthorizationTokenCommand,
|
|
25330
25337
|
DescribeImagesCommand as DescribeImagesCommand2
|
|
25331
25338
|
} from "@aws-sdk/client-ecr";
|
|
25339
|
+
|
|
25340
|
+
// src/assets/docker-build.ts
|
|
25341
|
+
import { execFile } from "node:child_process";
|
|
25342
|
+
import { promisify } from "node:util";
|
|
25332
25343
|
var execFileAsync = promisify(execFile);
|
|
25344
|
+
async function buildDockerImage(asset, cdkOutDir, tag, options) {
|
|
25345
|
+
const logger = getLogger().child("docker-build");
|
|
25346
|
+
const args = ["build", "-t", tag];
|
|
25347
|
+
if (options.platform) {
|
|
25348
|
+
args.push("--platform", options.platform);
|
|
25349
|
+
}
|
|
25350
|
+
if (asset.source.dockerFile) {
|
|
25351
|
+
args.push("-f", asset.source.dockerFile);
|
|
25352
|
+
}
|
|
25353
|
+
if (asset.source.dockerBuildArgs) {
|
|
25354
|
+
for (const [key, value] of Object.entries(asset.source.dockerBuildArgs)) {
|
|
25355
|
+
args.push("--build-arg", `${key}=${value}`);
|
|
25356
|
+
}
|
|
25357
|
+
}
|
|
25358
|
+
if (asset.source.dockerBuildTarget) {
|
|
25359
|
+
args.push("--target", asset.source.dockerBuildTarget);
|
|
25360
|
+
}
|
|
25361
|
+
if (asset.source.dockerOutputs) {
|
|
25362
|
+
for (const output of asset.source.dockerOutputs) {
|
|
25363
|
+
args.push("--output", output);
|
|
25364
|
+
}
|
|
25365
|
+
}
|
|
25366
|
+
const contextDir = `${cdkOutDir}/${asset.source.directory}`;
|
|
25367
|
+
args.push(contextDir);
|
|
25368
|
+
logger.debug(`docker ${args.join(" ")}`);
|
|
25369
|
+
try {
|
|
25370
|
+
await execFileAsync("docker", args, {
|
|
25371
|
+
maxBuffer: 50 * 1024 * 1024
|
|
25372
|
+
// 50MB for build output
|
|
25373
|
+
});
|
|
25374
|
+
} catch (error) {
|
|
25375
|
+
const err = error;
|
|
25376
|
+
const stderr = err.stderr || err.message || String(error);
|
|
25377
|
+
throw options.wrapError(stderr);
|
|
25378
|
+
}
|
|
25379
|
+
}
|
|
25380
|
+
|
|
25381
|
+
// src/assets/docker-asset-publisher.ts
|
|
25382
|
+
var execFileAsync2 = promisify2(execFile2);
|
|
25333
25383
|
var DockerAssetPublisher = class {
|
|
25334
25384
|
logger = getLogger().child("DockerAssetPublisher");
|
|
25335
25385
|
/**
|
|
@@ -25412,38 +25462,17 @@ var DockerAssetPublisher = class {
|
|
|
25412
25462
|
}
|
|
25413
25463
|
}
|
|
25414
25464
|
/**
|
|
25415
|
-
* Build Docker image
|
|
25465
|
+
* Build Docker image — delegates to the shared `buildDockerImage`
|
|
25466
|
+
* helper so this code path stays in sync with `cdkd local invoke`'s
|
|
25467
|
+
* container-Lambda build path. `--platform` is currently not threaded
|
|
25468
|
+
* through here (publish-assets has no Architectures hint to consult);
|
|
25469
|
+
* a follow-up can lift this once the asset manifest carries a
|
|
25470
|
+
* platform field.
|
|
25416
25471
|
*/
|
|
25417
25472
|
async buildImage(asset, cdkOutputDir, tag) {
|
|
25418
|
-
|
|
25419
|
-
|
|
25420
|
-
|
|
25421
|
-
}
|
|
25422
|
-
if (asset.source.dockerBuildArgs) {
|
|
25423
|
-
for (const [key, value] of Object.entries(asset.source.dockerBuildArgs)) {
|
|
25424
|
-
args.push("--build-arg", `${key}=${value}`);
|
|
25425
|
-
}
|
|
25426
|
-
}
|
|
25427
|
-
if (asset.source.dockerBuildTarget) {
|
|
25428
|
-
args.push("--target", asset.source.dockerBuildTarget);
|
|
25429
|
-
}
|
|
25430
|
-
if (asset.source.dockerOutputs) {
|
|
25431
|
-
for (const output of asset.source.dockerOutputs) {
|
|
25432
|
-
args.push("--output", output);
|
|
25433
|
-
}
|
|
25434
|
-
}
|
|
25435
|
-
const contextDir = `${cdkOutputDir}/${asset.source.directory}`;
|
|
25436
|
-
args.push(contextDir);
|
|
25437
|
-
this.logger.debug(`docker ${args.join(" ")}`);
|
|
25438
|
-
try {
|
|
25439
|
-
await execFileAsync("docker", args, {
|
|
25440
|
-
maxBuffer: 50 * 1024 * 1024
|
|
25441
|
-
// 50MB for build output
|
|
25442
|
-
});
|
|
25443
|
-
} catch (error) {
|
|
25444
|
-
const err = error;
|
|
25445
|
-
throw new AssetError(`Docker build failed: ${err.stderr || err.message || String(error)}`);
|
|
25446
|
-
}
|
|
25473
|
+
await buildDockerImage(asset, cdkOutputDir, tag, {
|
|
25474
|
+
wrapError: (stderr) => new AssetError(`Docker build failed: ${stderr}`)
|
|
25475
|
+
});
|
|
25447
25476
|
}
|
|
25448
25477
|
/**
|
|
25449
25478
|
* Authenticate with ECR
|
|
@@ -25487,7 +25516,7 @@ var DockerAssetPublisher = class {
|
|
|
25487
25516
|
* Tag Docker image
|
|
25488
25517
|
*/
|
|
25489
25518
|
async tagImage(source, target) {
|
|
25490
|
-
await
|
|
25519
|
+
await execFileAsync2("docker", ["tag", source, target]);
|
|
25491
25520
|
}
|
|
25492
25521
|
/**
|
|
25493
25522
|
* Push Docker image
|
|
@@ -25495,7 +25524,7 @@ var DockerAssetPublisher = class {
|
|
|
25495
25524
|
async pushImage(uri) {
|
|
25496
25525
|
this.logger.debug(`Pushing: ${uri}`);
|
|
25497
25526
|
try {
|
|
25498
|
-
await
|
|
25527
|
+
await execFileAsync2("docker", ["push", uri], {
|
|
25499
25528
|
maxBuffer: 50 * 1024 * 1024
|
|
25500
25529
|
});
|
|
25501
25530
|
} catch (error) {
|
|
@@ -25718,9 +25747,9 @@ var AssetPublisher = class {
|
|
|
25718
25747
|
const region = options.region || process.env["AWS_REGION"] || "us-east-1";
|
|
25719
25748
|
let accountId = options.accountId;
|
|
25720
25749
|
if (!accountId) {
|
|
25721
|
-
const { STSClient:
|
|
25722
|
-
const stsClient = new
|
|
25723
|
-
const identity = await stsClient.send(new
|
|
25750
|
+
const { STSClient: STSClient11, GetCallerIdentityCommand: GetCallerIdentityCommand12 } = await import("@aws-sdk/client-sts");
|
|
25751
|
+
const stsClient = new STSClient11({ region });
|
|
25752
|
+
const identity = await stsClient.send(new GetCallerIdentityCommand12({}));
|
|
25724
25753
|
accountId = identity.Account;
|
|
25725
25754
|
stsClient.destroy();
|
|
25726
25755
|
}
|
|
@@ -65303,11 +65332,11 @@ async function deployCommand(stacks, options) {
|
|
|
65303
65332
|
addDependencies(stack.stackName);
|
|
65304
65333
|
}
|
|
65305
65334
|
}
|
|
65306
|
-
const { STSClient:
|
|
65307
|
-
const stsClient = new
|
|
65335
|
+
const { STSClient: STSClient11, GetCallerIdentityCommand: GetCallerIdentityCommand12 } = await import("@aws-sdk/client-sts");
|
|
65336
|
+
const stsClient = new STSClient11({
|
|
65308
65337
|
region: options.region || process.env["AWS_REGION"] || "us-east-1"
|
|
65309
65338
|
});
|
|
65310
|
-
const callerIdentity = await stsClient.send(new
|
|
65339
|
+
const callerIdentity = await stsClient.send(new GetCallerIdentityCommand12({}));
|
|
65311
65340
|
const accountId = callerIdentity.Account;
|
|
65312
65341
|
stsClient.destroy();
|
|
65313
65342
|
const assetPublisher = new AssetPublisher();
|
|
@@ -67780,9 +67809,9 @@ async function publishAssetsCommand(stacks, options) {
|
|
|
67780
67809
|
);
|
|
67781
67810
|
}
|
|
67782
67811
|
const baseRegion = options.region || process.env["AWS_REGION"] || "us-east-1";
|
|
67783
|
-
const { STSClient:
|
|
67784
|
-
const stsClient = new
|
|
67785
|
-
const callerIdentity = await stsClient.send(new
|
|
67812
|
+
const { STSClient: STSClient11, GetCallerIdentityCommand: GetCallerIdentityCommand12 } = await import("@aws-sdk/client-sts");
|
|
67813
|
+
const stsClient = new STSClient11({ region: baseRegion });
|
|
67814
|
+
const callerIdentity = await stsClient.send(new GetCallerIdentityCommand12({}));
|
|
67786
67815
|
const accountId = callerIdentity.Account;
|
|
67787
67816
|
stsClient.destroy();
|
|
67788
67817
|
const assetPublisher = new AssetPublisher();
|
|
@@ -69963,12 +69992,13 @@ async function captureObservedForImportedResources(stackState, providerRegistry,
|
|
|
69963
69992
|
}
|
|
69964
69993
|
|
|
69965
69994
|
// src/cli/commands/local-invoke.ts
|
|
69966
|
-
import { mkdtempSync as mkdtempSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "node:fs";
|
|
69995
|
+
import { mkdtempSync as mkdtempSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync6, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "node:fs";
|
|
69967
69996
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
69997
|
+
import { dirname as dirname2 } from "node:path";
|
|
69968
69998
|
import * as path from "node:path";
|
|
69969
69999
|
import { Command as Command14, Option as Option7 } from "commander";
|
|
69970
70000
|
|
|
69971
|
-
// src/local
|
|
70001
|
+
// src/local/lambda-resolver.ts
|
|
69972
70002
|
import { existsSync as existsSync4, statSync as statSync3 } from "node:fs";
|
|
69973
70003
|
import { dirname, isAbsolute, resolve as resolve4 } from "node:path";
|
|
69974
70004
|
var LocalInvokeResolutionError = class _LocalInvokeResolutionError extends Error {
|
|
@@ -70067,25 +70097,38 @@ function pickStack(parsed, stacks) {
|
|
|
70067
70097
|
}
|
|
70068
70098
|
function extractLambdaProperties(stack, logicalId, resource) {
|
|
70069
70099
|
const props = resource.Properties ?? {};
|
|
70070
|
-
const runtime = typeof props["Runtime"] === "string" ? props["Runtime"] : "";
|
|
70071
|
-
const handler = typeof props["Handler"] === "string" ? props["Handler"] : "";
|
|
70072
70100
|
const memoryMb = typeof props["MemorySize"] === "number" ? props["MemorySize"] : 128;
|
|
70073
70101
|
const timeoutSec = typeof props["Timeout"] === "number" ? props["Timeout"] : 3;
|
|
70102
|
+
const code = props["Code"] ?? {};
|
|
70103
|
+
const imageUri = extractImageUri(code["ImageUri"]);
|
|
70104
|
+
if (imageUri !== void 0) {
|
|
70105
|
+
return extractImageLambdaProperties({
|
|
70106
|
+
stack,
|
|
70107
|
+
logicalId,
|
|
70108
|
+
resource,
|
|
70109
|
+
memoryMb,
|
|
70110
|
+
timeoutSec,
|
|
70111
|
+
props,
|
|
70112
|
+
imageUri
|
|
70113
|
+
});
|
|
70114
|
+
}
|
|
70115
|
+
const runtime = typeof props["Runtime"] === "string" ? props["Runtime"] : "";
|
|
70116
|
+
const handler = typeof props["Handler"] === "string" ? props["Handler"] : "";
|
|
70074
70117
|
if (!runtime) {
|
|
70075
70118
|
throw new LocalInvokeResolutionError(
|
|
70076
|
-
`Lambda '${logicalId}' has no Runtime property
|
|
70119
|
+
`Lambda '${logicalId}' has no Runtime property and no Code.ImageUri. cdkd cannot tell if this is a ZIP or a container Lambda.`
|
|
70077
70120
|
);
|
|
70078
70121
|
}
|
|
70079
70122
|
if (!handler) {
|
|
70080
70123
|
throw new LocalInvokeResolutionError(`Lambda '${logicalId}' has no Handler property.`);
|
|
70081
70124
|
}
|
|
70082
|
-
const code = props["Code"] ?? {};
|
|
70083
70125
|
const inlineCode = typeof code["ZipFile"] === "string" ? code["ZipFile"] : void 0;
|
|
70084
70126
|
let codePath = null;
|
|
70085
70127
|
if (!inlineCode) {
|
|
70086
70128
|
codePath = resolveAssetCodePath(stack, logicalId, resource);
|
|
70087
70129
|
}
|
|
70088
70130
|
return {
|
|
70131
|
+
kind: "zip",
|
|
70089
70132
|
stack,
|
|
70090
70133
|
logicalId,
|
|
70091
70134
|
resource,
|
|
@@ -70097,6 +70140,62 @@ function extractLambdaProperties(stack, logicalId, resource) {
|
|
|
70097
70140
|
...inlineCode !== void 0 && { inlineCode }
|
|
70098
70141
|
};
|
|
70099
70142
|
}
|
|
70143
|
+
function extractImageUri(value) {
|
|
70144
|
+
if (typeof value === "string" && value.length > 0)
|
|
70145
|
+
return value;
|
|
70146
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
70147
|
+
const obj = value;
|
|
70148
|
+
const sub = obj["Fn::Sub"];
|
|
70149
|
+
if (typeof sub === "string" && sub.length > 0)
|
|
70150
|
+
return sub;
|
|
70151
|
+
if (Array.isArray(sub) && typeof sub[0] === "string")
|
|
70152
|
+
return sub[0];
|
|
70153
|
+
}
|
|
70154
|
+
return void 0;
|
|
70155
|
+
}
|
|
70156
|
+
function extractImageLambdaProperties(args) {
|
|
70157
|
+
const { stack, logicalId, resource, memoryMb, timeoutSec, props, imageUri } = args;
|
|
70158
|
+
const rawImageConfig = props["ImageConfig"] ?? {};
|
|
70159
|
+
const imageConfig = {};
|
|
70160
|
+
if (Array.isArray(rawImageConfig["Command"])) {
|
|
70161
|
+
imageConfig.command = rawImageConfig["Command"].filter(
|
|
70162
|
+
(s) => typeof s === "string"
|
|
70163
|
+
);
|
|
70164
|
+
}
|
|
70165
|
+
if (Array.isArray(rawImageConfig["EntryPoint"])) {
|
|
70166
|
+
imageConfig.entryPoint = rawImageConfig["EntryPoint"].filter(
|
|
70167
|
+
(s) => typeof s === "string"
|
|
70168
|
+
);
|
|
70169
|
+
}
|
|
70170
|
+
if (typeof rawImageConfig["WorkingDirectory"] === "string") {
|
|
70171
|
+
imageConfig.workingDirectory = rawImageConfig["WorkingDirectory"];
|
|
70172
|
+
}
|
|
70173
|
+
const arches = props["Architectures"];
|
|
70174
|
+
let architecture = "x86_64";
|
|
70175
|
+
if (Array.isArray(arches) && arches.length > 0) {
|
|
70176
|
+
const first = arches[0];
|
|
70177
|
+
if (first === "arm64")
|
|
70178
|
+
architecture = "arm64";
|
|
70179
|
+
else if (first === "x86_64")
|
|
70180
|
+
architecture = "x86_64";
|
|
70181
|
+
else {
|
|
70182
|
+
throw new LocalInvokeResolutionError(
|
|
70183
|
+
`Lambda '${logicalId}' has unsupported Architectures value '${String(first)}'. cdkd local invoke supports x86_64 and arm64.`
|
|
70184
|
+
);
|
|
70185
|
+
}
|
|
70186
|
+
}
|
|
70187
|
+
return {
|
|
70188
|
+
kind: "image",
|
|
70189
|
+
stack,
|
|
70190
|
+
logicalId,
|
|
70191
|
+
resource,
|
|
70192
|
+
memoryMb,
|
|
70193
|
+
timeoutSec,
|
|
70194
|
+
imageUri,
|
|
70195
|
+
imageConfig,
|
|
70196
|
+
architecture
|
|
70197
|
+
};
|
|
70198
|
+
}
|
|
70100
70199
|
function resolveAssetCodePath(stack, logicalId, resource) {
|
|
70101
70200
|
const meta = resource.Metadata;
|
|
70102
70201
|
const assetPath = meta?.["aws:asset:path"];
|
|
@@ -70140,7 +70239,7 @@ function notFoundError(target, stack, resources) {
|
|
|
70140
70239
|
return new LocalInvokeResolutionError(msg.trimEnd());
|
|
70141
70240
|
}
|
|
70142
70241
|
|
|
70143
|
-
// src/local
|
|
70242
|
+
// src/local/env-resolver.ts
|
|
70144
70243
|
function resolveEnvVars(logicalId, templateEnv, overrides) {
|
|
70145
70244
|
const resolved = {};
|
|
70146
70245
|
const unresolved = [];
|
|
@@ -70177,7 +70276,184 @@ function isLiteralEnvValue(value) {
|
|
|
70177
70276
|
return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
70178
70277
|
}
|
|
70179
70278
|
|
|
70180
|
-
// src/local
|
|
70279
|
+
// src/local/state-resolver.ts
|
|
70280
|
+
function substituteAgainstState(value, resources) {
|
|
70281
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
70282
|
+
return { kind: "literal", value };
|
|
70283
|
+
}
|
|
70284
|
+
if (value === null || typeof value !== "object") {
|
|
70285
|
+
return {
|
|
70286
|
+
kind: "unresolved",
|
|
70287
|
+
reason: `unsupported value type: ${value === null ? "null" : typeof value}`
|
|
70288
|
+
};
|
|
70289
|
+
}
|
|
70290
|
+
const obj = value;
|
|
70291
|
+
const keys = Object.keys(obj);
|
|
70292
|
+
if (keys.length !== 1) {
|
|
70293
|
+
return {
|
|
70294
|
+
kind: "unresolved",
|
|
70295
|
+
reason: `expected an intrinsic with one key, got ${keys.length} keys`
|
|
70296
|
+
};
|
|
70297
|
+
}
|
|
70298
|
+
const intrinsic = keys[0];
|
|
70299
|
+
const arg = obj[intrinsic];
|
|
70300
|
+
if (intrinsic === "Ref") {
|
|
70301
|
+
return resolveRef(arg, resources);
|
|
70302
|
+
}
|
|
70303
|
+
if (intrinsic === "Fn::GetAtt") {
|
|
70304
|
+
return resolveGetAtt(arg, resources);
|
|
70305
|
+
}
|
|
70306
|
+
if (intrinsic === "Fn::Sub") {
|
|
70307
|
+
return resolveSub(arg, resources);
|
|
70308
|
+
}
|
|
70309
|
+
return {
|
|
70310
|
+
kind: "unresolved",
|
|
70311
|
+
reason: `unsupported intrinsic '${intrinsic}' (only Ref, Fn::GetAtt, Fn::Sub are wired in --from-state v1)`
|
|
70312
|
+
};
|
|
70313
|
+
}
|
|
70314
|
+
function resolveRef(arg, resources) {
|
|
70315
|
+
if (typeof arg !== "string" || arg.length === 0) {
|
|
70316
|
+
return { kind: "unresolved", reason: `Ref expects a non-empty logical ID, got ${typeof arg}` };
|
|
70317
|
+
}
|
|
70318
|
+
const resource = resources[arg];
|
|
70319
|
+
if (!resource) {
|
|
70320
|
+
return {
|
|
70321
|
+
kind: "unresolved",
|
|
70322
|
+
reason: `Ref '${arg}': no record in cdkd state (was the resource deployed?)`
|
|
70323
|
+
};
|
|
70324
|
+
}
|
|
70325
|
+
return { kind: "literal", value: resource.physicalId };
|
|
70326
|
+
}
|
|
70327
|
+
function resolveGetAtt(arg, resources) {
|
|
70328
|
+
let logicalId;
|
|
70329
|
+
let attr;
|
|
70330
|
+
if (Array.isArray(arg) && arg.length === 2 && typeof arg[0] === "string") {
|
|
70331
|
+
logicalId = arg[0];
|
|
70332
|
+
if (typeof arg[1] !== "string") {
|
|
70333
|
+
return {
|
|
70334
|
+
kind: "unresolved",
|
|
70335
|
+
reason: `Fn::GetAtt's second arg must be a string attribute name, got ${typeof arg[1]} (nested intrinsics in attribute names are not supported in --from-state v1)`
|
|
70336
|
+
};
|
|
70337
|
+
}
|
|
70338
|
+
attr = arg[1];
|
|
70339
|
+
} else if (typeof arg === "string") {
|
|
70340
|
+
const dot = arg.indexOf(".");
|
|
70341
|
+
if (dot <= 0 || dot === arg.length - 1) {
|
|
70342
|
+
return {
|
|
70343
|
+
kind: "unresolved",
|
|
70344
|
+
reason: `Fn::GetAtt string form must be '<LogicalId>.<Attribute>', got '${arg}'`
|
|
70345
|
+
};
|
|
70346
|
+
}
|
|
70347
|
+
logicalId = arg.slice(0, dot);
|
|
70348
|
+
attr = arg.slice(dot + 1);
|
|
70349
|
+
} else {
|
|
70350
|
+
return {
|
|
70351
|
+
kind: "unresolved",
|
|
70352
|
+
reason: `Fn::GetAtt expects [LogicalId, Attribute] or 'LogicalId.Attribute', got ${Array.isArray(arg) ? `array of length ${arg.length}` : typeof arg}`
|
|
70353
|
+
};
|
|
70354
|
+
}
|
|
70355
|
+
const resource = resources[logicalId];
|
|
70356
|
+
if (!resource) {
|
|
70357
|
+
return {
|
|
70358
|
+
kind: "unresolved",
|
|
70359
|
+
reason: `Fn::GetAtt '${logicalId}.${attr}': no record in cdkd state`
|
|
70360
|
+
};
|
|
70361
|
+
}
|
|
70362
|
+
const cached = resource.attributes?.[attr];
|
|
70363
|
+
if (cached === void 0) {
|
|
70364
|
+
return {
|
|
70365
|
+
kind: "unresolved",
|
|
70366
|
+
reason: `Fn::GetAtt '${logicalId}.${attr}': attribute not captured in cdkd state at deploy time`
|
|
70367
|
+
};
|
|
70368
|
+
}
|
|
70369
|
+
if (typeof cached === "string" || typeof cached === "number" || typeof cached === "boolean") {
|
|
70370
|
+
return { kind: "literal", value: cached };
|
|
70371
|
+
}
|
|
70372
|
+
return { kind: "literal", value: JSON.stringify(cached) };
|
|
70373
|
+
}
|
|
70374
|
+
function resolveSub(arg, resources) {
|
|
70375
|
+
let template;
|
|
70376
|
+
let bindings = {};
|
|
70377
|
+
if (typeof arg === "string") {
|
|
70378
|
+
template = arg;
|
|
70379
|
+
} else if (Array.isArray(arg) && arg.length === 2 && typeof arg[0] === "string" && arg[1] !== null && typeof arg[1] === "object" && !Array.isArray(arg[1])) {
|
|
70380
|
+
template = arg[0];
|
|
70381
|
+
bindings = arg[1];
|
|
70382
|
+
} else {
|
|
70383
|
+
return {
|
|
70384
|
+
kind: "unresolved",
|
|
70385
|
+
reason: `Fn::Sub expects a string or [string, object], got ${Array.isArray(arg) ? "malformed array" : typeof arg}`
|
|
70386
|
+
};
|
|
70387
|
+
}
|
|
70388
|
+
const placeholderRegex = /\$\{([^}]+)\}/g;
|
|
70389
|
+
const placeholders = [];
|
|
70390
|
+
template.replace(placeholderRegex, (_, key) => {
|
|
70391
|
+
placeholders.push(key);
|
|
70392
|
+
return "";
|
|
70393
|
+
});
|
|
70394
|
+
const resolutions = /* @__PURE__ */ new Map();
|
|
70395
|
+
for (const placeholder of placeholders) {
|
|
70396
|
+
if (resolutions.has(placeholder))
|
|
70397
|
+
continue;
|
|
70398
|
+
if (placeholder in bindings) {
|
|
70399
|
+
const sub = substituteAgainstState(bindings[placeholder], resources);
|
|
70400
|
+
if (sub.kind !== "literal") {
|
|
70401
|
+
return {
|
|
70402
|
+
kind: "unresolved",
|
|
70403
|
+
reason: `Fn::Sub placeholder '\${${placeholder}}': ${sub.reason}`
|
|
70404
|
+
};
|
|
70405
|
+
}
|
|
70406
|
+
resolutions.set(placeholder, String(sub.value));
|
|
70407
|
+
continue;
|
|
70408
|
+
}
|
|
70409
|
+
const dot = placeholder.indexOf(".");
|
|
70410
|
+
if (dot === -1) {
|
|
70411
|
+
const sub = resolveRef(placeholder, resources);
|
|
70412
|
+
if (sub.kind !== "literal") {
|
|
70413
|
+
return {
|
|
70414
|
+
kind: "unresolved",
|
|
70415
|
+
reason: `Fn::Sub placeholder '\${${placeholder}}': ${sub.reason}`
|
|
70416
|
+
};
|
|
70417
|
+
}
|
|
70418
|
+
resolutions.set(placeholder, String(sub.value));
|
|
70419
|
+
} else {
|
|
70420
|
+
const sub = resolveGetAtt(placeholder, resources);
|
|
70421
|
+
if (sub.kind !== "literal") {
|
|
70422
|
+
return {
|
|
70423
|
+
kind: "unresolved",
|
|
70424
|
+
reason: `Fn::Sub placeholder '\${${placeholder}}': ${sub.reason}`
|
|
70425
|
+
};
|
|
70426
|
+
}
|
|
70427
|
+
resolutions.set(placeholder, String(sub.value));
|
|
70428
|
+
}
|
|
70429
|
+
}
|
|
70430
|
+
const out = template.replace(placeholderRegex, (_, key) => {
|
|
70431
|
+
return resolutions.get(key) ?? "";
|
|
70432
|
+
});
|
|
70433
|
+
return { kind: "literal", value: out };
|
|
70434
|
+
}
|
|
70435
|
+
function substituteEnvVarsFromState(templateEnv, resources) {
|
|
70436
|
+
const env = {};
|
|
70437
|
+
const audit = { resolvedKeys: [], unresolved: [] };
|
|
70438
|
+
if (!templateEnv)
|
|
70439
|
+
return { env, audit };
|
|
70440
|
+
for (const [key, value] of Object.entries(templateEnv)) {
|
|
70441
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
70442
|
+
env[key] = value;
|
|
70443
|
+
continue;
|
|
70444
|
+
}
|
|
70445
|
+
const result = substituteAgainstState(value, resources);
|
|
70446
|
+
if (result.kind === "literal") {
|
|
70447
|
+
env[key] = result.value;
|
|
70448
|
+
audit.resolvedKeys.push(key);
|
|
70449
|
+
} else {
|
|
70450
|
+
audit.unresolved.push({ key, reason: result.reason });
|
|
70451
|
+
}
|
|
70452
|
+
}
|
|
70453
|
+
return { env, audit };
|
|
70454
|
+
}
|
|
70455
|
+
|
|
70456
|
+
// src/local/runtime-image.ts
|
|
70181
70457
|
var SUPPORTED_RUNTIMES = {
|
|
70182
70458
|
"nodejs18.x": { image: "public.ecr.aws/lambda/nodejs:18", fileExtension: ".js" },
|
|
70183
70459
|
"nodejs20.x": { image: "public.ecr.aws/lambda/nodejs:20", fileExtension: ".js" },
|
|
@@ -70204,7 +70480,7 @@ function resolveRuntimeSpec(runtime) {
|
|
|
70204
70480
|
if (typeof runtime !== "string" || runtime.length === 0) {
|
|
70205
70481
|
throw new UnsupportedRuntimeError(
|
|
70206
70482
|
String(runtime),
|
|
70207
|
-
"Lambda function has no Runtime property.
|
|
70483
|
+
"Lambda function has no Runtime property. This branch is only reached for ZIP Lambdas; container-image Lambdas (Code.ImageUri) take a different code path that does not consult the Runtime property."
|
|
70208
70484
|
);
|
|
70209
70485
|
}
|
|
70210
70486
|
const spec = SUPPORTED_RUNTIMES[runtime];
|
|
@@ -70222,11 +70498,11 @@ function resolveRuntimeSpec(runtime) {
|
|
|
70222
70498
|
);
|
|
70223
70499
|
}
|
|
70224
70500
|
|
|
70225
|
-
// src/local
|
|
70226
|
-
import { execFile as
|
|
70501
|
+
// src/local/docker-runner.ts
|
|
70502
|
+
import { execFile as execFile3, spawn as spawn3 } from "node:child_process";
|
|
70227
70503
|
import { createServer } from "node:net";
|
|
70228
|
-
import { promisify as
|
|
70229
|
-
var
|
|
70504
|
+
import { promisify as promisify3 } from "node:util";
|
|
70505
|
+
var execFileAsync3 = promisify3(execFile3);
|
|
70230
70506
|
var DockerRunnerError = class _DockerRunnerError extends Error {
|
|
70231
70507
|
constructor(message) {
|
|
70232
70508
|
super(message);
|
|
@@ -70245,6 +70521,12 @@ async function pullImage(image, skipPull) {
|
|
|
70245
70521
|
}
|
|
70246
70522
|
async function runDetached(opts) {
|
|
70247
70523
|
const args = ["run", "-d", "--rm"];
|
|
70524
|
+
if (opts.name) {
|
|
70525
|
+
args.push("--name", opts.name);
|
|
70526
|
+
}
|
|
70527
|
+
if (opts.platform) {
|
|
70528
|
+
args.push("--platform", opts.platform);
|
|
70529
|
+
}
|
|
70248
70530
|
const host = opts.host ?? "127.0.0.1";
|
|
70249
70531
|
args.push("-p", `${host}:${opts.hostPort}:8080`);
|
|
70250
70532
|
if (opts.debugPort !== void 0) {
|
|
@@ -70257,11 +70539,19 @@ async function runDetached(opts) {
|
|
|
70257
70539
|
for (const [k, v] of Object.entries(opts.env)) {
|
|
70258
70540
|
args.push("-e", `${k}=${v}`);
|
|
70259
70541
|
}
|
|
70260
|
-
|
|
70542
|
+
if (opts.workingDir) {
|
|
70543
|
+
args.push("--workdir", opts.workingDir);
|
|
70544
|
+
}
|
|
70545
|
+
let entryPointTail = [];
|
|
70546
|
+
if (opts.entryPoint && opts.entryPoint.length > 0) {
|
|
70547
|
+
args.push("--entrypoint", opts.entryPoint[0]);
|
|
70548
|
+
entryPointTail = opts.entryPoint.slice(1);
|
|
70549
|
+
}
|
|
70550
|
+
args.push(opts.image, ...entryPointTail, ...opts.cmd);
|
|
70261
70551
|
const logger = getLogger().child("docker");
|
|
70262
|
-
logger.debug(`docker ${args.join(" ")}`);
|
|
70552
|
+
logger.debug(`docker ${redactAwsCredentialsInArgs(args).join(" ")}`);
|
|
70263
70553
|
try {
|
|
70264
|
-
const { stdout } = await
|
|
70554
|
+
const { stdout } = await execFileAsync3("docker", args, {
|
|
70265
70555
|
maxBuffer: 10 * 1024 * 1024
|
|
70266
70556
|
});
|
|
70267
70557
|
return stdout.trim();
|
|
@@ -70290,7 +70580,7 @@ async function removeContainer(containerId) {
|
|
|
70290
70580
|
return;
|
|
70291
70581
|
const logger = getLogger().child("docker");
|
|
70292
70582
|
try {
|
|
70293
|
-
await
|
|
70583
|
+
await execFileAsync3("docker", ["rm", "-f", containerId]);
|
|
70294
70584
|
logger.debug(`Removed container ${containerId}`);
|
|
70295
70585
|
} catch (error) {
|
|
70296
70586
|
const err = error;
|
|
@@ -70301,7 +70591,7 @@ async function removeContainer(containerId) {
|
|
|
70301
70591
|
}
|
|
70302
70592
|
async function ensureDockerAvailable() {
|
|
70303
70593
|
try {
|
|
70304
|
-
await
|
|
70594
|
+
await execFileAsync3("docker", ["version", "--format", "{{.Server.Version}}"]);
|
|
70305
70595
|
} catch (error) {
|
|
70306
70596
|
const err = error;
|
|
70307
70597
|
if (err.code === "ENOENT") {
|
|
@@ -70331,6 +70621,31 @@ function pickFreePort() {
|
|
|
70331
70621
|
});
|
|
70332
70622
|
});
|
|
70333
70623
|
}
|
|
70624
|
+
var REDACTED_ENV_KEYS = /* @__PURE__ */ new Set([
|
|
70625
|
+
"AWS_ACCESS_KEY_ID",
|
|
70626
|
+
"AWS_SECRET_ACCESS_KEY",
|
|
70627
|
+
"AWS_SESSION_TOKEN"
|
|
70628
|
+
]);
|
|
70629
|
+
function redactAwsCredentialsInArgs(args) {
|
|
70630
|
+
const out = [];
|
|
70631
|
+
for (let i = 0; i < args.length; i++) {
|
|
70632
|
+
const cur = args[i];
|
|
70633
|
+
const next = args[i + 1];
|
|
70634
|
+
if (cur === "-e" && typeof next === "string") {
|
|
70635
|
+
const eqIdx = next.indexOf("=");
|
|
70636
|
+
if (eqIdx > 0) {
|
|
70637
|
+
const key = next.substring(0, eqIdx);
|
|
70638
|
+
if (REDACTED_ENV_KEYS.has(key)) {
|
|
70639
|
+
out.push("-e", `${key}=***`);
|
|
70640
|
+
i++;
|
|
70641
|
+
continue;
|
|
70642
|
+
}
|
|
70643
|
+
}
|
|
70644
|
+
}
|
|
70645
|
+
out.push(cur);
|
|
70646
|
+
}
|
|
70647
|
+
return out;
|
|
70648
|
+
}
|
|
70334
70649
|
function runForeground(cmd, args) {
|
|
70335
70650
|
return new Promise((resolveProc, rejectProc) => {
|
|
70336
70651
|
const proc = spawn3(cmd, args, { stdio: "inherit" });
|
|
@@ -70344,7 +70659,164 @@ function runForeground(cmd, args) {
|
|
|
70344
70659
|
});
|
|
70345
70660
|
}
|
|
70346
70661
|
|
|
70347
|
-
// src/local
|
|
70662
|
+
// src/local/docker-image-builder.ts
|
|
70663
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
70664
|
+
async function buildContainerImage(asset, cdkOutDir, options) {
|
|
70665
|
+
const tag = computeLocalTag(asset.source);
|
|
70666
|
+
const platform = architectureToPlatform(options.architecture);
|
|
70667
|
+
const logger = getLogger().child("local-invoke-build");
|
|
70668
|
+
logger.info(`Building container image (platform=${platform})...`);
|
|
70669
|
+
logger.debug(`Local tag: ${tag}`);
|
|
70670
|
+
await buildDockerImage(asset, cdkOutDir, tag, {
|
|
70671
|
+
platform,
|
|
70672
|
+
wrapError: (stderr) => new LocalInvokeBuildError(
|
|
70673
|
+
`docker build failed for container Lambda asset (${asset.source.directory}): ${stderr}`
|
|
70674
|
+
)
|
|
70675
|
+
});
|
|
70676
|
+
return tag;
|
|
70677
|
+
}
|
|
70678
|
+
function architectureToPlatform(architecture) {
|
|
70679
|
+
return architecture === "arm64" ? "linux/arm64" : "linux/amd64";
|
|
70680
|
+
}
|
|
70681
|
+
function computeLocalTag(source) {
|
|
70682
|
+
const hash = createHash2("sha256");
|
|
70683
|
+
hash.update(source.directory);
|
|
70684
|
+
hash.update("\0");
|
|
70685
|
+
hash.update(source.dockerFile ?? "");
|
|
70686
|
+
hash.update("\0");
|
|
70687
|
+
hash.update(source.dockerBuildTarget ?? "");
|
|
70688
|
+
hash.update("\0");
|
|
70689
|
+
if (source.dockerBuildArgs) {
|
|
70690
|
+
for (const [k, v] of Object.entries(source.dockerBuildArgs)) {
|
|
70691
|
+
hash.update(k);
|
|
70692
|
+
hash.update("=");
|
|
70693
|
+
hash.update(v);
|
|
70694
|
+
hash.update("\0");
|
|
70695
|
+
}
|
|
70696
|
+
}
|
|
70697
|
+
return `cdkd-local-invoke-${hash.digest("hex").slice(0, 16)}`;
|
|
70698
|
+
}
|
|
70699
|
+
|
|
70700
|
+
// src/local/ecr-puller.ts
|
|
70701
|
+
import { execFile as execFile4, spawn as spawn4 } from "node:child_process";
|
|
70702
|
+
import { promisify as promisify4 } from "node:util";
|
|
70703
|
+
import { ECRClient as ECRClient3, GetAuthorizationTokenCommand as GetAuthorizationTokenCommand2 } from "@aws-sdk/client-ecr";
|
|
70704
|
+
import { GetCallerIdentityCommand as GetCallerIdentityCommand11, STSClient as STSClient10 } from "@aws-sdk/client-sts";
|
|
70705
|
+
var execFileAsync4 = promisify4(execFile4);
|
|
70706
|
+
var ECR_URI_REGEX = /^(\d{12})\.dkr\.ecr\.([^.]+)\.amazonaws\.com(?:\.cn)?\/([^:]+):(.+)$/;
|
|
70707
|
+
function parseEcrUri(imageUri) {
|
|
70708
|
+
const m = ECR_URI_REGEX.exec(imageUri);
|
|
70709
|
+
if (!m)
|
|
70710
|
+
return void 0;
|
|
70711
|
+
return {
|
|
70712
|
+
accountId: m[1],
|
|
70713
|
+
region: m[2],
|
|
70714
|
+
repository: m[3],
|
|
70715
|
+
tag: m[4]
|
|
70716
|
+
};
|
|
70717
|
+
}
|
|
70718
|
+
async function pullEcrImage(imageUri, options) {
|
|
70719
|
+
const logger = getLogger().child("ecr-puller");
|
|
70720
|
+
const parsed = parseEcrUri(imageUri);
|
|
70721
|
+
if (!parsed) {
|
|
70722
|
+
throw new LocalInvokeBuildError(
|
|
70723
|
+
`Image URI '${imageUri}' is not an ECR URI. cdkd local invoke v1 only authenticates against ECR for the deployed-image fallback path.`
|
|
70724
|
+
);
|
|
70725
|
+
}
|
|
70726
|
+
const sts = new STSClient10({ region: parsed.region });
|
|
70727
|
+
let callerAccount;
|
|
70728
|
+
try {
|
|
70729
|
+
const identity = await sts.send(new GetCallerIdentityCommand11({}));
|
|
70730
|
+
if (!identity.Account) {
|
|
70731
|
+
throw new LocalInvokeBuildError(
|
|
70732
|
+
"STS GetCallerIdentity returned no Account. Verify your AWS credentials."
|
|
70733
|
+
);
|
|
70734
|
+
}
|
|
70735
|
+
callerAccount = identity.Account;
|
|
70736
|
+
} finally {
|
|
70737
|
+
sts.destroy();
|
|
70738
|
+
}
|
|
70739
|
+
if (callerAccount !== parsed.accountId) {
|
|
70740
|
+
throw new LocalInvokeBuildError(
|
|
70741
|
+
`Image URI '${imageUri}' is in account ${parsed.accountId}, but the caller is ${callerAccount}. Cross-account ECR pull is not supported in cdkd local invoke v1 \u2014 deferred to a follow-up PR. Workaround: assume a role in the target account before invoking, or build the image locally with \`cdkd local invoke -a cdk.out\` (no ECR pull).`
|
|
70742
|
+
);
|
|
70743
|
+
}
|
|
70744
|
+
const callerRegion = options.region ?? process.env["AWS_REGION"] ?? process.env["AWS_DEFAULT_REGION"];
|
|
70745
|
+
if (callerRegion && callerRegion !== parsed.region) {
|
|
70746
|
+
throw new LocalInvokeBuildError(
|
|
70747
|
+
`Image URI '${imageUri}' is in region ${parsed.region}, but the caller's region is ${callerRegion}. Cross-region ECR pull is not supported in cdkd local invoke v1 \u2014 deferred to a follow-up PR. Workaround: re-run with AWS_REGION=${parsed.region} set, or build the image locally with -a cdk.out.`
|
|
70748
|
+
);
|
|
70749
|
+
}
|
|
70750
|
+
if (options.skipPull) {
|
|
70751
|
+
logger.info(`Skipping ECR pull (--no-pull). Verifying ${imageUri} is in local cache...`);
|
|
70752
|
+
await verifyImageInLocalCache(imageUri);
|
|
70753
|
+
return imageUri;
|
|
70754
|
+
}
|
|
70755
|
+
const ecr = new ECRClient3({ region: parsed.region });
|
|
70756
|
+
try {
|
|
70757
|
+
await ecrLogin(ecr, parsed.accountId, parsed.region);
|
|
70758
|
+
} finally {
|
|
70759
|
+
ecr.destroy();
|
|
70760
|
+
}
|
|
70761
|
+
logger.info(`Pulling ${imageUri}...`);
|
|
70762
|
+
await runForeground2("docker", ["pull", imageUri]);
|
|
70763
|
+
return imageUri;
|
|
70764
|
+
}
|
|
70765
|
+
async function ecrLogin(client, accountId, region) {
|
|
70766
|
+
const logger = getLogger().child("ecr-puller");
|
|
70767
|
+
logger.debug(`ECR login (account=${accountId}, region=${region})`);
|
|
70768
|
+
const response = await client.send(new GetAuthorizationTokenCommand2({}));
|
|
70769
|
+
const authData = response.authorizationData?.[0];
|
|
70770
|
+
if (!authData?.authorizationToken) {
|
|
70771
|
+
throw new LocalInvokeBuildError("Failed to get ECR authorization token");
|
|
70772
|
+
}
|
|
70773
|
+
const token = Buffer.from(authData.authorizationToken, "base64").toString();
|
|
70774
|
+
const [username, password] = token.split(":");
|
|
70775
|
+
const endpoint = authData.proxyEndpoint || `https://${accountId}.dkr.ecr.${region}.amazonaws.com`;
|
|
70776
|
+
await new Promise((resolve5, reject) => {
|
|
70777
|
+
const proc = spawn4("docker", ["login", "--username", username, "--password-stdin", endpoint], {
|
|
70778
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
70779
|
+
});
|
|
70780
|
+
let stderr = "";
|
|
70781
|
+
proc.stderr?.on("data", (data) => {
|
|
70782
|
+
stderr += data.toString();
|
|
70783
|
+
});
|
|
70784
|
+
proc.on("close", (code) => {
|
|
70785
|
+
if (code === 0)
|
|
70786
|
+
resolve5();
|
|
70787
|
+
else
|
|
70788
|
+
reject(new LocalInvokeBuildError(`ECR login failed: ${stderr.trim()}`));
|
|
70789
|
+
});
|
|
70790
|
+
proc.on("error", (err) => {
|
|
70791
|
+
reject(new LocalInvokeBuildError(`ECR login failed: ${err.message}`));
|
|
70792
|
+
});
|
|
70793
|
+
proc.stdin?.write(password);
|
|
70794
|
+
proc.stdin?.end();
|
|
70795
|
+
});
|
|
70796
|
+
}
|
|
70797
|
+
async function verifyImageInLocalCache(imageUri) {
|
|
70798
|
+
try {
|
|
70799
|
+
await execFileAsync4("docker", ["image", "inspect", imageUri]);
|
|
70800
|
+
} catch {
|
|
70801
|
+
throw new LocalInvokeBuildError(
|
|
70802
|
+
`Image '${imageUri}' is not in the local docker cache and --no-pull was set. Either remove --no-pull (cdkd will pull from ECR) or pre-pull the image manually with \`docker pull\`.`
|
|
70803
|
+
);
|
|
70804
|
+
}
|
|
70805
|
+
}
|
|
70806
|
+
function runForeground2(cmd, args) {
|
|
70807
|
+
return new Promise((resolve5, reject) => {
|
|
70808
|
+
const proc = spawn4(cmd, args, { stdio: "inherit" });
|
|
70809
|
+
proc.on("error", (err) => reject(new LocalInvokeBuildError(`${cmd} failed: ${err.message}`)));
|
|
70810
|
+
proc.on("close", (code) => {
|
|
70811
|
+
if (code === 0)
|
|
70812
|
+
resolve5();
|
|
70813
|
+
else
|
|
70814
|
+
reject(new LocalInvokeBuildError(`${cmd} exited with code ${code}`));
|
|
70815
|
+
});
|
|
70816
|
+
});
|
|
70817
|
+
}
|
|
70818
|
+
|
|
70819
|
+
// src/local/rie-client.ts
|
|
70348
70820
|
import { setTimeout as delay } from "node:timers/promises";
|
|
70349
70821
|
var INVOKE_PATH = "/2015-03-31/functions/function/invocations";
|
|
70350
70822
|
async function waitForRieReady(host, port, timeoutMs = 5e3) {
|
|
@@ -70353,8 +70825,10 @@ async function waitForRieReady(host, port, timeoutMs = 5e3) {
|
|
|
70353
70825
|
while (Date.now() < deadline) {
|
|
70354
70826
|
try {
|
|
70355
70827
|
const ok = await httpProbe(host, port, 500);
|
|
70356
|
-
if (ok)
|
|
70828
|
+
if (ok) {
|
|
70829
|
+
await delay(250);
|
|
70357
70830
|
return;
|
|
70831
|
+
}
|
|
70358
70832
|
} catch (err) {
|
|
70359
70833
|
lastError = err;
|
|
70360
70834
|
}
|
|
@@ -70408,12 +70882,7 @@ async function invokeRie(host, port, event, timeoutMs) {
|
|
|
70408
70882
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
70409
70883
|
let response;
|
|
70410
70884
|
try {
|
|
70411
|
-
response = await
|
|
70412
|
-
method: "POST",
|
|
70413
|
-
headers: { "Content-Type": "application/json" },
|
|
70414
|
-
body,
|
|
70415
|
-
signal: controller.signal
|
|
70416
|
-
});
|
|
70885
|
+
response = await fetchWithStartupRetry(url, body, controller.signal);
|
|
70417
70886
|
} catch (err) {
|
|
70418
70887
|
if (err.name === "AbortError") {
|
|
70419
70888
|
throw new Error(
|
|
@@ -70432,8 +70901,130 @@ async function invokeRie(host, port, event, timeoutMs) {
|
|
|
70432
70901
|
}
|
|
70433
70902
|
return { payload, raw };
|
|
70434
70903
|
}
|
|
70904
|
+
async function fetchWithStartupRetry(url, body, signal) {
|
|
70905
|
+
const maxAttempts = 3;
|
|
70906
|
+
let lastError;
|
|
70907
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
70908
|
+
try {
|
|
70909
|
+
return await fetch(url, {
|
|
70910
|
+
method: "POST",
|
|
70911
|
+
headers: { "Content-Type": "application/json" },
|
|
70912
|
+
body,
|
|
70913
|
+
signal
|
|
70914
|
+
});
|
|
70915
|
+
} catch (err) {
|
|
70916
|
+
const name = err.name;
|
|
70917
|
+
if (name === "AbortError")
|
|
70918
|
+
throw err;
|
|
70919
|
+
lastError = err;
|
|
70920
|
+
if (attempt === maxAttempts)
|
|
70921
|
+
break;
|
|
70922
|
+
await delay(200);
|
|
70923
|
+
}
|
|
70924
|
+
}
|
|
70925
|
+
throw lastError;
|
|
70926
|
+
}
|
|
70927
|
+
|
|
70928
|
+
// src/assets/asset-manifest-loader.ts
|
|
70929
|
+
import { readFile } from "fs/promises";
|
|
70930
|
+
import { join as join6 } from "path";
|
|
70931
|
+
var AssetManifestLoader = class {
|
|
70932
|
+
logger = getLogger().child("AssetManifestLoader");
|
|
70933
|
+
/**
|
|
70934
|
+
* Load asset manifest from CDK output directory
|
|
70935
|
+
*
|
|
70936
|
+
* @param cdkOutputDir CDK output directory (e.g., "cdk.out")
|
|
70937
|
+
* @param stackName Stack name
|
|
70938
|
+
* @returns Asset manifest or null if not found
|
|
70939
|
+
*/
|
|
70940
|
+
async loadManifest(cdkOutputDir, stackName) {
|
|
70941
|
+
const manifestPath = join6(cdkOutputDir, `${stackName}.assets.json`);
|
|
70942
|
+
try {
|
|
70943
|
+
this.logger.debug(`Loading asset manifest from: ${manifestPath}`);
|
|
70944
|
+
const content = await readFile(manifestPath, "utf-8");
|
|
70945
|
+
const manifest = JSON.parse(content);
|
|
70946
|
+
this.logger.debug(
|
|
70947
|
+
`Loaded asset manifest: ${Object.keys(manifest.files).length} file assets, ${Object.keys(manifest.dockerImages).length} docker image assets`
|
|
70948
|
+
);
|
|
70949
|
+
return manifest;
|
|
70950
|
+
} catch (error) {
|
|
70951
|
+
if (error.code === "ENOENT") {
|
|
70952
|
+
this.logger.debug(`Asset manifest not found: ${manifestPath}`);
|
|
70953
|
+
return null;
|
|
70954
|
+
}
|
|
70955
|
+
throw new Error(
|
|
70956
|
+
`Failed to load asset manifest from ${manifestPath}: ${error instanceof Error ? error.message : String(error)}`
|
|
70957
|
+
);
|
|
70958
|
+
}
|
|
70959
|
+
}
|
|
70960
|
+
/**
|
|
70961
|
+
* Get file assets from manifest (excludes CloudFormation templates)
|
|
70962
|
+
*
|
|
70963
|
+
* @param manifest Asset manifest
|
|
70964
|
+
* @returns Map of asset hash to file asset
|
|
70965
|
+
*/
|
|
70966
|
+
getFileAssets(manifest) {
|
|
70967
|
+
const fileAssets = /* @__PURE__ */ new Map();
|
|
70968
|
+
for (const [assetHash, asset] of Object.entries(manifest.files)) {
|
|
70969
|
+
if (asset.source.path.endsWith(".json") || asset.source.path.endsWith(".template.json")) {
|
|
70970
|
+
this.logger.debug(`Skipping CloudFormation template asset: ${asset.displayName}`);
|
|
70971
|
+
continue;
|
|
70972
|
+
}
|
|
70973
|
+
fileAssets.set(assetHash, asset);
|
|
70974
|
+
}
|
|
70975
|
+
this.logger.debug(`Found ${fileAssets.size} file assets (excluding templates)`);
|
|
70976
|
+
return fileAssets;
|
|
70977
|
+
}
|
|
70978
|
+
/**
|
|
70979
|
+
* Get asset source path (absolute path)
|
|
70980
|
+
*
|
|
70981
|
+
* @param cdkOutputDir CDK output directory
|
|
70982
|
+
* @param asset File asset
|
|
70983
|
+
* @returns Absolute path to asset source
|
|
70984
|
+
*/
|
|
70985
|
+
getAssetSourcePath(cdkOutputDir, asset) {
|
|
70986
|
+
return join6(cdkOutputDir, asset.source.path);
|
|
70987
|
+
}
|
|
70988
|
+
/**
|
|
70989
|
+
* Resolve asset destination values (replace ${AWS::AccountId}, ${AWS::Region}, etc.)
|
|
70990
|
+
*
|
|
70991
|
+
* @param value Value with placeholders
|
|
70992
|
+
* @param accountId AWS account ID
|
|
70993
|
+
* @param region AWS region
|
|
70994
|
+
* @param partition AWS partition (default: "aws")
|
|
70995
|
+
* @returns Resolved value
|
|
70996
|
+
*/
|
|
70997
|
+
resolveAssetDestinationValue(value, accountId, region, partition = "aws") {
|
|
70998
|
+
return value.replace(/\$\{AWS::AccountId\}/g, accountId).replace(/\$\{AWS::Region\}/g, region).replace(/\$\{AWS::Partition\}/g, partition);
|
|
70999
|
+
}
|
|
71000
|
+
};
|
|
71001
|
+
function getDockerImageBySourceHash(manifest, imageUri) {
|
|
71002
|
+
const dockerImages = manifest.dockerImages ?? {};
|
|
71003
|
+
const entries = Object.entries(dockerImages);
|
|
71004
|
+
if (entries.length === 0)
|
|
71005
|
+
return void 0;
|
|
71006
|
+
const hash = extractHashFromImageUri(imageUri);
|
|
71007
|
+
if (hash !== void 0) {
|
|
71008
|
+
const asset = dockerImages[hash];
|
|
71009
|
+
if (asset) {
|
|
71010
|
+
return { hash, asset };
|
|
71011
|
+
}
|
|
71012
|
+
}
|
|
71013
|
+
if (entries.length === 1) {
|
|
71014
|
+
const [singleHash, singleAsset] = entries[0];
|
|
71015
|
+
return { hash: singleHash, asset: singleAsset };
|
|
71016
|
+
}
|
|
71017
|
+
return void 0;
|
|
71018
|
+
}
|
|
71019
|
+
function extractHashFromImageUri(imageUri) {
|
|
71020
|
+
if (imageUri.includes("@sha256:"))
|
|
71021
|
+
return void 0;
|
|
71022
|
+
const match = /:([a-f0-9]{8,})$/.exec(imageUri);
|
|
71023
|
+
return match?.[1];
|
|
71024
|
+
}
|
|
70435
71025
|
|
|
70436
71026
|
// src/cli/commands/local-invoke.ts
|
|
71027
|
+
init_aws_clients();
|
|
70437
71028
|
async function localInvokeCommand(target, options) {
|
|
70438
71029
|
const logger = getLogger();
|
|
70439
71030
|
if (options.verbose) {
|
|
@@ -70458,21 +71049,48 @@ async function localInvokeCommand(target, options) {
|
|
|
70458
71049
|
};
|
|
70459
71050
|
const { stacks } = await synthesizer.synthesize(synthOpts);
|
|
70460
71051
|
const lambda = resolveLambdaTarget(target, stacks);
|
|
70461
|
-
|
|
70462
|
-
|
|
70463
|
-
|
|
70464
|
-
|
|
70465
|
-
|
|
70466
|
-
|
|
71052
|
+
const targetLabel = lambda.kind === "zip" ? lambda.runtime : "container image";
|
|
71053
|
+
logger.info(`Target: ${lambda.stack.stackName}/${lambda.logicalId} (${targetLabel})`);
|
|
71054
|
+
const imagePlan = await resolveImagePlan(lambda, options);
|
|
71055
|
+
let stateAudit;
|
|
71056
|
+
let templateEnv = getTemplateEnv(lambda.resource);
|
|
71057
|
+
let stateForRoleHint;
|
|
71058
|
+
if (options.fromState) {
|
|
71059
|
+
const loaded = await loadStateForStack(lambda.stack.stackName, lambda.stack.region, {
|
|
71060
|
+
...options.stackRegion !== void 0 && { stackRegion: options.stackRegion },
|
|
71061
|
+
...options.stateBucket !== void 0 && { stateBucket: options.stateBucket },
|
|
71062
|
+
statePrefix: options.statePrefix,
|
|
71063
|
+
...options.region !== void 0 && { region: options.region },
|
|
71064
|
+
...options.profile !== void 0 && { profile: options.profile }
|
|
71065
|
+
});
|
|
71066
|
+
if (loaded) {
|
|
71067
|
+
stateForRoleHint = loaded.state;
|
|
71068
|
+
const { env, audit } = substituteEnvVarsFromState(templateEnv, loaded.state.resources);
|
|
71069
|
+
templateEnv = env;
|
|
71070
|
+
stateAudit = audit;
|
|
71071
|
+
for (const key of audit.resolvedKeys) {
|
|
71072
|
+
logger.debug(`--from-state: substituted env var ${key} from cdkd state`);
|
|
71073
|
+
}
|
|
71074
|
+
for (const { key, reason } of audit.unresolved) {
|
|
71075
|
+
logger.warn(
|
|
71076
|
+
`--from-state: could not substitute env var ${key} (${reason}). Override it via --env-vars or it will be dropped.`
|
|
71077
|
+
);
|
|
71078
|
+
}
|
|
71079
|
+
}
|
|
71080
|
+
}
|
|
70467
71081
|
const overrides = readEnvOverridesFile(options.envVars);
|
|
70468
|
-
const envResult = resolveEnvVars(lambda.logicalId,
|
|
71082
|
+
const envResult = resolveEnvVars(lambda.logicalId, templateEnv, overrides);
|
|
70469
71083
|
for (const key of envResult.unresolved) {
|
|
71084
|
+
if (stateAudit && stateAudit.unresolved.some((u) => u.key === key))
|
|
71085
|
+
continue;
|
|
70470
71086
|
logger.warn(
|
|
70471
|
-
`Environment variable ${key} contains a CloudFormation intrinsic and was dropped. Override it with --env-vars (e.g. {"${lambda.logicalId}":{"${key}":"<literal>"}}) or
|
|
71087
|
+
`Environment variable ${key} contains a CloudFormation intrinsic and was dropped. Override it with --env-vars (e.g. {"${lambda.logicalId}":{"${key}":"<literal>"}}) or pass --from-state to recover deployed values.`
|
|
70472
71088
|
);
|
|
70473
71089
|
}
|
|
71090
|
+
if (options.fromState && !options.assumeRole && stateForRoleHint) {
|
|
71091
|
+
suggestAssumeRoleFromState(stateForRoleHint, lambda.logicalId);
|
|
71092
|
+
}
|
|
70474
71093
|
const event = await readEvent(options);
|
|
70475
|
-
const image = resolveRuntimeImage(lambda.runtime);
|
|
70476
71094
|
const dockerEnv = {
|
|
70477
71095
|
AWS_LAMBDA_FUNCTION_NAME: lambda.logicalId,
|
|
70478
71096
|
AWS_LAMBDA_FUNCTION_MEMORY_SIZE: String(lambda.memoryMb),
|
|
@@ -70500,19 +71118,26 @@ async function localInvokeCommand(target, options) {
|
|
|
70500
71118
|
throw new Error(`--debug-port must be an integer in 1..65535, got '${options.debugPort}'`);
|
|
70501
71119
|
}
|
|
70502
71120
|
dockerEnv["NODE_OPTIONS"] = `--inspect-brk=0.0.0.0:${debugPort}`;
|
|
71121
|
+
if (lambda.kind === "image") {
|
|
71122
|
+
logger.warn(
|
|
71123
|
+
"--debug-port sets NODE_OPTIONS unconditionally on container Lambdas. If the image's runtime is not Node.js, this flag is a no-op."
|
|
71124
|
+
);
|
|
71125
|
+
}
|
|
70503
71126
|
}
|
|
70504
|
-
await pullImage(image, options.pull === false);
|
|
70505
71127
|
const hostPort = await pickFreePort();
|
|
70506
|
-
const containerHost = options.containerHost
|
|
70507
|
-
logger.info(`Starting container (image=${image}, port=${hostPort})...`);
|
|
71128
|
+
const containerHost = options.containerHost;
|
|
71129
|
+
logger.info(`Starting container (image=${imagePlan.image}, port=${hostPort})...`);
|
|
70508
71130
|
const containerId = await runDetached({
|
|
70509
|
-
image,
|
|
70510
|
-
mounts:
|
|
71131
|
+
image: imagePlan.image,
|
|
71132
|
+
mounts: imagePlan.mounts,
|
|
70511
71133
|
env: dockerEnv,
|
|
70512
|
-
cmd:
|
|
71134
|
+
cmd: imagePlan.cmd,
|
|
70513
71135
|
hostPort,
|
|
70514
71136
|
host: containerHost,
|
|
70515
|
-
...debugPort !== void 0 && { debugPort }
|
|
71137
|
+
...debugPort !== void 0 && { debugPort },
|
|
71138
|
+
...imagePlan.platform !== void 0 && { platform: imagePlan.platform },
|
|
71139
|
+
...imagePlan.entryPoint !== void 0 && { entryPoint: imagePlan.entryPoint },
|
|
71140
|
+
...imagePlan.workingDir !== void 0 && { workingDir: imagePlan.workingDir }
|
|
70516
71141
|
});
|
|
70517
71142
|
const stopLogs = streamLogs(containerId);
|
|
70518
71143
|
const sigintHandler = () => {
|
|
@@ -70533,7 +71158,92 @@ async function localInvokeCommand(target, options) {
|
|
|
70533
71158
|
process.off("SIGINT", sigintHandler);
|
|
70534
71159
|
stopLogs();
|
|
70535
71160
|
await removeContainer(containerId);
|
|
71161
|
+
if (imagePlan.inlineTmpDir) {
|
|
71162
|
+
try {
|
|
71163
|
+
rmSync2(imagePlan.inlineTmpDir, { recursive: true, force: true });
|
|
71164
|
+
} catch (err) {
|
|
71165
|
+
getLogger().debug(
|
|
71166
|
+
`Failed to remove inline-code tmpdir ${imagePlan.inlineTmpDir}: ${err instanceof Error ? err.message : String(err)}`
|
|
71167
|
+
);
|
|
71168
|
+
}
|
|
71169
|
+
}
|
|
71170
|
+
}
|
|
71171
|
+
}
|
|
71172
|
+
async function resolveImagePlan(lambda, options) {
|
|
71173
|
+
if (lambda.kind === "zip") {
|
|
71174
|
+
return resolveZipImagePlan(lambda, options);
|
|
71175
|
+
}
|
|
71176
|
+
return resolveContainerImagePlan(lambda, options);
|
|
71177
|
+
}
|
|
71178
|
+
async function resolveZipImagePlan(lambda, options) {
|
|
71179
|
+
let inlineTmpDir;
|
|
71180
|
+
let codeDir = lambda.codePath;
|
|
71181
|
+
if (codeDir === null) {
|
|
71182
|
+
inlineTmpDir = materializeInlineCode(
|
|
71183
|
+
lambda.handler,
|
|
71184
|
+
lambda.inlineCode ?? "",
|
|
71185
|
+
resolveRuntimeFileExtension(lambda.runtime)
|
|
71186
|
+
);
|
|
71187
|
+
codeDir = inlineTmpDir;
|
|
70536
71188
|
}
|
|
71189
|
+
const image = resolveRuntimeImage(lambda.runtime);
|
|
71190
|
+
await pullImage(image, options.pull === false);
|
|
71191
|
+
return {
|
|
71192
|
+
image,
|
|
71193
|
+
mounts: [{ hostPath: codeDir, containerPath: "/var/task", readOnly: true }],
|
|
71194
|
+
cmd: [lambda.handler],
|
|
71195
|
+
...inlineTmpDir !== void 0 && { inlineTmpDir }
|
|
71196
|
+
};
|
|
71197
|
+
}
|
|
71198
|
+
async function resolveContainerImagePlan(lambda, options) {
|
|
71199
|
+
const logger = getLogger();
|
|
71200
|
+
const platform = architectureToPlatform(lambda.architecture);
|
|
71201
|
+
const localBuild = await resolveLocalBuildPlan(lambda);
|
|
71202
|
+
let imageRef;
|
|
71203
|
+
if (localBuild) {
|
|
71204
|
+
imageRef = await buildContainerImage(localBuild.asset, localBuild.cdkOutDir, {
|
|
71205
|
+
architecture: lambda.architecture
|
|
71206
|
+
});
|
|
71207
|
+
} else {
|
|
71208
|
+
if (!parseEcrUri(lambda.imageUri)) {
|
|
71209
|
+
throw new Error(
|
|
71210
|
+
`Container Lambda '${lambda.logicalId}' has no matching asset in cdk.out, and Code.ImageUri '${lambda.imageUri}' is not an ECR URI cdkd can authenticate against. Re-synthesize the CDK app (so cdk.out includes the build context) or deploy the image to ECR first.`
|
|
71211
|
+
);
|
|
71212
|
+
}
|
|
71213
|
+
logger.info(
|
|
71214
|
+
`No matching cdk.out asset for ${lambda.imageUri}; falling back to ECR pull (same-acct/region only)...`
|
|
71215
|
+
);
|
|
71216
|
+
imageRef = await pullEcrImage(lambda.imageUri, {
|
|
71217
|
+
skipPull: options.pull === false,
|
|
71218
|
+
...options.region !== void 0 && { region: options.region }
|
|
71219
|
+
});
|
|
71220
|
+
}
|
|
71221
|
+
return {
|
|
71222
|
+
image: imageRef,
|
|
71223
|
+
mounts: [],
|
|
71224
|
+
cmd: lambda.imageConfig.command ?? [],
|
|
71225
|
+
platform,
|
|
71226
|
+
...lambda.imageConfig.entryPoint && lambda.imageConfig.entryPoint.length > 0 && {
|
|
71227
|
+
entryPoint: lambda.imageConfig.entryPoint
|
|
71228
|
+
},
|
|
71229
|
+
...lambda.imageConfig.workingDirectory !== void 0 && {
|
|
71230
|
+
workingDir: lambda.imageConfig.workingDirectory
|
|
71231
|
+
}
|
|
71232
|
+
};
|
|
71233
|
+
}
|
|
71234
|
+
async function resolveLocalBuildPlan(lambda) {
|
|
71235
|
+
const manifestPath = lambda.stack.assetManifestPath;
|
|
71236
|
+
if (!manifestPath)
|
|
71237
|
+
return void 0;
|
|
71238
|
+
const cdkOutDir = dirname2(manifestPath);
|
|
71239
|
+
const loader = new AssetManifestLoader();
|
|
71240
|
+
const manifest = await loader.loadManifest(cdkOutDir, lambda.stack.stackName);
|
|
71241
|
+
if (!manifest)
|
|
71242
|
+
return void 0;
|
|
71243
|
+
const entry = getDockerImageBySourceHash(manifest, lambda.imageUri);
|
|
71244
|
+
if (!entry)
|
|
71245
|
+
return void 0;
|
|
71246
|
+
return { asset: entry.asset, cdkOutDir };
|
|
70537
71247
|
}
|
|
70538
71248
|
function getTemplateEnv(resource) {
|
|
70539
71249
|
const props = resource.Properties ?? {};
|
|
@@ -70600,8 +71310,8 @@ async function readStdin() {
|
|
|
70600
71310
|
return Buffer.concat(chunks).toString("utf-8");
|
|
70601
71311
|
}
|
|
70602
71312
|
async function assumeLambdaExecutionRole(roleArn, region) {
|
|
70603
|
-
const { STSClient:
|
|
70604
|
-
const sts = new
|
|
71313
|
+
const { STSClient: STSClient11, AssumeRoleCommand: AssumeRoleCommand2 } = await import("@aws-sdk/client-sts");
|
|
71314
|
+
const sts = new STSClient11({ ...region && { region } });
|
|
70605
71315
|
try {
|
|
70606
71316
|
const response = await sts.send(
|
|
70607
71317
|
new AssumeRoleCommand2({
|
|
@@ -70649,6 +71359,109 @@ function materializeInlineCode(handler, source, fileExtension) {
|
|
|
70649
71359
|
writeFileSync5(filePath, source, "utf-8");
|
|
70650
71360
|
return dir;
|
|
70651
71361
|
}
|
|
71362
|
+
async function loadStateForStack(stackName, synthRegion, opts) {
|
|
71363
|
+
const logger = getLogger();
|
|
71364
|
+
const region = opts.region ?? process.env["AWS_REGION"] ?? process.env["AWS_DEFAULT_REGION"] ?? synthRegion ?? "us-east-1";
|
|
71365
|
+
let stateBucket;
|
|
71366
|
+
try {
|
|
71367
|
+
stateBucket = await resolveStateBucketWithDefault(opts.stateBucket, region);
|
|
71368
|
+
} catch (err) {
|
|
71369
|
+
logger.warn(
|
|
71370
|
+
`--from-state: could not resolve state bucket: ${err instanceof Error ? err.message : String(err)}. Falling back to PR 1 warn-and-drop semantics.`
|
|
71371
|
+
);
|
|
71372
|
+
return void 0;
|
|
71373
|
+
}
|
|
71374
|
+
const awsClients = new AwsClients({
|
|
71375
|
+
...opts.region !== void 0 && { region: opts.region },
|
|
71376
|
+
...opts.profile !== void 0 && { profile: opts.profile }
|
|
71377
|
+
});
|
|
71378
|
+
setAwsClients(awsClients);
|
|
71379
|
+
try {
|
|
71380
|
+
const stateConfig = { bucket: stateBucket, prefix: opts.statePrefix };
|
|
71381
|
+
const stateBackend = new S3StateBackend(awsClients.s3, stateConfig, {
|
|
71382
|
+
...opts.region !== void 0 && { region: opts.region },
|
|
71383
|
+
...opts.profile !== void 0 && { profile: opts.profile }
|
|
71384
|
+
});
|
|
71385
|
+
await stateBackend.verifyBucketExists();
|
|
71386
|
+
const refs = (await stateBackend.listStacks()).filter((r) => r.stackName === stackName);
|
|
71387
|
+
if (refs.length === 0) {
|
|
71388
|
+
logger.warn(
|
|
71389
|
+
`--from-state: no cdkd state found for stack '${stackName}' in bucket '${stateBucket}'. Was it deployed via 'cdkd deploy'? Falling back to PR 1 warn-and-drop semantics.`
|
|
71390
|
+
);
|
|
71391
|
+
return void 0;
|
|
71392
|
+
}
|
|
71393
|
+
let targetRegion;
|
|
71394
|
+
if (opts.stackRegion) {
|
|
71395
|
+
const found = refs.find((r) => r.region === opts.stackRegion);
|
|
71396
|
+
if (!found) {
|
|
71397
|
+
const seen = refs.map((r) => r.region ?? "(legacy)").join(", ");
|
|
71398
|
+
logger.warn(
|
|
71399
|
+
`--from-state: stack '${stackName}' has no state in region '${opts.stackRegion}' (available: ${seen}). Falling back.`
|
|
71400
|
+
);
|
|
71401
|
+
return void 0;
|
|
71402
|
+
}
|
|
71403
|
+
targetRegion = opts.stackRegion;
|
|
71404
|
+
} else if (synthRegion && refs.some((r) => r.region === synthRegion)) {
|
|
71405
|
+
targetRegion = synthRegion;
|
|
71406
|
+
} else if (refs.length === 1) {
|
|
71407
|
+
targetRegion = refs[0].region ?? synthRegion ?? region;
|
|
71408
|
+
} else {
|
|
71409
|
+
const seen = refs.map((r) => r.region ?? "(legacy)").join(", ");
|
|
71410
|
+
logger.warn(
|
|
71411
|
+
`--from-state: stack '${stackName}' has state in multiple regions (${seen}). Re-run with --stack-region <region>. Falling back.`
|
|
71412
|
+
);
|
|
71413
|
+
return void 0;
|
|
71414
|
+
}
|
|
71415
|
+
const stateData = await stateBackend.getState(stackName, targetRegion);
|
|
71416
|
+
if (!stateData) {
|
|
71417
|
+
logger.warn(
|
|
71418
|
+
`--from-state: state record for '${stackName}' (${targetRegion}) returned empty. Falling back.`
|
|
71419
|
+
);
|
|
71420
|
+
return void 0;
|
|
71421
|
+
}
|
|
71422
|
+
logger.debug(`--from-state: loaded state for ${stackName} (${targetRegion})`);
|
|
71423
|
+
return { state: stateData.state, region: targetRegion };
|
|
71424
|
+
} finally {
|
|
71425
|
+
awsClients.destroy();
|
|
71426
|
+
}
|
|
71427
|
+
}
|
|
71428
|
+
function suggestAssumeRoleFromState(state, logicalId) {
|
|
71429
|
+
const logger = getLogger();
|
|
71430
|
+
const lambda = state.resources[logicalId];
|
|
71431
|
+
if (!lambda)
|
|
71432
|
+
return;
|
|
71433
|
+
const roleRef = lambda.properties?.["Role"] ?? lambda.observedProperties?.["Role"];
|
|
71434
|
+
let roleArn;
|
|
71435
|
+
if (typeof roleRef === "string" && roleRef.startsWith("arn:")) {
|
|
71436
|
+
roleArn = roleRef;
|
|
71437
|
+
} else if (typeof roleRef === "object" && roleRef !== null) {
|
|
71438
|
+
const refLogicalId = pickReferencedLogicalId(roleRef);
|
|
71439
|
+
if (refLogicalId) {
|
|
71440
|
+
const roleResource = state.resources[refLogicalId];
|
|
71441
|
+
const cached = roleResource?.attributes?.["Arn"];
|
|
71442
|
+
if (typeof cached === "string" && cached.startsWith("arn:")) {
|
|
71443
|
+
roleArn = cached;
|
|
71444
|
+
}
|
|
71445
|
+
}
|
|
71446
|
+
}
|
|
71447
|
+
if (roleArn) {
|
|
71448
|
+
logger.info(
|
|
71449
|
+
`Hint: the deployed function uses execution role ${roleArn}. Re-run with --assume-role <that-arn> to invoke under the deployed function's narrow permissions.`
|
|
71450
|
+
);
|
|
71451
|
+
}
|
|
71452
|
+
}
|
|
71453
|
+
function pickReferencedLogicalId(intrinsic) {
|
|
71454
|
+
if ("Ref" in intrinsic && typeof intrinsic["Ref"] === "string")
|
|
71455
|
+
return intrinsic["Ref"];
|
|
71456
|
+
if ("Fn::GetAtt" in intrinsic) {
|
|
71457
|
+
const arg = intrinsic["Fn::GetAtt"];
|
|
71458
|
+
if (Array.isArray(arg) && typeof arg[0] === "string")
|
|
71459
|
+
return arg[0];
|
|
71460
|
+
if (typeof arg === "string")
|
|
71461
|
+
return arg.split(".")[0];
|
|
71462
|
+
}
|
|
71463
|
+
return void 0;
|
|
71464
|
+
}
|
|
70652
71465
|
function createLocalCommand() {
|
|
70653
71466
|
const local = new Command14("local").description(
|
|
70654
71467
|
"Local Lambda execution against the AWS Lambda Runtime Interface Emulator (Docker required)"
|
|
@@ -70660,15 +71473,32 @@ function createLocalCommand() {
|
|
|
70660
71473
|
"--env-vars <file>",
|
|
70661
71474
|
'JSON env-var overrides (SAM-compatible: {"LogicalId":{"KEY":"VALUE"}})'
|
|
70662
71475
|
)
|
|
70663
|
-
).addOption(
|
|
71476
|
+
).addOption(
|
|
71477
|
+
new Option7(
|
|
71478
|
+
"--no-pull",
|
|
71479
|
+
"Skip docker pull (use cached image) \u2014 no-op for IMAGE local-build path; `docker build` does not pull base layers by default"
|
|
71480
|
+
)
|
|
71481
|
+
).addOption(new Option7("--debug-port <port>", "Node --inspect-brk port (default: off)")).addOption(
|
|
70664
71482
|
new Option7("--container-host <host>", "Host to bind the RIE port to").default("127.0.0.1")
|
|
70665
71483
|
).addOption(
|
|
70666
71484
|
new Option7(
|
|
70667
71485
|
"--assume-role <arn>",
|
|
70668
71486
|
`Assume the Lambda's deployed execution role and forward STS-issued temp credentials to the container so the handler runs with the deployed function's narrow permissions (closes the "developer admin / function narrow" skew). Off by default \u2014 when omitted, the developer's shell credentials are forwarded unchanged (SAM-compatible default).`
|
|
70669
71487
|
)
|
|
71488
|
+
).addOption(
|
|
71489
|
+
new Option7(
|
|
71490
|
+
"--from-state",
|
|
71491
|
+
"Read cdkd S3 state for the target stack and substitute Ref / Fn::GetAtt / Fn::Sub in env vars with the deployed physical IDs / attributes. Off by default \u2014 keep PR 1 warn-and-drop semantics; turn on for stacks already deployed via cdkd deploy."
|
|
71492
|
+
).default(false)
|
|
71493
|
+
).addOption(
|
|
71494
|
+
new Option7(
|
|
71495
|
+
"--stack-region <region>",
|
|
71496
|
+
"Region of the cdkd state record to read (used with --from-state when the same stack name has state in multiple regions)."
|
|
71497
|
+
)
|
|
70670
71498
|
).action(withErrorHandling(localInvokeCommand));
|
|
70671
|
-
[...commonOptions, ...appOptions, ...contextOptions].forEach(
|
|
71499
|
+
[...commonOptions, ...appOptions, ...contextOptions, ...stateOptions].forEach(
|
|
71500
|
+
(opt) => invoke.addOption(opt)
|
|
71501
|
+
);
|
|
70672
71502
|
invoke.addOption(deprecatedRegionOption);
|
|
70673
71503
|
local.addCommand(invoke);
|
|
70674
71504
|
return local;
|
|
@@ -70703,7 +71533,7 @@ function reorderArgs(argv) {
|
|
|
70703
71533
|
}
|
|
70704
71534
|
async function main() {
|
|
70705
71535
|
const program = new Command15();
|
|
70706
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.
|
|
71536
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.70.0");
|
|
70707
71537
|
program.addCommand(createBootstrapCommand());
|
|
70708
71538
|
program.addCommand(createSynthCommand());
|
|
70709
71539
|
program.addCommand(createListCommand());
|