@go-to-k/cdkd 0.167.1 → 0.167.3
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/dist/cli.js +148 -13
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -62,7 +62,7 @@ import { CreateVectorBucketCommand, DeleteIndexCommand, DeleteVectorBucketComman
|
|
|
62
62
|
import { CreateNamespaceCommand, CreateTableBucketCommand, CreateTableCommand as CreateTableCommand$2, DeleteNamespaceCommand as DeleteNamespaceCommand$1, DeleteTableBucketCommand, DeleteTableCommand as DeleteTableCommand$2, GetTableBucketCommand, GetTableCommand as GetTableCommand$1, ListNamespacesCommand as ListNamespacesCommand$1, ListTableBucketsCommand, ListTablesCommand as ListTablesCommand$1, ListTagsForResourceCommand as ListTagsForResourceCommand$19, NotFoundException as NotFoundException$5, S3TablesClient } from "@aws-sdk/client-s3tables";
|
|
63
63
|
import { AttachLoadBalancerTargetGroupsCommand, AttachLoadBalancersCommand, AttachTrafficSourcesCommand, AutoScalingClient, CreateAutoScalingGroupCommand, CreateOrUpdateTagsCommand, DeleteAutoScalingGroupCommand, DeleteLifecycleHookCommand, DeleteNotificationConfigurationCommand, DeleteTagsCommand as DeleteTagsCommand$1, DescribeAutoScalingGroupsCommand, DescribeLifecycleHooksCommand, DescribeNotificationConfigurationsCommand, DescribeTrafficSourcesCommand, DetachLoadBalancerTargetGroupsCommand, DetachLoadBalancersCommand, DetachTrafficSourcesCommand, DisableMetricsCollectionCommand, EnableMetricsCollectionCommand, PutLifecycleHookCommand, PutNotificationConfigurationCommand, UpdateAutoScalingGroupCommand } from "@aws-sdk/client-auto-scaling";
|
|
64
64
|
import { Document, Pair, Scalar, YAMLMap, YAMLSeq, parse as parse$1, stringify } from "yaml";
|
|
65
|
-
import { mkdir, mkdtemp } from "node:fs/promises";
|
|
65
|
+
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
66
66
|
import { Readable } from "node:stream";
|
|
67
67
|
import { pipeline } from "node:stream/promises";
|
|
68
68
|
import { createServer } from "node:net";
|
|
@@ -46520,6 +46520,62 @@ function singleFlight(fn, onError) {
|
|
|
46520
46520
|
};
|
|
46521
46521
|
}
|
|
46522
46522
|
|
|
46523
|
+
//#endregion
|
|
46524
|
+
//#region src/cli/commands/local-profile-credentials-file.ts
|
|
46525
|
+
/**
|
|
46526
|
+
* Path inside the container where the credentials file is mounted. Fixed
|
|
46527
|
+
* (not user-configurable) so the env-var injection is stable. `/cdkd-aws/`
|
|
46528
|
+
* is outside `/var/task` (the Lambda code mount) and outside `/root/`
|
|
46529
|
+
* (which the user's handler may bind-mount or modify), so there is no
|
|
46530
|
+
* collision risk with the user's payload.
|
|
46531
|
+
*/
|
|
46532
|
+
const CONTAINER_AWS_CREDENTIALS_PATH = "/cdkd-aws/credentials";
|
|
46533
|
+
/**
|
|
46534
|
+
* Write a temporary AWS shared-credentials file containing the resolved
|
|
46535
|
+
* `--profile <name>` credentials, ready to bind-mount into a Lambda
|
|
46536
|
+
* container at {@link CONTAINER_AWS_CREDENTIALS_PATH}.
|
|
46537
|
+
*
|
|
46538
|
+
* The file content is the standard `[profile-name]` INI shape:
|
|
46539
|
+
*
|
|
46540
|
+
* [<profileName>]
|
|
46541
|
+
* aws_access_key_id = <accessKeyId>
|
|
46542
|
+
* aws_secret_access_key = <secretAccessKey>
|
|
46543
|
+
* aws_session_token = <sessionToken> ← only when present
|
|
46544
|
+
*
|
|
46545
|
+
* `aws_session_token` is omitted when the resolved profile produced
|
|
46546
|
+
* long-lived (non-STS) credentials, mirroring the same logic
|
|
46547
|
+
* `applyProfileCredentialsOverlay` uses for env-var injection.
|
|
46548
|
+
*
|
|
46549
|
+
* Caller is responsible for invoking `dispose()` when the container pool
|
|
46550
|
+
* tears down (e.g., on `SIGINT` via `singleFlight` cleanup). Leaving the
|
|
46551
|
+
* file behind in `/tmp` is a security smell (temp credentials live on
|
|
46552
|
+
* disk).
|
|
46553
|
+
*/
|
|
46554
|
+
async function writeProfileCredentialsFile(profileName, creds) {
|
|
46555
|
+
if (profileName === "") throw new Error("writeProfileCredentialsFile: profile name must not be empty.");
|
|
46556
|
+
if (/[\r\n[\]]/.test(profileName)) throw new Error(`writeProfileCredentialsFile: profile name '${profileName}' contains a forbidden character (any of CR, LF, '[', ']' would corrupt the INI file or the docker -e env var).`);
|
|
46557
|
+
const dir = await mkdtemp(path.join(tmpdir(), "cdkd-profile-creds-"));
|
|
46558
|
+
const hostPath = path.join(dir, "credentials");
|
|
46559
|
+
const lines = [
|
|
46560
|
+
`[${profileName}]`,
|
|
46561
|
+
`aws_access_key_id = ${creds.accessKeyId}`,
|
|
46562
|
+
`aws_secret_access_key = ${creds.secretAccessKey}`
|
|
46563
|
+
];
|
|
46564
|
+
if (creds.sessionToken) lines.push(`aws_session_token = ${creds.sessionToken}`);
|
|
46565
|
+
await writeFile(hostPath, lines.join("\n") + "\n", { mode: 384 });
|
|
46566
|
+
return {
|
|
46567
|
+
hostPath,
|
|
46568
|
+
containerPath: CONTAINER_AWS_CREDENTIALS_PATH,
|
|
46569
|
+
profileName,
|
|
46570
|
+
dispose: async () => {
|
|
46571
|
+
await rm(dir, {
|
|
46572
|
+
recursive: true,
|
|
46573
|
+
force: true
|
|
46574
|
+
});
|
|
46575
|
+
}
|
|
46576
|
+
};
|
|
46577
|
+
}
|
|
46578
|
+
|
|
46523
46579
|
//#endregion
|
|
46524
46580
|
//#region src/local/intrinsic-lambda-arn.ts
|
|
46525
46581
|
/**
|
|
@@ -50510,6 +50566,11 @@ function createContainerPool(specs, options) {
|
|
|
50510
50566
|
containerPath: "/opt",
|
|
50511
50567
|
readOnly: true
|
|
50512
50568
|
}] : [];
|
|
50569
|
+
const extraMounts = spec.profileCredentialsFile ? [...optMount, {
|
|
50570
|
+
hostPath: spec.profileCredentialsFile.hostPath,
|
|
50571
|
+
containerPath: spec.profileCredentialsFile.containerPath,
|
|
50572
|
+
readOnly: true
|
|
50573
|
+
}] : optMount;
|
|
50513
50574
|
const containerCodePath = resolveRuntimeCodeMountPath(spec.lambda.runtime);
|
|
50514
50575
|
containerId = await runDetached({
|
|
50515
50576
|
image: resolveRuntimeImage(spec.lambda.runtime),
|
|
@@ -50518,7 +50579,7 @@ function createContainerPool(specs, options) {
|
|
|
50518
50579
|
containerPath: containerCodePath,
|
|
50519
50580
|
readOnly: true
|
|
50520
50581
|
}],
|
|
50521
|
-
extraMounts
|
|
50582
|
+
extraMounts,
|
|
50522
50583
|
env: spec.env,
|
|
50523
50584
|
cmd: [spec.lambda.handler],
|
|
50524
50585
|
hostPort,
|
|
@@ -50531,6 +50592,11 @@ function createContainerPool(specs, options) {
|
|
|
50531
50592
|
} else containerId = await runDetached({
|
|
50532
50593
|
image: spec.image,
|
|
50533
50594
|
mounts: [],
|
|
50595
|
+
...spec.profileCredentialsFile && { extraMounts: [{
|
|
50596
|
+
hostPath: spec.profileCredentialsFile.hostPath,
|
|
50597
|
+
containerPath: spec.profileCredentialsFile.containerPath,
|
|
50598
|
+
readOnly: true
|
|
50599
|
+
}] },
|
|
50534
50600
|
env: spec.env,
|
|
50535
50601
|
cmd: spec.command,
|
|
50536
50602
|
hostPort,
|
|
@@ -55023,6 +55089,7 @@ async function localStartApiCommand(target, options) {
|
|
|
55023
55089
|
const perLambdaConcurrency = parsePerLambdaConcurrency(options.perLambdaConcurrency);
|
|
55024
55090
|
const inlineTmpDirs = /* @__PURE__ */ new Set();
|
|
55025
55091
|
const layerTmpDirs = /* @__PURE__ */ new Set();
|
|
55092
|
+
let profileCredsFile;
|
|
55026
55093
|
const lastAssetPaths = { value: [] };
|
|
55027
55094
|
const authorizerCache = createAuthorizerCache();
|
|
55028
55095
|
const jwksCache = createJwksCache();
|
|
@@ -55094,6 +55161,7 @@ async function localStartApiCommand(target, options) {
|
|
|
55094
55161
|
}
|
|
55095
55162
|
const stateByStack = options.fromState || isCfnFlagPresent(options) ? await loadStateForRoutedStacks(targetStacks, routes, routesWithAuth, options) : /* @__PURE__ */ new Map();
|
|
55096
55163
|
const profileCredentials = options.profile ? await resolveProfileCredentials(options.profile) : void 0;
|
|
55164
|
+
if (options.profile && profileCredentials && !profileCredsFile) profileCredsFile = await writeProfileCredentialsFile(options.profile, profileCredentials);
|
|
55097
55165
|
const lambdaIds = uniqueLambdaIds(routes, routesWithAuth, webSocketApis);
|
|
55098
55166
|
const specs = /* @__PURE__ */ new Map();
|
|
55099
55167
|
for (let i = 0; i < lambdaIds.length; i++) {
|
|
@@ -55111,7 +55179,8 @@ async function localStartApiCommand(target, options) {
|
|
|
55111
55179
|
stateByStack,
|
|
55112
55180
|
skipPull: options.pull === false,
|
|
55113
55181
|
...options.layerRoleArn !== void 0 && { layerRoleArn: options.layerRoleArn },
|
|
55114
|
-
...profileCredentials && { profileCredentials }
|
|
55182
|
+
...profileCredentials && { profileCredentials },
|
|
55183
|
+
...profileCredsFile && { profileCredsFile }
|
|
55115
55184
|
});
|
|
55116
55185
|
specs.set(logicalId, spec);
|
|
55117
55186
|
}
|
|
@@ -55387,6 +55456,11 @@ async function localStartApiCommand(target, options) {
|
|
|
55387
55456
|
} catch (err) {
|
|
55388
55457
|
logger.warn(`Failed to remove merged-layers tmpdir ${dir}: ${err instanceof Error ? err.message : String(err)}`);
|
|
55389
55458
|
}
|
|
55459
|
+
if (profileCredsFile) try {
|
|
55460
|
+
await profileCredsFile.dispose();
|
|
55461
|
+
} catch (err) {
|
|
55462
|
+
logger.warn(`Failed to remove profile credentials tmpdir ${profileCredsFile.hostPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
55463
|
+
}
|
|
55390
55464
|
});
|
|
55391
55465
|
const shutdown = async (signal, exitCode) => {
|
|
55392
55466
|
if (shutdownStarted) {
|
|
@@ -55545,7 +55619,7 @@ function warnIamRoutes(routesWithAuth) {
|
|
|
55545
55619
|
* missing, runtime not supported).
|
|
55546
55620
|
*/
|
|
55547
55621
|
async function buildContainerSpec(args) {
|
|
55548
|
-
const { logicalId, stacks, overrides, assumeRole, containerHost, debugPort, stsRegion, inlineTmpDirs, layerTmpDirs, stateByStack, skipPull, layerRoleArn, profileCredentials } = args;
|
|
55622
|
+
const { logicalId, stacks, overrides, assumeRole, containerHost, debugPort, stsRegion, inlineTmpDirs, layerTmpDirs, stateByStack, skipPull, layerRoleArn, profileCredentials, profileCredsFile } = args;
|
|
55549
55623
|
const lambda = resolveLambdaByLogicalId(logicalId, stacks);
|
|
55550
55624
|
let codeDir;
|
|
55551
55625
|
let optDir;
|
|
@@ -55599,6 +55673,10 @@ async function buildContainerSpec(args) {
|
|
|
55599
55673
|
if (profileCredentials.sessionToken) dockerEnv["AWS_SESSION_TOKEN"] = profileCredentials.sessionToken;
|
|
55600
55674
|
else delete dockerEnv["AWS_SESSION_TOKEN"];
|
|
55601
55675
|
}
|
|
55676
|
+
if (profileCredsFile) {
|
|
55677
|
+
dockerEnv["AWS_SHARED_CREDENTIALS_FILE"] = profileCredsFile.containerPath;
|
|
55678
|
+
dockerEnv["AWS_PROFILE"] = profileCredsFile.profileName;
|
|
55679
|
+
}
|
|
55602
55680
|
}
|
|
55603
55681
|
if (debugPort !== void 0) dockerEnv["NODE_OPTIONS"] = `--inspect-brk=0.0.0.0:${debugPort}`;
|
|
55604
55682
|
const tmpfs = lambda.ephemeralStorageMb !== void 0 ? {
|
|
@@ -55613,7 +55691,11 @@ async function buildContainerSpec(args) {
|
|
|
55613
55691
|
containerHost,
|
|
55614
55692
|
...optDir !== void 0 && { optDir },
|
|
55615
55693
|
...debugPort !== void 0 && { debugPort },
|
|
55616
|
-
...tmpfs !== void 0 && { tmpfs }
|
|
55694
|
+
...tmpfs !== void 0 && { tmpfs },
|
|
55695
|
+
...profileCredsFile && { profileCredentialsFile: {
|
|
55696
|
+
hostPath: profileCredsFile.hostPath,
|
|
55697
|
+
containerPath: profileCredsFile.containerPath
|
|
55698
|
+
} }
|
|
55617
55699
|
};
|
|
55618
55700
|
return {
|
|
55619
55701
|
kind: "image",
|
|
@@ -55626,7 +55708,11 @@ async function buildContainerSpec(args) {
|
|
|
55626
55708
|
env: dockerEnv,
|
|
55627
55709
|
containerHost,
|
|
55628
55710
|
...debugPort !== void 0 && { debugPort },
|
|
55629
|
-
...tmpfs !== void 0 && { tmpfs }
|
|
55711
|
+
...tmpfs !== void 0 && { tmpfs },
|
|
55712
|
+
...profileCredsFile && { profileCredentialsFile: {
|
|
55713
|
+
hostPath: profileCredsFile.hostPath,
|
|
55714
|
+
containerPath: profileCredsFile.containerPath
|
|
55715
|
+
} }
|
|
55630
55716
|
};
|
|
55631
55717
|
}
|
|
55632
55718
|
/**
|
|
@@ -56818,7 +56904,8 @@ async function runEcsTask(task, options, state) {
|
|
|
56818
56904
|
sidecarIp: state.network.sidecarIp,
|
|
56819
56905
|
...options.skipHostPortPublish ? { skipHostPortPublish: true } : {},
|
|
56820
56906
|
...options.addHostFlags && options.addHostFlags.length > 0 ? { addHostFlags: options.addHostFlags } : {},
|
|
56821
|
-
...(options.networkAliasesByContainer?.get(container.name)?.length ?? 0) > 0 ? { networkAliases: options.networkAliasesByContainer.get(container.name) } : {}
|
|
56907
|
+
...(options.networkAliasesByContainer?.get(container.name)?.length ?? 0) > 0 ? { networkAliases: options.networkAliasesByContainer.get(container.name) } : {},
|
|
56908
|
+
...options.profileCredentialsFile && { profileCredentialsFile: options.profileCredentialsFile }
|
|
56822
56909
|
}));
|
|
56823
56910
|
}
|
|
56824
56911
|
const startedByName = /* @__PURE__ */ new Map();
|
|
@@ -57150,6 +57237,7 @@ function buildDockerRunArgs(opts) {
|
|
|
57150
57237
|
const hostPort = pm.hostPort ?? pm.containerPort;
|
|
57151
57238
|
args.push("-p", `${containerHost}:${hostPort}:${pm.containerPort}/${pm.protocol}`);
|
|
57152
57239
|
}
|
|
57240
|
+
if (opts.profileCredentialsFile) args.push("-v", `${opts.profileCredentialsFile.hostPath}:${opts.profileCredentialsFile.containerPath}:ro`);
|
|
57153
57241
|
for (const mp of container.mountPoints) {
|
|
57154
57242
|
const v = volumeByName.get(mp.sourceVolume);
|
|
57155
57243
|
if (!v) continue;
|
|
@@ -57171,6 +57259,10 @@ function buildDockerRunArgs(opts) {
|
|
|
57171
57259
|
...opts.sidecarIp !== void 0 && { sidecarIp: opts.sidecarIp }
|
|
57172
57260
|
});
|
|
57173
57261
|
Object.assign(finalEnv, metaEnv);
|
|
57262
|
+
if (opts.profileCredentialsFile) {
|
|
57263
|
+
finalEnv["AWS_SHARED_CREDENTIALS_FILE"] = opts.profileCredentialsFile.containerPath;
|
|
57264
|
+
finalEnv["AWS_PROFILE"] = opts.profileCredentialsFile.profileName;
|
|
57265
|
+
}
|
|
57174
57266
|
Object.assign(finalEnv, container.environment);
|
|
57175
57267
|
for (const s of secrets) finalEnv[s.name] = s.value;
|
|
57176
57268
|
const overrides = opts.envOverrides;
|
|
@@ -57240,6 +57332,7 @@ async function localRunTaskCommand(target, options) {
|
|
|
57240
57332
|
let sigintHandler;
|
|
57241
57333
|
let sigintCount = 0;
|
|
57242
57334
|
let stateProvider;
|
|
57335
|
+
let profileCredsFile;
|
|
57243
57336
|
let cleanupPromise;
|
|
57244
57337
|
const cleanup = async () => {
|
|
57245
57338
|
if (!cleanupPromise) cleanupPromise = (async () => {
|
|
@@ -57248,6 +57341,11 @@ async function localRunTaskCommand(target, options) {
|
|
|
57248
57341
|
} catch (err) {
|
|
57249
57342
|
getLogger().debug(`cleanup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
57250
57343
|
}
|
|
57344
|
+
if (profileCredsFile) try {
|
|
57345
|
+
await profileCredsFile.dispose();
|
|
57346
|
+
} catch (err) {
|
|
57347
|
+
getLogger().debug(`Failed to remove profile credentials tmpdir ${profileCredsFile.hostPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
57348
|
+
}
|
|
57251
57349
|
})();
|
|
57252
57350
|
await cleanupPromise;
|
|
57253
57351
|
};
|
|
@@ -57309,6 +57407,7 @@ async function localRunTaskCommand(target, options) {
|
|
|
57309
57407
|
assumedCredentials = await assumeTaskRole$1(resolvedRoleArn, options.region);
|
|
57310
57408
|
}
|
|
57311
57409
|
const sidecarCredentials = await resolveSidecarCredentials(options, assumedCredentials);
|
|
57410
|
+
if (options.profile && sidecarCredentials && !assumedCredentials) profileCredsFile = await writeProfileCredentialsFile(options.profile, sidecarCredentials);
|
|
57312
57411
|
const envOverrides = readEnvOverridesFile$2(options.envVars);
|
|
57313
57412
|
const runOpts = {
|
|
57314
57413
|
cluster: options.cluster,
|
|
@@ -57323,6 +57422,11 @@ async function localRunTaskCommand(target, options) {
|
|
|
57323
57422
|
if (options.platform) runOpts.platformOverride = options.platform;
|
|
57324
57423
|
if (options.region) runOpts.region = options.region;
|
|
57325
57424
|
if (options.ecrRoleArn) runOpts.ecrRoleArn = options.ecrRoleArn;
|
|
57425
|
+
if (profileCredsFile) runOpts.profileCredentialsFile = {
|
|
57426
|
+
hostPath: profileCredsFile.hostPath,
|
|
57427
|
+
containerPath: profileCredsFile.containerPath,
|
|
57428
|
+
profileName: profileCredsFile.profileName
|
|
57429
|
+
};
|
|
57326
57430
|
const result = await runEcsTask(task, runOpts, state);
|
|
57327
57431
|
if (options.detach) {
|
|
57328
57432
|
logger.info("Task containers started in detached mode; cdkd is exiting.");
|
|
@@ -58573,6 +58677,7 @@ async function localStartServiceCommand(targets, options) {
|
|
|
58573
58677
|
let sigintHandler;
|
|
58574
58678
|
let sigintCount = 0;
|
|
58575
58679
|
let sharedNetwork;
|
|
58680
|
+
let profileCredsFile;
|
|
58576
58681
|
const cleanup = singleFlight(async () => {
|
|
58577
58682
|
await Promise.allSettled(perTarget.map(async (pt) => {
|
|
58578
58683
|
if (pt.controller) await pt.controller.shutdown();
|
|
@@ -58581,6 +58686,14 @@ async function localStartServiceCommand(targets, options) {
|
|
|
58581
58686
|
await Promise.allSettled(pt.runState.replicas.map((r) => cleanupEcsRun(r.state, { keepRunning: false }).catch(() => void 0)));
|
|
58582
58687
|
}
|
|
58583
58688
|
}));
|
|
58689
|
+
if (profileCredsFile) {
|
|
58690
|
+
try {
|
|
58691
|
+
await profileCredsFile.dispose();
|
|
58692
|
+
} catch (err) {
|
|
58693
|
+
getLogger().warn(`Failed to remove profile credentials tmpdir ${profileCredsFile.hostPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
58694
|
+
}
|
|
58695
|
+
profileCredsFile = void 0;
|
|
58696
|
+
}
|
|
58584
58697
|
if (sharedNetwork) {
|
|
58585
58698
|
try {
|
|
58586
58699
|
await destroyTaskNetwork(sharedNetwork);
|
|
@@ -58629,6 +58742,7 @@ async function localStartServiceCommand(targets, options) {
|
|
|
58629
58742
|
} catch (err) {
|
|
58630
58743
|
throw new LocalStartServiceError(`Failed to create shared service network: ${err instanceof Error ? err.message : String(err)}`);
|
|
58631
58744
|
}
|
|
58745
|
+
if (options.profile && sidecarCredentials) profileCredsFile = await writeProfileCredentialsFile(options.profile, sidecarCredentials);
|
|
58632
58746
|
const discovery = {
|
|
58633
58747
|
registry,
|
|
58634
58748
|
cloudMapIndexByStack,
|
|
@@ -58645,7 +58759,7 @@ async function localStartServiceCommand(targets, options) {
|
|
|
58645
58759
|
};
|
|
58646
58760
|
process.on("SIGINT", sigintHandler);
|
|
58647
58761
|
process.on("SIGTERM", sigintHandler);
|
|
58648
|
-
for (const pt of perTarget) pt.controller = await bootOneTarget(pt.target, pt.runState, stacks, options, discovery, skipPull);
|
|
58762
|
+
for (const pt of perTarget) pt.controller = await bootOneTarget(pt.target, pt.runState, stacks, options, discovery, skipPull, profileCredsFile);
|
|
58649
58763
|
const summary = perTarget.map((pt) => `${pt.controller.service.serviceName} (${pt.controller.activeReplicaCount()} replica(s))`).join(", ");
|
|
58650
58764
|
logger.info(`Service(s) running: ${summary}. Press ^C to shut down.`);
|
|
58651
58765
|
await Promise.all(perTarget.map((pt) => pt.controller.waitForShutdown()));
|
|
@@ -58663,16 +58777,16 @@ async function localStartServiceCommand(targets, options) {
|
|
|
58663
58777
|
* options) is scoped locally. Returns the started controller for the
|
|
58664
58778
|
* outer code to wait + tear down.
|
|
58665
58779
|
*/
|
|
58666
|
-
async function bootOneTarget(target, runState, stacks, options, discovery, skipPull) {
|
|
58780
|
+
async function bootOneTarget(target, runState, stacks, options, discovery, skipPull, profileCredsFile) {
|
|
58667
58781
|
const candidate = pickCandidateStack(parseEcsTarget(target).stackPattern, stacks);
|
|
58668
58782
|
const stateProvider = createLocalStateProvider(options, candidate?.stackName ?? "", candidate?.region);
|
|
58669
58783
|
try {
|
|
58670
|
-
return await runOneTarget(target, runState, stacks, options, discovery, skipPull, stateProvider);
|
|
58784
|
+
return await runOneTarget(target, runState, stacks, options, discovery, skipPull, stateProvider, profileCredsFile);
|
|
58671
58785
|
} finally {
|
|
58672
58786
|
if (stateProvider) stateProvider.dispose();
|
|
58673
58787
|
}
|
|
58674
58788
|
}
|
|
58675
|
-
async function runOneTarget(target, runState, stacks, options, discovery, skipPull, stateProvider) {
|
|
58789
|
+
async function runOneTarget(target, runState, stacks, options, discovery, skipPull, stateProvider, profileCredsFile) {
|
|
58676
58790
|
const logger = getLogger();
|
|
58677
58791
|
const imageContext = await buildEcsImageResolutionContext(target, stacks, options, stateProvider);
|
|
58678
58792
|
const service = resolveEcsServiceTarget(target, stacks, imageContext);
|
|
@@ -58718,6 +58832,11 @@ async function runOneTarget(target, runState, stacks, options, discovery, skipPu
|
|
|
58718
58832
|
if (options.platform) taskOpts.platformOverride = options.platform;
|
|
58719
58833
|
if (options.region) taskOpts.region = options.region;
|
|
58720
58834
|
if (options.ecrRoleArn) taskOpts.ecrRoleArn = options.ecrRoleArn;
|
|
58835
|
+
if (profileCredsFile && !assumedCredentials) taskOpts.profileCredentialsFile = {
|
|
58836
|
+
hostPath: profileCredsFile.hostPath,
|
|
58837
|
+
containerPath: profileCredsFile.containerPath,
|
|
58838
|
+
profileName: profileCredsFile.profileName
|
|
58839
|
+
};
|
|
58721
58840
|
return startEcsService(service, {
|
|
58722
58841
|
maxTasks: options.maxTasks,
|
|
58723
58842
|
restartPolicy: options.restartPolicy,
|
|
@@ -58928,6 +59047,7 @@ async function localInvokeCommand(target, options) {
|
|
|
58928
59047
|
let containerId;
|
|
58929
59048
|
let stopLogs;
|
|
58930
59049
|
let sigintHandler;
|
|
59050
|
+
let profileCredsFile;
|
|
58931
59051
|
/**
|
|
58932
59052
|
* Unified cleanup for both the success / failure unwind path AND the
|
|
58933
59053
|
* SIGINT handler. Idempotent — every step guards on its own undefined
|
|
@@ -58976,6 +59096,11 @@ async function localInvokeCommand(target, options) {
|
|
|
58976
59096
|
} catch (err) {
|
|
58977
59097
|
getLogger().debug(`Failed to remove ARN-layer tmpdir ${dir}: ${err instanceof Error ? err.message : String(err)}`);
|
|
58978
59098
|
}
|
|
59099
|
+
if (profileCredsFile) try {
|
|
59100
|
+
await profileCredsFile.dispose();
|
|
59101
|
+
} catch (err) {
|
|
59102
|
+
getLogger().debug(`Failed to remove profile credentials tmpdir ${profileCredsFile.hostPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
59103
|
+
}
|
|
58979
59104
|
}, (err) => {
|
|
58980
59105
|
getLogger().debug(`cleanup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
58981
59106
|
});
|
|
@@ -58986,6 +59111,7 @@ async function localInvokeCommand(target, options) {
|
|
|
58986
59111
|
});
|
|
58987
59112
|
await ensureDockerAvailable();
|
|
58988
59113
|
const profileCredentials = options.profile ? await resolveProfileCredentials(options.profile) : void 0;
|
|
59114
|
+
if (options.profile && profileCredentials) profileCredsFile = await writeProfileCredentialsFile(options.profile, profileCredentials);
|
|
58989
59115
|
const appCmd = resolveApp(options.app);
|
|
58990
59116
|
if (!appCmd) throw new Error("No CDK app specified. Pass --app, set CDKD_APP, or add \"app\" to cdk.json.");
|
|
58991
59117
|
logger.info("Synthesizing CDK app...");
|
|
@@ -59086,6 +59212,10 @@ async function localInvokeCommand(target, options) {
|
|
|
59086
59212
|
if (!assumeSucceeded) {
|
|
59087
59213
|
forwardAwsEnv(dockerEnv);
|
|
59088
59214
|
applyProfileCredentialsOverlay(dockerEnv, profileCredentials, false);
|
|
59215
|
+
if (profileCredsFile) {
|
|
59216
|
+
dockerEnv["AWS_SHARED_CREDENTIALS_FILE"] = profileCredsFile.containerPath;
|
|
59217
|
+
dockerEnv["AWS_PROFILE"] = profileCredsFile.profileName;
|
|
59218
|
+
}
|
|
59089
59219
|
}
|
|
59090
59220
|
let debugPort;
|
|
59091
59221
|
if (options.debugPort) {
|
|
@@ -59098,10 +59228,15 @@ async function localInvokeCommand(target, options) {
|
|
|
59098
59228
|
const containerHost = options.containerHost;
|
|
59099
59229
|
if (lambda.layers.length > 0) logger.info(`Mounting ${lambda.layers.length} Lambda layer${lambda.layers.length === 1 ? "" : "s"} at /opt`);
|
|
59100
59230
|
logger.info(`Starting container (image=${imagePlan.image}, port=${hostPort})...`);
|
|
59231
|
+
const extraMountsWithProfile = profileCredsFile ? [...imagePlan.extraMounts ?? [], {
|
|
59232
|
+
hostPath: profileCredsFile.hostPath,
|
|
59233
|
+
containerPath: profileCredsFile.containerPath,
|
|
59234
|
+
readOnly: true
|
|
59235
|
+
}] : imagePlan.extraMounts;
|
|
59101
59236
|
containerId = await runDetached({
|
|
59102
59237
|
image: imagePlan.image,
|
|
59103
59238
|
mounts: imagePlan.mounts,
|
|
59104
|
-
extraMounts:
|
|
59239
|
+
extraMounts: extraMountsWithProfile,
|
|
59105
59240
|
env: dockerEnv,
|
|
59106
59241
|
cmd: imagePlan.cmd,
|
|
59107
59242
|
hostPort,
|
|
@@ -60780,7 +60915,7 @@ function reorderArgs(argv) {
|
|
|
60780
60915
|
*/
|
|
60781
60916
|
async function main() {
|
|
60782
60917
|
const program = new Command();
|
|
60783
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.167.
|
|
60918
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.167.3");
|
|
60784
60919
|
program.addCommand(createBootstrapCommand());
|
|
60785
60920
|
program.addCommand(createSynthCommand());
|
|
60786
60921
|
program.addCommand(createListCommand());
|