cdk-local 0.27.0 → 0.28.1
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 +2 -0
- package/dist/cli.js +2 -2
- package/dist/index.d.ts +87 -71
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/{local-list-KUEmeW9J.js → local-list-CY18YQf1.js} +226 -8
- package/dist/local-list-CY18YQf1.js.map +1 -0
- package/package.json +1 -1
- package/dist/local-list-KUEmeW9J.js.map +0 -1
|
@@ -10,6 +10,7 @@ import { AssetManifestArtifact } from "@aws-cdk/cloud-assembly-api";
|
|
|
10
10
|
import { BaseCredentials, CdkAppMultiContext, NonInteractiveIoHost, Toolkit } from "@aws-cdk/toolkit-lib";
|
|
11
11
|
import { CloudFormationClient, DescribeStacksCommand, ListExportsCommand, ListStackResourcesCommand } from "@aws-sdk/client-cloudformation";
|
|
12
12
|
import { GetFunctionConfigurationCommand, LambdaClient } from "@aws-sdk/client-lambda";
|
|
13
|
+
import { GetParameterCommand, GetParametersCommand, SSMClient } from "@aws-sdk/client-ssm";
|
|
13
14
|
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
14
15
|
import { Readable } from "node:stream";
|
|
15
16
|
import { pipeline } from "node:stream/promises";
|
|
@@ -27,7 +28,6 @@ import { createServer as createServer$2 } from "node:https";
|
|
|
27
28
|
import * as chokidar from "chokidar";
|
|
28
29
|
import graphlib from "graphlib";
|
|
29
30
|
import { GetSecretValueCommand, SecretsManagerClient } from "@aws-sdk/client-secrets-manager";
|
|
30
|
-
import { GetParameterCommand, SSMClient } from "@aws-sdk/client-ssm";
|
|
31
31
|
|
|
32
32
|
//#region src/cli/options.ts
|
|
33
33
|
/**
|
|
@@ -2278,10 +2278,19 @@ function mapStackArtifact(stack) {
|
|
|
2278
2278
|
* Thin wrapper around {@link AssemblyReader} that mimics cdkd's
|
|
2279
2279
|
* `Synthesizer` API so the ported `cdkl invoke` / `start-api` /
|
|
2280
2280
|
* `run-task` / `start-service` source compiles without rewrites.
|
|
2281
|
+
*
|
|
2282
|
+
* When `app` resolves to an existing directory it is read as a
|
|
2283
|
+
* pre-synthesized cloud assembly (no subprocess synth); otherwise it is
|
|
2284
|
+
* executed as the CDK app command.
|
|
2281
2285
|
*/
|
|
2282
2286
|
var Synthesizer = class {
|
|
2283
2287
|
async synthesize(opts) {
|
|
2284
2288
|
const reader = new AssemblyReader();
|
|
2289
|
+
const appPath = resolve(opts.app);
|
|
2290
|
+
if (existsSync(appPath) && statSync(appPath).isDirectory()) {
|
|
2291
|
+
getLogger().debug(`Using pre-synthesized cloud assembly at ${appPath}`);
|
|
2292
|
+
return { stacks: await reader.readFromDirectory(appPath) };
|
|
2293
|
+
}
|
|
2285
2294
|
const readOpts = {};
|
|
2286
2295
|
if (opts.output !== void 0) readOpts.outdir = opts.output;
|
|
2287
2296
|
const env = {};
|
|
@@ -2354,6 +2363,156 @@ function resolveWatchConfig() {
|
|
|
2354
2363
|
};
|
|
2355
2364
|
}
|
|
2356
2365
|
|
|
2366
|
+
//#endregion
|
|
2367
|
+
//#region src/local/ssm-parameter-resolver.ts
|
|
2368
|
+
/**
|
|
2369
|
+
* Resolve CloudFormation template `Parameters` of the SSM-backed types
|
|
2370
|
+
* `AWS::SSM::Parameter::Value<String>` / `AWS::SSM::Parameter::Value<List<String>>`
|
|
2371
|
+
* (what CDK synthesizes for `ssm.StringParameter.valueForStringParameter(...)`)
|
|
2372
|
+
* into their deployed values via SSM Parameter Store.
|
|
2373
|
+
*
|
|
2374
|
+
* Motivation (issue #94): a container / Lambda env var that `Ref`s such a
|
|
2375
|
+
* parameter cannot be resolved from the `--from-cfn-stack` state source.
|
|
2376
|
+
* That source is built from `ListStackResources` (deployed RESOURCES); a
|
|
2377
|
+
* CloudFormation PARAMETER is not a resource, so the `Ref` misses
|
|
2378
|
+
* `context.resources[<id>]` in `state-resolver.ts` and the env var is
|
|
2379
|
+
* warn-and-dropped. The synthesized template, however, carries the SSM
|
|
2380
|
+
* parameter NAME in each entry's `Default`:
|
|
2381
|
+
*
|
|
2382
|
+
* "Parameters": {
|
|
2383
|
+
* "SsmParameterValue...Parameter": {
|
|
2384
|
+
* "Type": "AWS::SSM::Parameter::Value<String>",
|
|
2385
|
+
* "Default": "/path/to/the/parameter"
|
|
2386
|
+
* }
|
|
2387
|
+
* }
|
|
2388
|
+
*
|
|
2389
|
+
* and the run already has working AWS credentials / region (the same ones
|
|
2390
|
+
* `--from-cfn-stack` uses for `ListStackResources`). This module reads each
|
|
2391
|
+
* parameter NAME from `Default`, batch-resolves the values via SSM
|
|
2392
|
+
* `GetParameters`, and returns a `logicalId -> value` map the CLI feeds
|
|
2393
|
+
* into the substitution context so a `Ref` to the parameter's logical id
|
|
2394
|
+
* resolves to the value instead of being dropped.
|
|
2395
|
+
*
|
|
2396
|
+
* Best-effort by design: on any SSM failure (no credentials, access
|
|
2397
|
+
* denied, throttling) the helper logs a warn and returns whatever it
|
|
2398
|
+
* could resolve (possibly nothing) — the caller then falls back to the
|
|
2399
|
+
* existing warn-and-drop behavior on the affected `Ref`s. It NEVER throws
|
|
2400
|
+
* out of the substitution pass.
|
|
2401
|
+
*/
|
|
2402
|
+
/** SSM-backed CFn parameter types CDK synthesizes for SSM lookups. */
|
|
2403
|
+
const SSM_STRING_TYPE = "AWS::SSM::Parameter::Value<String>";
|
|
2404
|
+
const SSM_LIST_TYPE = "AWS::SSM::Parameter::Value<List<String>>";
|
|
2405
|
+
/**
|
|
2406
|
+
* Scan a synthesized template's `Parameters` block for entries whose
|
|
2407
|
+
* `Type` is one of the SSM-backed parameter types AND whose `Default`
|
|
2408
|
+
* carries a usable SSM parameter name. Pure — no AWS calls.
|
|
2409
|
+
*
|
|
2410
|
+
* Entries without a non-empty string `Default` are skipped (CDK always
|
|
2411
|
+
* synthesizes the parameter name into `Default` for the
|
|
2412
|
+
* `valueForStringParameter` shape; a parameter declared without a default
|
|
2413
|
+
* has no name we can resolve, so it stays warn-and-drop).
|
|
2414
|
+
*
|
|
2415
|
+
* Exported for unit testing.
|
|
2416
|
+
*/
|
|
2417
|
+
function collectSsmParameterRefs(template) {
|
|
2418
|
+
const params = template?.Parameters;
|
|
2419
|
+
if (!params) return [];
|
|
2420
|
+
const out = [];
|
|
2421
|
+
for (const [logicalId, entry] of Object.entries(params)) {
|
|
2422
|
+
if (!entry || typeof entry !== "object") continue;
|
|
2423
|
+
const type = entry.Type;
|
|
2424
|
+
const isList = type === SSM_LIST_TYPE;
|
|
2425
|
+
if (type !== SSM_STRING_TYPE && !isList) continue;
|
|
2426
|
+
const ssmName = entry.Default;
|
|
2427
|
+
if (typeof ssmName !== "string" || ssmName.length === 0) continue;
|
|
2428
|
+
out.push({
|
|
2429
|
+
logicalId,
|
|
2430
|
+
ssmName,
|
|
2431
|
+
isList
|
|
2432
|
+
});
|
|
2433
|
+
}
|
|
2434
|
+
return out;
|
|
2435
|
+
}
|
|
2436
|
+
/**
|
|
2437
|
+
* Batch-resolve a set of {@link SsmParameterRef}s via SSM `GetParameters`
|
|
2438
|
+
* and return a `logicalId -> resolved value` map. `List<String>`
|
|
2439
|
+
* parameters are comma-joined (CloudFormation surfaces the list type as a
|
|
2440
|
+
* comma-delimited string when the value is consumed as a `Ref`).
|
|
2441
|
+
*
|
|
2442
|
+
* `GetParameters` accepts up to 10 names per call, so the refs are
|
|
2443
|
+
* chunked. Names that SSM reports as invalid (`InvalidParameters`) are
|
|
2444
|
+
* left out of the result map so the caller falls back to warn-and-drop
|
|
2445
|
+
* on the corresponding `Ref`. `WithDecryption: true` is set so Secure
|
|
2446
|
+
* String parameters resolve too (matching how CloudFormation resolves
|
|
2447
|
+
* the `AWS::SSM::Parameter::Value<String>` type at deploy time).
|
|
2448
|
+
*
|
|
2449
|
+
* Security note: a decrypted SecureString value resolved here is then
|
|
2450
|
+
* baked into the container's `Environment` like any other resolved env
|
|
2451
|
+
* value, so it follows the standard plaintext-env exposure path — it can
|
|
2452
|
+
* appear on the `docker run -e KEY=VALUE` argv (visible in host `ps`) and
|
|
2453
|
+
* is not redacted by `redactAwsCredentialsInArgs` (which only covers
|
|
2454
|
+
* `SENSITIVE_ENV_KEYS`). This mirrors the deployed Lambda/ECS env and is
|
|
2455
|
+
* the same inherent exposure documented in `docker-runner`; routing
|
|
2456
|
+
* SecureString-resolved values through the value-from-process-env form is
|
|
2457
|
+
* tracked as a follow-up.
|
|
2458
|
+
*
|
|
2459
|
+
* Best-effort: a failed `GetParameters` chunk logs a warn and is skipped
|
|
2460
|
+
* (the other chunks still contribute their values); the function never
|
|
2461
|
+
* throws.
|
|
2462
|
+
*
|
|
2463
|
+
* `label` is the state-source label (e.g. `--from-cfn-stack`) used to
|
|
2464
|
+
* prefix warns so the user can tell which source produced them.
|
|
2465
|
+
*
|
|
2466
|
+
* Exported for unit testing.
|
|
2467
|
+
*/
|
|
2468
|
+
async function resolveSsmParameters(client, refs, label) {
|
|
2469
|
+
const out = {};
|
|
2470
|
+
if (refs.length === 0) return out;
|
|
2471
|
+
const logger = getLogger();
|
|
2472
|
+
const CHUNK = 10;
|
|
2473
|
+
const byName = /* @__PURE__ */ new Map();
|
|
2474
|
+
for (const ref of refs) {
|
|
2475
|
+
const list = byName.get(ref.ssmName);
|
|
2476
|
+
if (list) list.push(ref);
|
|
2477
|
+
else byName.set(ref.ssmName, [ref]);
|
|
2478
|
+
}
|
|
2479
|
+
const uniqueNames = [...byName.keys()];
|
|
2480
|
+
for (let i = 0; i < uniqueNames.length; i += CHUNK) {
|
|
2481
|
+
const names = uniqueNames.slice(i, i + CHUNK);
|
|
2482
|
+
let resolved;
|
|
2483
|
+
try {
|
|
2484
|
+
const resp = await client.send(new GetParametersCommand({
|
|
2485
|
+
Names: names,
|
|
2486
|
+
WithDecryption: true
|
|
2487
|
+
}));
|
|
2488
|
+
resolved = resp.Parameters ?? [];
|
|
2489
|
+
const invalid = resp.InvalidParameters ?? [];
|
|
2490
|
+
if (invalid.length > 0) logger.warn(`${label}: SSM GetParameters reported invalid parameter name(s): ${invalid.join(", ")}. Ref to the matching CloudFormation parameter(s) will warn-and-drop (was the SSM parameter created?).`);
|
|
2491
|
+
} catch (err) {
|
|
2492
|
+
logger.warn(`${label}: SSM GetParameters(${names.join(", ")}) failed: ${formatSsmError(err)}. Ref to the matching CloudFormation parameter(s) will warn-and-drop (grant ssm:GetParameters or override via --env-vars).`);
|
|
2493
|
+
continue;
|
|
2494
|
+
}
|
|
2495
|
+
for (const p of resolved) {
|
|
2496
|
+
if (typeof p.Name !== "string" || typeof p.Value !== "string") continue;
|
|
2497
|
+
const requesters = byName.get(p.Name);
|
|
2498
|
+
if (!requesters) continue;
|
|
2499
|
+
for (const ref of requesters) out[ref.logicalId] = p.Value;
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
return out;
|
|
2503
|
+
}
|
|
2504
|
+
/**
|
|
2505
|
+
* Format an SSM SDK error as `<name>: <message>` so the warn names the
|
|
2506
|
+
* error class (e.g. `AccessDeniedException`, `ThrottlingException`).
|
|
2507
|
+
* Mirrors `formatAwsErrorForWarn` in `cfn-local-state-provider.ts`.
|
|
2508
|
+
* Exported for unit testing.
|
|
2509
|
+
*/
|
|
2510
|
+
function formatSsmError(err) {
|
|
2511
|
+
if (!(err instanceof Error)) return String(err);
|
|
2512
|
+
const name = err.name && err.name !== "Error" ? err.name : void 0;
|
|
2513
|
+
return name !== void 0 ? `${name}: ${err.message}` : err.message;
|
|
2514
|
+
}
|
|
2515
|
+
|
|
2357
2516
|
//#endregion
|
|
2358
2517
|
//#region src/local/cfn-local-state-provider.ts
|
|
2359
2518
|
/**
|
|
@@ -2425,6 +2584,7 @@ var CfnLocalStateProvider = class {
|
|
|
2425
2584
|
region;
|
|
2426
2585
|
client;
|
|
2427
2586
|
lambdaClient;
|
|
2587
|
+
ssmClient;
|
|
2428
2588
|
clientOptions;
|
|
2429
2589
|
disposed = false;
|
|
2430
2590
|
constructor(opts) {
|
|
@@ -2449,6 +2609,31 @@ var CfnLocalStateProvider = class {
|
|
|
2449
2609
|
});
|
|
2450
2610
|
return this.lambdaClient;
|
|
2451
2611
|
}
|
|
2612
|
+
getSsmClient() {
|
|
2613
|
+
if (this.disposed) throw new Error("CfnLocalStateProvider used after dispose()");
|
|
2614
|
+
if (!this.ssmClient) this.ssmClient = new SSMClient({
|
|
2615
|
+
region: this.region,
|
|
2616
|
+
...this.clientOptions.profile !== void 0 && { profile: this.clientOptions.profile }
|
|
2617
|
+
});
|
|
2618
|
+
return this.ssmClient;
|
|
2619
|
+
}
|
|
2620
|
+
/**
|
|
2621
|
+
* Resolve the synthesized template's SSM-backed `Parameters`
|
|
2622
|
+
* (`AWS::SSM::Parameter::Value<String>` /
|
|
2623
|
+
* `AWS::SSM::Parameter::Value<List<String>>`) into a
|
|
2624
|
+
* `parameterLogicalId -> value` map via SSM Parameter Store. See
|
|
2625
|
+
* {@link LocalStateProvider.resolveTemplateSsmParameters}.
|
|
2626
|
+
*
|
|
2627
|
+
* Returns an empty map (and opens no SSM client) when the template
|
|
2628
|
+
* declares no SSM-backed parameters. Best-effort: SSM failures are
|
|
2629
|
+
* absorbed inside {@link resolveSsmParameters} with a per-chunk warn.
|
|
2630
|
+
*/
|
|
2631
|
+
async resolveTemplateSsmParameters(template) {
|
|
2632
|
+
if (this.disposed) throw new Error("CfnLocalStateProvider used after dispose()");
|
|
2633
|
+
const refs = collectSsmParameterRefs(template);
|
|
2634
|
+
if (refs.length === 0) return {};
|
|
2635
|
+
return resolveSsmParameters(this.getSsmClient(), refs, this.label);
|
|
2636
|
+
}
|
|
2452
2637
|
/**
|
|
2453
2638
|
* Read a deployed Lambda function's already-resolved
|
|
2454
2639
|
* `Environment.Variables` via `lambda:GetFunctionConfiguration`. See
|
|
@@ -2560,6 +2745,10 @@ var CfnLocalStateProvider = class {
|
|
|
2560
2745
|
this.lambdaClient.destroy();
|
|
2561
2746
|
this.lambdaClient = void 0;
|
|
2562
2747
|
}
|
|
2748
|
+
if (this.ssmClient) {
|
|
2749
|
+
this.ssmClient.destroy();
|
|
2750
|
+
this.ssmClient = void 0;
|
|
2751
|
+
}
|
|
2563
2752
|
}
|
|
2564
2753
|
};
|
|
2565
2754
|
/**
|
|
@@ -3983,14 +4172,19 @@ function resolveRef(arg, context) {
|
|
|
3983
4172
|
};
|
|
3984
4173
|
if (arg.startsWith("AWS::")) return resolvePseudoParameter(arg, context.pseudoParameters);
|
|
3985
4174
|
const resource = context.resources[arg];
|
|
3986
|
-
if (
|
|
3987
|
-
kind: "unresolved",
|
|
3988
|
-
reason: `Ref '${arg}': no record in the state source (was the resource deployed?)`
|
|
3989
|
-
};
|
|
3990
|
-
return {
|
|
4175
|
+
if (resource) return {
|
|
3991
4176
|
kind: "literal",
|
|
3992
4177
|
value: resource.physicalId
|
|
3993
4178
|
};
|
|
4179
|
+
const parameterValue = context.parameters?.[arg];
|
|
4180
|
+
if (parameterValue !== void 0) return {
|
|
4181
|
+
kind: "literal",
|
|
4182
|
+
value: parameterValue
|
|
4183
|
+
};
|
|
4184
|
+
return {
|
|
4185
|
+
kind: "unresolved",
|
|
4186
|
+
reason: `Ref '${arg}': no record in the state source (was the resource deployed, or is it a CloudFormation parameter that could not be resolved — e.g. an SSM-backed AWS::SSM::Parameter::Value parameter whose SSM value was not readable?)`
|
|
4187
|
+
};
|
|
3994
4188
|
}
|
|
3995
4189
|
function resolvePseudoParameter(name, pseudo) {
|
|
3996
4190
|
if (!pseudo) return {
|
|
@@ -5110,6 +5304,7 @@ function buildSubstitutionContextFromImageContext(context) {
|
|
|
5110
5304
|
if (!context?.stateResources) return void 0;
|
|
5111
5305
|
const subContext = { resources: context.stateResources };
|
|
5112
5306
|
if (context.pseudoParameters) subContext.pseudoParameters = { ...context.pseudoParameters };
|
|
5307
|
+
if (context.stateParameters) subContext.parameters = { ...context.stateParameters };
|
|
5113
5308
|
return subContext;
|
|
5114
5309
|
}
|
|
5115
5310
|
/**
|
|
@@ -7139,6 +7334,10 @@ async function localInvokeCommand(target, options, extraStateProviders) {
|
|
|
7139
7334
|
const pseudo = await resolvePseudoParametersForInvoke(lambda.stack.region, options);
|
|
7140
7335
|
if (pseudo) subContext.pseudoParameters = pseudo;
|
|
7141
7336
|
}
|
|
7337
|
+
if (envHasIntrinsicValue$1(templateEnv) && stateProvider.resolveTemplateSsmParameters) {
|
|
7338
|
+
const ssmParams = await stateProvider.resolveTemplateSsmParameters(lambda.stack.template);
|
|
7339
|
+
if (Object.keys(ssmParams).length > 0) subContext.parameters = ssmParams;
|
|
7340
|
+
}
|
|
7142
7341
|
if (envHasCrossStackIntrinsic(templateEnv)) {
|
|
7143
7342
|
const resolver = await stateProvider.buildCrossStackResolver(loaded.region);
|
|
7144
7343
|
if (resolver) subContext.crossStackResolver = resolver;
|
|
@@ -15468,6 +15667,7 @@ async function buildContainerSpec(args) {
|
|
|
15468
15667
|
if (stateBundle) {
|
|
15469
15668
|
const context = { resources: stateBundle.state.resources };
|
|
15470
15669
|
if (stateBundle.pseudoParameters) context.pseudoParameters = stateBundle.pseudoParameters;
|
|
15670
|
+
if (stateBundle.ssmParameters) context.parameters = stateBundle.ssmParameters;
|
|
15471
15671
|
const { env, audit } = substituteEnvVarsFromState(templateEnv, context);
|
|
15472
15672
|
templateEnv = env;
|
|
15473
15673
|
for (const key of audit.resolvedKeys) getLogger().debug(`Lambda ${logicalId}: state source substituted env var ${key}`);
|
|
@@ -16277,6 +16477,10 @@ async function loadStateForRoutedStacks(stacks, routes, routesWithAuth, options,
|
|
|
16277
16477
|
}
|
|
16278
16478
|
if (deployedEnvByLambda.size > 0) bundle.deployedEnvByLambda = deployedEnvByLambda;
|
|
16279
16479
|
}
|
|
16480
|
+
if (stackHasIntrinsicEnv(stackName) && provider.resolveTemplateSsmParameters) {
|
|
16481
|
+
const ssmParameters = await provider.resolveTemplateSsmParameters(stack.template);
|
|
16482
|
+
if (Object.keys(ssmParameters).length > 0) bundle.ssmParameters = ssmParameters;
|
|
16483
|
+
}
|
|
16280
16484
|
out.set(stackName, bundle);
|
|
16281
16485
|
logger.debug(`${provider.label}: loaded state for ${stackName} (${loaded.region})`);
|
|
16282
16486
|
} finally {
|
|
@@ -17441,6 +17645,7 @@ async function localRunTaskCommand(target, options, extraStateProviders) {
|
|
|
17441
17645
|
if (resolver) await applyCrossStackResolverToTask(task, {
|
|
17442
17646
|
resources: imageContext?.stateResources ?? {},
|
|
17443
17647
|
...imageContext?.pseudoParameters && { pseudoParameters: imageContext.pseudoParameters },
|
|
17648
|
+
...imageContext?.stateParameters && { parameters: imageContext.stateParameters },
|
|
17444
17649
|
consumerRegion,
|
|
17445
17650
|
crossStackResolver: resolver
|
|
17446
17651
|
});
|
|
@@ -17578,6 +17783,10 @@ async function buildEcsImageResolutionContext$1(candidate, stateProvider, option
|
|
|
17578
17783
|
if (stateProvider && wantsState) {
|
|
17579
17784
|
const loaded = await stateProvider.load(candidate.stackName, candidate.region);
|
|
17580
17785
|
if (loaded) ctx.stateResources = loaded.resources;
|
|
17786
|
+
if (needs.needsEnvOrSecretSubstitution && stateProvider.resolveTemplateSsmParameters) {
|
|
17787
|
+
const ssmParameters = await stateProvider.resolveTemplateSsmParameters(candidate.template);
|
|
17788
|
+
if (Object.keys(ssmParameters).length > 0) ctx.stateParameters = ssmParameters;
|
|
17789
|
+
}
|
|
17581
17790
|
} else if (!stateProvider && needs.needsStateResources) logger.warn("Container Image references a same-stack AWS::ECR::Repository. Pass a state-source flag (e.g. --from-cfn-stack or a host-provided extension) to substitute the deployed repository URI. Otherwise the resolver will surface its existing error.");
|
|
17582
17791
|
else if (!stateProvider && needs.needsEnvOrSecretSubstitution) logger.warn("Container Environment / Secrets entries contain CloudFormation intrinsics (Ref / Fn::GetAtt / Fn::Sub / Fn::Join). Pass a state-source flag (e.g. --from-cfn-stack or a host-provided extension) to substitute them against deployed state. Without a state source these entries are dropped (per-key warnings will follow).");
|
|
17583
17792
|
return ctx;
|
|
@@ -18917,6 +19126,7 @@ async function runOneTarget(target, runState, stacks, options, discovery, skipPu
|
|
|
18917
19126
|
const subContext = {
|
|
18918
19127
|
resources: imageContext?.stateResources ?? {},
|
|
18919
19128
|
...imageContext?.pseudoParameters && { pseudoParameters: imageContext.pseudoParameters },
|
|
19129
|
+
...imageContext?.stateParameters && { parameters: imageContext.stateParameters },
|
|
18920
19130
|
consumerRegion,
|
|
18921
19131
|
crossStackResolver: resolver
|
|
18922
19132
|
};
|
|
@@ -18995,6 +19205,10 @@ async function assumeTaskRole(roleArn, region) {
|
|
|
18995
19205
|
}
|
|
18996
19206
|
/**
|
|
18997
19207
|
* Build the substitution context the ECS resolver consumes.
|
|
19208
|
+
*
|
|
19209
|
+
* Exported for the site-level binding test that locks the `--from-cfn-stack`
|
|
19210
|
+
* SSM-parameter resolution call (issue #94) into this start-service call site
|
|
19211
|
+
* (mirrors `local-run-task`'s exported helper).
|
|
18998
19212
|
*/
|
|
18999
19213
|
async function buildEcsImageResolutionContext(target, stacks, options, stateProvider) {
|
|
19000
19214
|
const logger = getLogger();
|
|
@@ -19027,6 +19241,10 @@ async function buildEcsImageResolutionContext(target, stacks, options, stateProv
|
|
|
19027
19241
|
if (stateProvider && wantsState) {
|
|
19028
19242
|
const loaded = await stateProvider.load(candidate.stackName, candidate.region);
|
|
19029
19243
|
if (loaded) ctx.stateResources = loaded.resources;
|
|
19244
|
+
if (needs.needsEnvOrSecretSubstitution && stateProvider.resolveTemplateSsmParameters) {
|
|
19245
|
+
const ssmParameters = await stateProvider.resolveTemplateSsmParameters(candidate.template);
|
|
19246
|
+
if (Object.keys(ssmParameters).length > 0) ctx.stateParameters = ssmParameters;
|
|
19247
|
+
}
|
|
19030
19248
|
} else if (!stateProvider && needs.needsStateResources) logger.warn("Container Image references a same-stack AWS::ECR::Repository. Pass a state-source flag (e.g. --from-cfn-stack or a host-provided extension) to substitute the deployed repository URI.");
|
|
19031
19249
|
else if (!stateProvider && needs.needsEnvOrSecretSubstitution) logger.warn("Container Environment / Secrets entries contain CloudFormation intrinsics. Pass a state-source flag (e.g. --from-cfn-stack or a host-provided extension) to substitute them against the deployed state.");
|
|
19032
19250
|
return ctx;
|
|
@@ -19199,5 +19417,5 @@ function createLocalListCommand(opts = {}) {
|
|
|
19199
19417
|
}
|
|
19200
19418
|
|
|
19201
19419
|
//#endregion
|
|
19202
|
-
export { materializeLayerFromArn as $, matchRoute as A, parseConnectionsPath as B, evaluateCachedLambdaPolicy as C, buildCorsConfigByApiId as D, applyCorsResponseHeaders as E, HOST_GATEWAY_MIN_VERSION as F, resolveRuntimeCodeMountPath as G, buildDisconnectEvent as H, probeHostGatewaySupport as I, substituteAgainstState as J, resolveRuntimeFileExtension as K, ConnectionRegistry as L, applyAuthorizerOverlay as M, buildHttpApiV2Event as N, buildCorsConfigFromCloudFrontChain as O, buildRestV1Event as P, resolveEnvVars as Q, buildMgmtEndpointEnvUrl as R, computeRequestIdentityHash as S, invokeTokenAuthorizer as T, buildMessageEvent as U, buildConnectEvent as V, createLocalInvokeCommand as W, substituteEnvVarsFromState as X, substituteAgainstStateAsync as Y, substituteEnvVarsFromStateAsync as Z, buildJwksUrlFromIssuer as _,
|
|
19203
|
-
//# sourceMappingURL=local-list-
|
|
19420
|
+
export { materializeLayerFromArn as $, matchRoute as A, parseConnectionsPath as B, evaluateCachedLambdaPolicy as C, buildCorsConfigByApiId as D, applyCorsResponseHeaders as E, HOST_GATEWAY_MIN_VERSION as F, resolveRuntimeCodeMountPath as G, buildDisconnectEvent as H, probeHostGatewaySupport as I, substituteAgainstState as J, resolveRuntimeFileExtension as K, ConnectionRegistry as L, applyAuthorizerOverlay as M, buildHttpApiV2Event as N, buildCorsConfigFromCloudFrontChain as O, buildRestV1Event as P, resolveEnvVars as Q, buildMgmtEndpointEnvUrl as R, computeRequestIdentityHash as S, invokeTokenAuthorizer as T, buildMessageEvent as U, buildConnectEvent as V, createLocalInvokeCommand as W, substituteEnvVarsFromState as X, substituteAgainstStateAsync as Y, substituteEnvVarsFromStateAsync as Z, buildJwksUrlFromIssuer as _, parseSelectionExpressionPath as _t, getContainerNetworkIp as a, isCfnFlagPresent as at, verifyJwtAuthorizer as b, resolveLambdaArnIntrinsic as bt, createAuthorizerCache as c, resolveCfnRegion as ct, availableApiIdentifiers as d, collectSsmParameterRefs as dt, derivePseudoParametersFromRegion as et, filterRoutesByApiIdentifier as f, resolveSsmParameters as ft, buildCognitoJwksUrl as g, discoverWebSocketApisOrThrow as gt, resolveServiceIntegrationParameters as h, discoverWebSocketApis as ht, CloudMapRegistry as i, createLocalStateProvider as it, translateLambdaResponse as j, matchPreflight as k, attachStageContext as l, resolveCfnStackName as lt, resolveSelectionExpression as m, listTargets as mt, formatTargetListing as n, tryResolveImageFnJoin as nt, createLocalRunTaskCommand as o, rejectExplicitCfnStackWithMultipleStacks as ot, groupRoutesByServer as p, countTargets as pt, resolveRuntimeImage as q, createLocalStartServiceCommand as r, LocalStateSourceError as rt, createLocalStartApiCommand as s, resolveCfnFallbackRegion as st, createLocalListCommand as t, substituteImagePlaceholders as tt, buildStageMap as u, CfnLocalStateProvider as ut, createJwksCache as v, discoverRoutes as vt, invokeRequestAuthorizer as w, buildMethodArn as x, verifyCognitoJwt as y, pickRefLogicalId as yt, handleConnectionsRequest as z };
|
|
19421
|
+
//# sourceMappingURL=local-list-CY18YQf1.js.map
|