@go-to-k/cdkd 0.238.4 → 0.238.6
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
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { a as getLiveRenderer, c as PATTERN_B_RESOURCE_TYPES, d as generateResourceNameWithFallback, f as withSkipPrefix, i as runStackBuffered, n as getLogger, o as PATTERN_B_NAME_OPTIONS, p as withStackName, s as PATTERN_B_NAME_PROPERTIES, u as generateResourceName } from "./logger-BzO-joNR.js";
|
|
3
3
|
import { A as withErrorHandling, C as StackHasActiveImportsError, S as ResourceUpdateNotSupportedError, _ as MissingCdkCliError, a as normalizeAwsTagsToCfn, b as ProvisioningError, f as LocalInvokeBuildError$1, i as matchesCdkPath, k as normalizeAwsError, l as CdkdError, m as LocalStartServiceError, n as isTerminationProtectionPropagationError, o as resolveExplicitPhysicalId, p as LocalMigrateError, r as CDK_PATH_TAG, s as assertRegionMatch, t as disableInstanceApiTermination, v as NestedStackChildDirectDestroyError, w as StackTerminationProtectionError, x as ResourceTimeoutError, y as PartialFailureError } from "./ec2-termination-protection-q-WGWgxa.js";
|
|
4
4
|
import { a as setAwsClients, i as resetAwsClients, r as getAwsClients, t as AwsClients } from "./aws-clients-B15NAPbL.js";
|
|
5
|
-
import { $ as getDockerCmd, A as DiffCalculator, B as buildAssetRedirectMap, C as findActionableSilentDrops, Ct as resolveBucketRegion, D as refStateLookupFromResource, E as cfnRefValueFromPhysicalId, F as rebuildClientForBucketRegion, G as BOOTSTRAP_MARKER_PREFIX, H as loadPublishableAssetManifest, I as shouldRetainResource, J as parseBootstrapMarker, K as ensureAssetStorage, L as AssetPublisher, M as TemplateParser, N as LockManager, O as WAFv2WebACLProvider, P as S3StateBackend, Q as formatDockerLoginError, R as stringifyValue, S as ProviderRegistry, T as IntrinsicFunctionResolver, U as rewriteTemplateAssetReferences, V as createAssetRedirectResolver, W as AssetModeResolver, X as validateContainerRepoName, Y as validateAssetBucketName, Z as buildDockerImage, _ as green, _t as CFN_TEMPLATE_URL_LIMIT, a as withRetry, at as synthesisStatusMessage, b as IAMRoleProvider, bt as uploadCfnTemplate, c as computeImplicitDeleteEdges, ct as resolveApp, d as isStatefulRecreateTargetSync, dt as resolveSkipPrefix, et as runDockerForeground, f as renderStatefulReason, ft as resolveStateBucketWithDefault, g as gray, gt as CFN_TEMPLATE_BODY_LIMIT, h as cyan, ht as warnDeprecatedNoPrefixCliFlag, i as withResourceDeadline, it as Synthesizer, j as DagBuilder, k as applyRoleArnIfSet, l as extractDeploymentEventError, lt as resolveAutoAssetStorage, m as bold, mt as resolveUseCdkBootstrapAssets, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as AssetManifestLoader, o as isRetryableTransientError, ot as getDefaultStateBucketName, p as formatResourceLine, pt as resolveStateBucketWithDefaultAndSource, q as getBootstrapMarkerKey, r as DeployEngine, rt as getDockerImageBySourceHash, s as IMPLICIT_DELETE_DEPENDENCIES, st as getLegacyStateBucketName, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as runDockerStreaming, u as MULTI_REGION_RECREATE_BLOCKED_TYPES, ut as resolveCaptureObservedState, v as red, vt as MIGRATE_TMP_PREFIX, w as CloudControlProvider, x as collectInlinePolicyNamesManagedBySiblings, xt as AssemblyReader, y as yellow, yt as findLargeInlineResources, z as WorkGraph } from "./deploy-engine-
|
|
5
|
+
import { $ as getDockerCmd, A as DiffCalculator, B as buildAssetRedirectMap, C as findActionableSilentDrops, Ct as resolveBucketRegion, D as refStateLookupFromResource, E as cfnRefValueFromPhysicalId, F as rebuildClientForBucketRegion, G as BOOTSTRAP_MARKER_PREFIX, H as loadPublishableAssetManifest, I as shouldRetainResource, J as parseBootstrapMarker, K as ensureAssetStorage, L as AssetPublisher, M as TemplateParser, N as LockManager, O as WAFv2WebACLProvider, P as S3StateBackend, Q as formatDockerLoginError, R as stringifyValue, S as ProviderRegistry, T as IntrinsicFunctionResolver, U as rewriteTemplateAssetReferences, V as createAssetRedirectResolver, W as AssetModeResolver, X as validateContainerRepoName, Y as validateAssetBucketName, Z as buildDockerImage, _ as green, _t as CFN_TEMPLATE_URL_LIMIT, a as withRetry, at as synthesisStatusMessage, b as IAMRoleProvider, bt as uploadCfnTemplate, c as computeImplicitDeleteEdges, ct as resolveApp, d as isStatefulRecreateTargetSync, dt as resolveSkipPrefix, et as runDockerForeground, f as renderStatefulReason, ft as resolveStateBucketWithDefault, g as gray, gt as CFN_TEMPLATE_BODY_LIMIT, h as cyan, ht as warnDeprecatedNoPrefixCliFlag, i as withResourceDeadline, it as Synthesizer, j as DagBuilder, k as applyRoleArnIfSet, l as extractDeploymentEventError, lt as resolveAutoAssetStorage, m as bold, mt as resolveUseCdkBootstrapAssets, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as AssetManifestLoader, o as isRetryableTransientError, ot as getDefaultStateBucketName, p as formatResourceLine, pt as resolveStateBucketWithDefaultAndSource, q as getBootstrapMarkerKey, r as DeployEngine, rt as getDockerImageBySourceHash, s as IMPLICIT_DELETE_DEPENDENCIES, st as getLegacyStateBucketName, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as runDockerStreaming, u as MULTI_REGION_RECREATE_BLOCKED_TYPES, ut as resolveCaptureObservedState, v as red, vt as MIGRATE_TMP_PREFIX, w as CloudControlProvider, x as collectInlinePolicyNamesManagedBySiblings, xt as AssemblyReader, y as yellow, yt as findLargeInlineResources, z as WorkGraph } from "./deploy-engine-_tADDg2k.js";
|
|
6
6
|
import { t as expectedOwnerParam } from "./expected-bucket-owner-BjEfUnkA.js";
|
|
7
7
|
import { t as ASGProvider } from "./asg-provider-Dbl1_mwT.js";
|
|
8
8
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -1885,7 +1885,7 @@ const FLUSH_INTERVAL_MS = 2e3;
|
|
|
1885
1885
|
const FLUSH_EVENT_THRESHOLD = 50;
|
|
1886
1886
|
/** Build-time cdkd version, with a dev fallback for non-built contexts. */
|
|
1887
1887
|
function getCdkdVersion() {
|
|
1888
|
-
return "0.238.
|
|
1888
|
+
return "0.238.6";
|
|
1889
1889
|
}
|
|
1890
1890
|
/**
|
|
1891
1891
|
* Generate a time-sortable unique run id, e.g.
|
|
@@ -46316,12 +46316,18 @@ function formatBucketSource(source) {
|
|
|
46316
46316
|
* not-yet-bootstrapped bucket. (Bucket existence is verified separately
|
|
46317
46317
|
* via {@link setupStateBackend}, so getting here implies the bucket is
|
|
46318
46318
|
* reachable; `GetBucketLocation` failing is most often a permissions gap.)
|
|
46319
|
+
*
|
|
46320
|
+
* Takes the (region-corrected) S3 client directly — see the issue #1054 note
|
|
46321
|
+
* in {@link stateInfoCommand}. Before that fix this call was made with the
|
|
46322
|
+
* ambient-region client, so a cross-region state bucket silently degraded to
|
|
46323
|
+
* `undefined` ("Region: unknown") here; with the corrected client it now
|
|
46324
|
+
* succeeds and reports the bucket's actual region.
|
|
46319
46325
|
*/
|
|
46320
|
-
async function detectBucketRegion(
|
|
46326
|
+
async function detectBucketRegion(s3, bucket) {
|
|
46321
46327
|
try {
|
|
46322
|
-
const constraint = (await
|
|
46328
|
+
const constraint = (await s3.send(new GetBucketLocationCommand({
|
|
46323
46329
|
Bucket: bucket,
|
|
46324
|
-
...await expectedOwnerParam(
|
|
46330
|
+
...await expectedOwnerParam(s3)
|
|
46325
46331
|
}))).LocationConstraint;
|
|
46326
46332
|
if (!constraint) return "us-east-1";
|
|
46327
46333
|
if (constraint === "EU") return "eu-west-1";
|
|
@@ -46342,12 +46348,12 @@ async function detectBucketRegion(awsClients, bucket) {
|
|
|
46342
46348
|
* Returns the full set of state-file keys; the count is the unique-stacks
|
|
46343
46349
|
* tally we want for the `Stacks:` line.
|
|
46344
46350
|
*/
|
|
46345
|
-
async function listStateFileKeys(
|
|
46351
|
+
async function listStateFileKeys(s3, bucket, prefix) {
|
|
46346
46352
|
const keys = [];
|
|
46347
46353
|
let continuationToken;
|
|
46348
46354
|
const searchPrefix = `${prefix}/`;
|
|
46349
46355
|
do {
|
|
46350
|
-
const resp = await
|
|
46356
|
+
const resp = await s3.send(new ListObjectsV2Command({
|
|
46351
46357
|
Bucket: bucket,
|
|
46352
46358
|
Prefix: searchPrefix,
|
|
46353
46359
|
...continuationToken && { ContinuationToken: continuationToken }
|
|
@@ -46365,13 +46371,13 @@ async function listStateFileKeys(awsClients, bucket, prefix) {
|
|
|
46365
46371
|
* Returns `'unknown'` when no state files exist or parsing fails — we don't
|
|
46366
46372
|
* want a cosmetic command to crash on an unexpected payload.
|
|
46367
46373
|
*/
|
|
46368
|
-
async function readSchemaVersion(
|
|
46374
|
+
async function readSchemaVersion(s3, bucket, keys) {
|
|
46369
46375
|
if (keys.length === 0) return "unknown";
|
|
46370
46376
|
try {
|
|
46371
|
-
const resp = await
|
|
46377
|
+
const resp = await s3.send(new GetObjectCommand({
|
|
46372
46378
|
Bucket: bucket,
|
|
46373
46379
|
Key: keys[0],
|
|
46374
|
-
...await expectedOwnerParam(
|
|
46380
|
+
...await expectedOwnerParam(s3)
|
|
46375
46381
|
}));
|
|
46376
46382
|
if (!resp.Body) return "unknown";
|
|
46377
46383
|
const body = await resp.Body.transformToString();
|
|
@@ -46387,13 +46393,13 @@ async function readSchemaVersion(awsClients, bucket, keys) {
|
|
|
46387
46393
|
* cosmetic command and should not crash on an unexpected payload (deploy
|
|
46388
46394
|
* hard-errors on the same marker instead).
|
|
46389
46395
|
*/
|
|
46390
|
-
async function listAssetStorageMarkers(
|
|
46396
|
+
async function listAssetStorageMarkers(s3, bucket) {
|
|
46391
46397
|
const logger = getLogger();
|
|
46392
46398
|
const entries = [];
|
|
46393
46399
|
let continuationToken;
|
|
46394
46400
|
const keys = [];
|
|
46395
46401
|
do {
|
|
46396
|
-
const resp = await
|
|
46402
|
+
const resp = await s3.send(new ListObjectsV2Command({
|
|
46397
46403
|
Bucket: bucket,
|
|
46398
46404
|
Prefix: BOOTSTRAP_MARKER_PREFIX,
|
|
46399
46405
|
...continuationToken && { ContinuationToken: continuationToken }
|
|
@@ -46404,10 +46410,10 @@ async function listAssetStorageMarkers(awsClients, bucket) {
|
|
|
46404
46410
|
for (const key of keys) {
|
|
46405
46411
|
const region = key.slice(BOOTSTRAP_MARKER_PREFIX.length, -5);
|
|
46406
46412
|
try {
|
|
46407
|
-
const marker = parseBootstrapMarker(await (await
|
|
46413
|
+
const marker = parseBootstrapMarker(await (await s3.send(new GetObjectCommand({
|
|
46408
46414
|
Bucket: bucket,
|
|
46409
46415
|
Key: key,
|
|
46410
|
-
...await expectedOwnerParam(
|
|
46416
|
+
...await expectedOwnerParam(s3)
|
|
46411
46417
|
}))).Body?.transformToString() ?? "", key);
|
|
46412
46418
|
entries.push({
|
|
46413
46419
|
region,
|
|
@@ -46451,6 +46457,7 @@ async function stateInfoCommand(options) {
|
|
|
46451
46457
|
...options.profile && { profile: options.profile }
|
|
46452
46458
|
});
|
|
46453
46459
|
setAwsClients(awsClients);
|
|
46460
|
+
let regionCorrectedS3 = null;
|
|
46454
46461
|
try {
|
|
46455
46462
|
const region = options.region || process.env["AWS_REGION"] || "us-east-1";
|
|
46456
46463
|
const resolved = await resolveStateBucketWithDefaultAndSource(options.stateBucket, region);
|
|
@@ -46460,10 +46467,18 @@ async function stateInfoCommand(options) {
|
|
|
46460
46467
|
bucket,
|
|
46461
46468
|
prefix
|
|
46462
46469
|
}).verifyBucketExists();
|
|
46463
|
-
|
|
46464
|
-
|
|
46465
|
-
|
|
46466
|
-
|
|
46470
|
+
regionCorrectedS3 = await rebuildClientForBucketRegion(awsClients.s3, bucket, {
|
|
46471
|
+
reuseClientCredentials: true,
|
|
46472
|
+
tolerateNonStandardClient: true,
|
|
46473
|
+
onRebuild: ({ bucketRegion, currentRegion }) => {
|
|
46474
|
+
logger.debug(`State bucket '${bucket}' is in '${bucketRegion}' (state-info client was '${String(currentRegion)}'); building a region-corrected S3 client for info reads.`);
|
|
46475
|
+
}
|
|
46476
|
+
});
|
|
46477
|
+
const infoS3 = regionCorrectedS3 ?? awsClients.s3;
|
|
46478
|
+
const detectedRegion = await detectBucketRegion(infoS3, bucket);
|
|
46479
|
+
const stateFileKeys = await listStateFileKeys(infoS3, bucket, prefix);
|
|
46480
|
+
const schemaVersion = await readSchemaVersion(infoS3, bucket, stateFileKeys);
|
|
46481
|
+
const assetStorage = await listAssetStorageMarkers(infoS3, bucket);
|
|
46467
46482
|
if (options.json) {
|
|
46468
46483
|
const json = {
|
|
46469
46484
|
bucket,
|
|
@@ -46491,6 +46506,7 @@ async function stateInfoCommand(options) {
|
|
|
46491
46506
|
}
|
|
46492
46507
|
process.stdout.write(`${lines.join("\n")}\n`);
|
|
46493
46508
|
} finally {
|
|
46509
|
+
regionCorrectedS3?.destroy();
|
|
46494
46510
|
awsClients.destroy();
|
|
46495
46511
|
}
|
|
46496
46512
|
}
|
|
@@ -47705,6 +47721,72 @@ async function loadStateForStack(stackName, synthRegion, opts) {
|
|
|
47705
47721
|
}
|
|
47706
47722
|
}
|
|
47707
47723
|
/**
|
|
47724
|
+
* Best-effort read of the region's asset-storage bootstrap marker
|
|
47725
|
+
* (`s3://{stateBucket}/cdkd-bootstrap/{region}.json`) to recover the
|
|
47726
|
+
* cdkd-owned container-asset ECR repository name (issue #1025). Since
|
|
47727
|
+
* `cdkd bootstrap --container-repo <name>` (issue #1011) the repo can
|
|
47728
|
+
* carry ANY name, so the local resolvers' conventional-prefix regex
|
|
47729
|
+
* cannot classify images published to a custom-named repo — the marker
|
|
47730
|
+
* is the only source of truth.
|
|
47731
|
+
*
|
|
47732
|
+
* This is a fast-path optimization for `cdkd local run-task
|
|
47733
|
+
* --from-state` (recognizing a cdk-asset image enables the local
|
|
47734
|
+
* `cdk.out` docker build instead of an ECR pull), so it must NEVER fail
|
|
47735
|
+
* the run: every miss (no bucket, no marker, malformed marker, any AWS
|
|
47736
|
+
* error) logs at debug and returns `undefined` — the caller falls back
|
|
47737
|
+
* to the conventional-prefix regex.
|
|
47738
|
+
*
|
|
47739
|
+
* Marker-key region resolution: the marker records the repo for the
|
|
47740
|
+
* stack's DEPLOY region, so after the explicit CLI overrides (`--region`
|
|
47741
|
+
* highest per the repo convention, then `--stack-region` — the state
|
|
47742
|
+
* disambiguator that names the region whose state is being loaded) the
|
|
47743
|
+
* synth-derived stack region outranks the ambient env region. This
|
|
47744
|
+
* deliberately differs from {@link loadStateForStack}'s bucket-resolution
|
|
47745
|
+
* chain (which is about WHERE the state bucket is, not WHICH region's
|
|
47746
|
+
* data is read).
|
|
47747
|
+
*/
|
|
47748
|
+
async function loadBootstrapContainerRepo(synthRegion, opts) {
|
|
47749
|
+
const logger = getLogger();
|
|
47750
|
+
const prefix = opts.logPrefix ?? "--from-state";
|
|
47751
|
+
const region = opts.region ?? opts.stackRegion ?? synthRegion ?? process.env["AWS_REGION"] ?? process.env["AWS_DEFAULT_REGION"] ?? "us-east-1";
|
|
47752
|
+
let stateBucket;
|
|
47753
|
+
try {
|
|
47754
|
+
stateBucket = await resolveStateBucketWithDefault(opts.stateBucket, region);
|
|
47755
|
+
} catch (err) {
|
|
47756
|
+
logger.debug(`${prefix}: could not resolve state bucket for the bootstrap-marker read: ${err instanceof Error ? err.message : String(err)}. Falling back to conventional asset-repo names.`);
|
|
47757
|
+
return;
|
|
47758
|
+
}
|
|
47759
|
+
const awsClients = new AwsClients({
|
|
47760
|
+
...opts.region !== void 0 && { region: opts.region },
|
|
47761
|
+
...opts.profile !== void 0 && { profile: opts.profile }
|
|
47762
|
+
});
|
|
47763
|
+
setAwsClients(awsClients);
|
|
47764
|
+
try {
|
|
47765
|
+
const stateConfig = {
|
|
47766
|
+
bucket: stateBucket,
|
|
47767
|
+
prefix: opts.statePrefix
|
|
47768
|
+
};
|
|
47769
|
+
const stateBackend = new S3StateBackend(awsClients.s3, stateConfig, {
|
|
47770
|
+
...opts.region !== void 0 && { region: opts.region },
|
|
47771
|
+
...opts.profile !== void 0 && { profile: opts.profile }
|
|
47772
|
+
});
|
|
47773
|
+
const markerKey = getBootstrapMarkerKey(region);
|
|
47774
|
+
const body = await stateBackend.getRawObject(markerKey);
|
|
47775
|
+
if (body === null) {
|
|
47776
|
+
logger.debug(`${prefix}: no bootstrap marker at '${markerKey}' in bucket '${stateBucket}' — assuming conventional asset-repo names.`);
|
|
47777
|
+
return;
|
|
47778
|
+
}
|
|
47779
|
+
const marker = parseBootstrapMarker(body, markerKey);
|
|
47780
|
+
logger.debug(`${prefix}: bootstrap marker for ${region} names container repo '${marker.containerRepo}'.`);
|
|
47781
|
+
return marker.containerRepo;
|
|
47782
|
+
} catch (err) {
|
|
47783
|
+
logger.debug(`${prefix}: bootstrap-marker read failed: ${err instanceof Error ? err.message : String(err)}. Falling back to conventional asset-repo names.`);
|
|
47784
|
+
return;
|
|
47785
|
+
} finally {
|
|
47786
|
+
resetAwsClients();
|
|
47787
|
+
}
|
|
47788
|
+
}
|
|
47789
|
+
/**
|
|
47708
47790
|
* Build a {@link CrossStackResolver} that walks cdkd's S3 state to look
|
|
47709
47791
|
* up `Fn::ImportValue` / `Fn::GetStackOutput` references the same way
|
|
47710
47792
|
* `cdkd deploy`'s `IntrinsicFunctionResolver` does. Returns `undefined`
|
|
@@ -48431,6 +48513,7 @@ function detectEcsImageResolutionNeeds(stack) {
|
|
|
48431
48513
|
let needsStateResources = false;
|
|
48432
48514
|
let needsEnvOrSecretSubstitution = false;
|
|
48433
48515
|
let needsCrossStackResolver = false;
|
|
48516
|
+
let needsAssetRepoMarker = false;
|
|
48434
48517
|
for (const res of Object.values(resources)) {
|
|
48435
48518
|
if (res.Type !== "AWS::ECS::TaskDefinition") continue;
|
|
48436
48519
|
const props = res.Properties ?? {};
|
|
@@ -48442,6 +48525,8 @@ function detectEcsImageResolutionNeeds(stack) {
|
|
|
48442
48525
|
const need = inspectImageForSubstitutions(image, resources);
|
|
48443
48526
|
if (need.pseudo) needsPseudoParameters = true;
|
|
48444
48527
|
if (need.state) needsStateResources = true;
|
|
48528
|
+
const flat = extractImageString(image);
|
|
48529
|
+
if (flat !== void 0 && extractEcrRepoComponent(flat) !== void 0 && !CDK_ASSET_IMAGE_REPO_RE.test(flat)) needsAssetRepoMarker = true;
|
|
48445
48530
|
if (containerHasIntrinsicEnvOrSecret(co)) needsEnvOrSecretSubstitution = true;
|
|
48446
48531
|
if (containerHasCrossStackEnvOrSecret(co)) {
|
|
48447
48532
|
needsEnvOrSecretSubstitution = true;
|
|
@@ -48461,7 +48546,8 @@ function detectEcsImageResolutionNeeds(stack) {
|
|
|
48461
48546
|
needsPseudoParameters,
|
|
48462
48547
|
needsStateResources,
|
|
48463
48548
|
needsEnvOrSecretSubstitution,
|
|
48464
|
-
needsCrossStackResolver
|
|
48549
|
+
needsCrossStackResolver,
|
|
48550
|
+
needsAssetRepoMarker
|
|
48465
48551
|
};
|
|
48466
48552
|
}
|
|
48467
48553
|
/**
|
|
@@ -48937,11 +49023,53 @@ function buildSubstitutionContextFromImageContext(context) {
|
|
|
48937
49023
|
* `cdk.out` build, so both must classify as `kind: 'cdk-asset'`. The `cdk-`
|
|
48938
49024
|
* qualifier is generalized to `[a-z0-9]+` so a custom-qualifier bootstrap is
|
|
48939
49025
|
* matched too (previously only the hardcoded `hnb659fds` default was).
|
|
49026
|
+
*
|
|
49027
|
+
* Since `cdkd bootstrap --container-repo <name>` (issue #1011) the
|
|
49028
|
+
* cdkd-owned repo can carry ANY name — the per-region bootstrap marker is
|
|
49029
|
+
* the source of truth. The regex therefore cannot recognize images
|
|
49030
|
+
* published to a custom-named repo; `isCdkAssetImageUri` additionally
|
|
49031
|
+
* matches an ECR-hosted URI whose repository path component equals the
|
|
49032
|
+
* marker-resolved name when the caller supplies it (issue #1025). The
|
|
49033
|
+
* regex stays as the no-marker fallback — `cdkd local run-task` can run
|
|
49034
|
+
* without AWS access, where no marker read is possible.
|
|
48940
49035
|
*/
|
|
48941
49036
|
const CDK_ASSET_IMAGE_REPO_RE = /(?:cdk-[a-z0-9]+|cdkd)-container-assets-/;
|
|
48942
|
-
/**
|
|
48943
|
-
|
|
48944
|
-
|
|
49037
|
+
/**
|
|
49038
|
+
* Extract the repository path component of an ECR-hosted image URI.
|
|
49039
|
+
*
|
|
49040
|
+
* The host part (before the first `/`) must contain `.dkr.ecr.` — this
|
|
49041
|
+
* tolerates both concrete hosts (`123456789012.dkr.ecr.us-east-1.amazonaws.com`)
|
|
49042
|
+
* and placeholder-bearing hosts
|
|
49043
|
+
* (`${AWS::AccountId}.dkr.ecr.${AWS::Region}.${AWS::URLSuffix}`). The repo
|
|
49044
|
+
* component is the substring after the first `/`, stripped of a trailing
|
|
49045
|
+
* `@<digest>` (first `@`) and then a trailing `:<tag>` (last `:` — ECR
|
|
49046
|
+
* repo names cannot contain `:` but CAN contain `/`, so the last colon is
|
|
49047
|
+
* the tag separator). Stripping the digest FIRST handles the combined
|
|
49048
|
+
* `name:tag@digest` form Docker accepts. Returns `undefined` for non-ECR
|
|
49049
|
+
* hosts and empty results.
|
|
49050
|
+
*/
|
|
49051
|
+
function extractEcrRepoComponent(uri) {
|
|
49052
|
+
const slash = uri.indexOf("/");
|
|
49053
|
+
if (slash <= 0) return void 0;
|
|
49054
|
+
if (!uri.slice(0, slash).includes(".dkr.ecr.")) return void 0;
|
|
49055
|
+
let repo = uri.slice(slash + 1);
|
|
49056
|
+
const at = repo.indexOf("@");
|
|
49057
|
+
if (at !== -1) repo = repo.slice(0, at);
|
|
49058
|
+
const colon = repo.lastIndexOf(":");
|
|
49059
|
+
if (colon !== -1) repo = repo.slice(0, colon);
|
|
49060
|
+
return repo.length > 0 ? repo : void 0;
|
|
49061
|
+
}
|
|
49062
|
+
/**
|
|
49063
|
+
* True when `uri` embeds a CDK-bootstrap or cdkd-owned container-assets
|
|
49064
|
+
* repo — either via the conventional-name regex, or (issue #1025) via an
|
|
49065
|
+
* exact match between the URI's ECR repository path component and the
|
|
49066
|
+
* bootstrap-marker-resolved `cdkAssetContainerRepo` name, which covers
|
|
49067
|
+
* regions bootstrapped with `cdkd bootstrap --container-repo <name>`.
|
|
49068
|
+
*/
|
|
49069
|
+
function isCdkAssetImageUri(uri, cdkAssetContainerRepo) {
|
|
49070
|
+
if (CDK_ASSET_IMAGE_REPO_RE.test(uri)) return true;
|
|
49071
|
+
if (cdkAssetContainerRepo === void 0) return false;
|
|
49072
|
+
return extractEcrRepoComponent(uri) === cdkAssetContainerRepo;
|
|
48945
49073
|
}
|
|
48946
49074
|
/**
|
|
48947
49075
|
* Parse the `Image` field of an ECS container definition.
|
|
@@ -48976,14 +49104,14 @@ function isCdkAssetImageUri(uri) {
|
|
|
48976
49104
|
*/
|
|
48977
49105
|
function parseContainerImage(raw, containerName, taskLogicalId, resources, _stack, context) {
|
|
48978
49106
|
const getAttImage = tryResolveImageGetAtt(raw, resources, context);
|
|
48979
|
-
if (getAttImage) return classifyResolvedImage(getAttImage);
|
|
49107
|
+
if (getAttImage) return classifyResolvedImage(getAttImage, context?.cdkAssetContainerRepo);
|
|
48980
49108
|
const joinResolved = tryResolveImageFnJoin(raw, resources, context);
|
|
48981
|
-
if (joinResolved.kind === "resolved") return classifyResolvedImage(joinResolved.uri);
|
|
49109
|
+
if (joinResolved.kind === "resolved") return classifyResolvedImage(joinResolved.uri, context?.cdkAssetContainerRepo);
|
|
48982
49110
|
if (joinResolved.kind === "needs-state") throw new EcsTaskResolutionError(`Container '${containerName}' in task '${taskLogicalId}' references same-stack ECR repository '${joinResolved.repoLogicalId}' via Fn::Join. cdkd local run-task cannot resolve the repository URI without state — pass --from-state (the stack must have been deployed via cdkd deploy), build via ContainerImage.fromAsset, or pin a public image.`);
|
|
48983
49111
|
if (joinResolved.kind === "unsupported-join") throw new EcsTaskResolutionError(`Container '${containerName}' in task '${taskLogicalId}' has an unsupported Fn::Join Image shape: ${joinResolved.reason}. cdkd local run-task recognizes the canonical CDK 2.x ContainerImage.fromEcrRepository Fn::Join shape (delimiter "" with nested Fn::Select/Fn::Split over an ECR Repository Arn GetAtt + Ref to the repo).`);
|
|
48984
49112
|
const flat = extractImageString(raw);
|
|
48985
49113
|
if (!flat) throw new EcsTaskResolutionError(`Container '${containerName}' in task '${taskLogicalId}' has an unparseable Image property. cdkd local run-task v1 supports flat string images, single-key Fn::Sub bodies, and CDK-asset Image references.`);
|
|
48986
|
-
if (isCdkAssetImageUri(flat)) {
|
|
49114
|
+
if (isCdkAssetImageUri(flat, context?.cdkAssetContainerRepo)) {
|
|
48987
49115
|
const hashMatch = /:([a-f0-9]{8,})$/.exec(flat);
|
|
48988
49116
|
const out = { kind: "cdk-asset" };
|
|
48989
49117
|
if (hashMatch) out.assetHash = hashMatch[1];
|
|
@@ -49029,9 +49157,11 @@ function findUnresolvedEcrRepositoryRef(substituted, resources) {
|
|
|
49029
49157
|
* Classify a fully-substituted image URI (Tier 1 / Tier 2 produced a
|
|
49030
49158
|
* concrete string) into the `ResolvedEcsImage` shape. Splits out so the
|
|
49031
49159
|
* `Fn::GetAtt` path can share the regex-match branches.
|
|
49160
|
+
* `cdkAssetContainerRepo` is the optional marker-resolved custom repo
|
|
49161
|
+
* name (issue #1025) threaded through from the resolution context.
|
|
49032
49162
|
*/
|
|
49033
|
-
function classifyResolvedImage(uri) {
|
|
49034
|
-
if (isCdkAssetImageUri(uri)) {
|
|
49163
|
+
function classifyResolvedImage(uri, cdkAssetContainerRepo) {
|
|
49164
|
+
if (isCdkAssetImageUri(uri, cdkAssetContainerRepo)) {
|
|
49035
49165
|
const hashMatch = /:([a-f0-9]{8,})$/.exec(uri);
|
|
49036
49166
|
const out = { kind: "cdk-asset" };
|
|
49037
49167
|
if (hashMatch) out.assetHash = hashMatch[1];
|
|
@@ -53488,7 +53618,7 @@ async function buildEcsImageResolutionContext$1(candidate, stateProvider, option
|
|
|
53488
53618
|
const logger = getLogger();
|
|
53489
53619
|
if (!candidate) return void 0;
|
|
53490
53620
|
const needs = detectEcsImageResolutionNeeds(candidate);
|
|
53491
|
-
if (!needs.needsPseudoParameters && !needs.needsStateResources && !needs.needsEnvOrSecretSubstitution) return;
|
|
53621
|
+
if (!needs.needsPseudoParameters && !needs.needsStateResources && !needs.needsEnvOrSecretSubstitution && !needs.needsAssetRepoMarker) return;
|
|
53492
53622
|
const ctx = {};
|
|
53493
53623
|
const wantsPseudoForEnvOrSecret = !!stateProvider && needs.needsEnvOrSecretSubstitution;
|
|
53494
53624
|
if (needs.needsPseudoParameters || wantsPseudoForEnvOrSecret) {
|
|
@@ -53516,6 +53646,17 @@ async function buildEcsImageResolutionContext$1(candidate, stateProvider, option
|
|
|
53516
53646
|
if (loaded) ctx.stateResources = loaded.resources;
|
|
53517
53647
|
} else if (!stateProvider && needs.needsStateResources) logger.warn("Container Image references a same-stack AWS::ECR::Repository. Pass --from-state (cdkd-deployed) or --from-cfn-stack (cdk-deployed) to substitute the deployed repository URI. Otherwise the resolver will surface its existing error.");
|
|
53518
53648
|
else if (!stateProvider && needs.needsEnvOrSecretSubstitution) logger.warn("Container Environment / Secrets entries contain CloudFormation intrinsics (Ref / Fn::GetAtt / Fn::Sub / Fn::Join). Pass --from-state (cdkd-deployed) or --from-cfn-stack (cdk-deployed) to substitute them against deployed state. Without a state source these entries are dropped (per-key warnings will follow).");
|
|
53649
|
+
if (needs.needsAssetRepoMarker && options.fromState) {
|
|
53650
|
+
const containerRepo = await loadBootstrapContainerRepo(candidate.region, {
|
|
53651
|
+
statePrefix: options.statePrefix,
|
|
53652
|
+
...options.stackRegion !== void 0 && { stackRegion: options.stackRegion },
|
|
53653
|
+
...options.stateBucket !== void 0 && { stateBucket: options.stateBucket },
|
|
53654
|
+
...options.region !== void 0 && { region: options.region },
|
|
53655
|
+
...options.profile !== void 0 && { profile: options.profile },
|
|
53656
|
+
logPrefix: "--from-state"
|
|
53657
|
+
});
|
|
53658
|
+
if (containerRepo !== void 0) ctx.cdkAssetContainerRepo = containerRepo;
|
|
53659
|
+
}
|
|
53519
53660
|
return ctx;
|
|
53520
53661
|
}
|
|
53521
53662
|
function pickCandidateStack(stackPattern, stacks) {
|
|
@@ -57058,7 +57199,7 @@ function reorderArgs(argv) {
|
|
|
57058
57199
|
async function main() {
|
|
57059
57200
|
installPipeCloseHandler();
|
|
57060
57201
|
const program = new Command();
|
|
57061
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.238.
|
|
57202
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.238.6");
|
|
57062
57203
|
program.addCommand(createBootstrapCommand());
|
|
57063
57204
|
program.addCommand(createSynthCommand());
|
|
57064
57205
|
program.addCommand(createListCommand());
|