@go-to-k/cdkd 0.282.3 → 0.282.5
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/{asg-provider-BPaZaY_z.js → asg-provider-Dl8-YYQR.js} +2 -2
- package/dist/{asg-provider-BPaZaY_z.js.map → asg-provider-Dl8-YYQR.js.map} +1 -1
- package/dist/cli.js +327 -36
- package/dist/cli.js.map +1 -1
- package/dist/{deploy-engine-DGH5aBd0.js → deploy-engine-Cg_wFdJP.js} +53 -5
- package/dist/deploy-engine-Cg_wFdJP.js.map +1 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/deploy-engine-DGH5aBd0.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as configStringRefusal, $t as resolveUseCdkBootstrapAssets, A as green, An as
|
|
2
|
+
import { $ as configStringRefusal, $t as resolveUseCdkBootstrapAssets, A as green, An as PartialFailureError, At as BOOTSTRAP_MARKER_PREFIX, B as slowCcOperationTimeoutMs, Bn as normalizeAwsError, Bt as runDockerStreaming, C as MULTI_REGION_RECREATE_BLOCKED_TYPES, Cn as DeployCancelledError, Ct as stringifyValue, D as bold, Dt as loadPublishableAssetManifest, E as formatResourceLine, En as LocalStartServiceError, Et as createAssetRedirectResolver, F as clearOnUpdateRemoval, Fn as StackTerminationProtectionError, Ft as validateContainerRepoName, G as getAccountInfo, Gt as getDefaultStateBucketName, H as isTerminationProtectionPropagationError, Ht as getDockerImageBySourceHash, I as ProviderRegistry, It as buildDockerImage, J as normalizeAwsTagsToCfn, Jt as resolveAutoAssetStorage, K as refStateLookupFromResource, Kt as getLegacyStateBucketName, L as findActionableSilentDrops, Lt as formatDockerLoginError, M as yellow, Mn as ResourceTimeoutError, Mt as getBootstrapMarkerKey, N as IAMRoleProvider, Nn as ResourceUpdateNotSupportedError, Nt as parseBootstrapMarker, O as cyan, On as MissingCdkCliError, Ot as rewriteTemplateAssetReferences, P as collectInlinePolicyNamesManagedBySiblings, Pn as StackHasActiveImportsError, Pt as validateAssetBucketName, Q as configBooleanRefusal, Qt as resolveStateBucketWithDefaultAndSource, R as findSilentDropProperties, Rt as getDockerCmd, S as extractDeploymentEventError, St as AssetPublisher, T as renderStatefulReason, Tn as LocalMigrateError, Tt as buildAssetRedirectMap, U as IntrinsicFunctionResolver, Ut as Synthesizer, V as disableInstanceApiTermination, Vn as withErrorHandling, Vt as AssetManifestLoader, W as cfnRefValueFromPhysicalId, Wt as synthesisStatusMessage, X as assertRegionMatch, Xt as resolveSkipPrefix, Y as resolveExplicitPhysicalId, Yt as resolveCaptureObservedState, Z as coerceCfnBoolean, Zt as resolveStateBucketWithDefault, _ as createPreDeleteFinalSnapshot, _n as resetAwsClients, _t as TemplateParser, a as DeploymentEventsStore, an as findLargeInlineResources, at as s3BucketArn, b as unsupportedFinalSnapshotError, bn as CdkdError, bt as rebuildClientForBucketRegion, c as replayFailedOperations, cn as PARTITION_TABLE, ct as s3BucketRegionalDomainName, d as IMPLICIT_DELETE_DEPENDENCIES, dn as AssemblyReader, dt as DiffCalculator, en as stateBucketExistenceConfirmed, et as readConfigString, f as computeImplicitDeleteEdges, fn as processStackMessages, ft as describeTypeWithThrottleRetry, g as ccRoutedFinalSnapshotError, gn as getAwsClients, gt as DagBuilder, h as buildFinalSnapshotIdentifier, hn as AwsClients, ht as isThrottlingError, i as DeploymentEventsReader, in as MIGRATE_TMP_PREFIX, it as requireConfigString, j as red, jn as ProvisioningError, jt as ensureAssetStorage, k as gray, kn as NestedStackChildDirectDestroyError, kt as AssetModeResolver, l as replayRollback, ln as canonicalizeRegion, lt as s3BucketWebsiteUrl, m as PRE_DELETE_SNAPSHOT_TYPES, mn as resolveBucketRegion, mt as isRetryableTransientError, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as CFN_TEMPLATE_BODY_LIMIT, nt as requireConfigArray, o as planFailedOps, on as uploadCfnTemplate, ot as s3BucketDomainName, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pt as withRetry, q as WAFv2WebACLProvider, qt as resolveApp, r as DeployEngine, rn as CFN_TEMPLATE_URL_LIMIT, rt as requireConfigObject, s as planRollback, sn as expectedOwnerParam, st as s3BucketDualStackDomainName, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as warnDeprecatedNoPrefixCliFlag, tt as replayWarn, u as withResourceDeadline, un as derivePartitionAndUrlSuffix, ut as applyRoleArnIfSet, v as isFinalSnapshotError, vn as setAwsClients, vt as LockManager, w as isStatefulRecreateTargetSync, wn as LocalInvokeBuildError$1, wt as WorkGraph, x as makeCanonicalizePropertiesFn, xt as shouldRetainResource, y as refusesFinalSnapshot, yt as S3StateBackend, z as CloudControlProvider, zt as runDockerForeground } from "./deploy-engine-Cg_wFdJP.js";
|
|
3
3
|
import { a as getLiveRenderer, c as PATTERN_B_RESOURCE_TYPES, d as generateResourceNameWithFallback, h as withStackName, i as runStackBuffered, m as withSkipPrefix, n as getLogger, o as PATTERN_B_NAME_OPTIONS, s as PATTERN_B_NAME_PROPERTIES, u as generateResourceName } from "./logger-zRrlbaQt.js";
|
|
4
|
-
import { t as ASGProvider } from "./asg-provider-
|
|
4
|
+
import { t as ASGProvider } from "./asg-provider-Dl8-YYQR.js";
|
|
5
5
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
6
6
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
7
7
|
import { CopyObjectCommand, CreateBucketCommand, DeleteBucketAnalyticsConfigurationCommand, DeleteBucketCommand, DeleteBucketCorsCommand, DeleteBucketEncryptionCommand, DeleteBucketIntelligentTieringConfigurationCommand, DeleteBucketInventoryConfigurationCommand, DeleteBucketLifecycleCommand, DeleteBucketMetricsConfigurationCommand, DeleteBucketOwnershipControlsCommand, DeleteBucketPolicyCommand, DeleteBucketReplicationCommand, DeleteBucketTaggingCommand, DeleteBucketWebsiteCommand, DeleteObjectsCommand, GetBucketAccelerateConfigurationCommand, GetBucketCorsCommand, GetBucketEncryptionCommand, GetBucketLifecycleConfigurationCommand, GetBucketLocationCommand, GetBucketLoggingCommand, GetBucketNotificationConfigurationCommand, GetBucketOwnershipControlsCommand, GetBucketPolicyCommand, GetBucketReplicationCommand, GetBucketTaggingCommand, GetBucketVersioningCommand, GetBucketWebsiteCommand, GetObjectCommand, GetObjectLockConfigurationCommand, GetPublicAccessBlockCommand, HeadBucketCommand, ListBucketAnalyticsConfigurationsCommand, ListBucketIntelligentTieringConfigurationsCommand, ListBucketInventoryConfigurationsCommand, ListBucketMetricsConfigurationsCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchBucket, PutBucketAccelerateConfigurationCommand, PutBucketAnalyticsConfigurationCommand, PutBucketCorsCommand, PutBucketEncryptionCommand, PutBucketIntelligentTieringConfigurationCommand, PutBucketInventoryConfigurationCommand, PutBucketLifecycleConfigurationCommand, PutBucketLoggingCommand, PutBucketMetricsConfigurationCommand, PutBucketNotificationConfigurationCommand, PutBucketOwnershipControlsCommand, PutBucketPolicyCommand, PutBucketReplicationCommand, PutBucketTaggingCommand, PutBucketVersioningCommand, PutBucketWebsiteCommand, PutObjectCommand, PutObjectLockConfigurationCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
|
|
@@ -20350,7 +20350,7 @@ const EC2_NETWORK_ACL_ENTRY_ID_FORMAT = {
|
|
|
20350
20350
|
* `DestinationCidrBlock || DestinationIpv6CidrBlock || DestinationPrefixListId`
|
|
20351
20351
|
* chain resolves them.
|
|
20352
20352
|
*/
|
|
20353
|
-
const ROUTE_DESTINATION_KEYS = [
|
|
20353
|
+
const ROUTE_DESTINATION_KEYS$1 = [
|
|
20354
20354
|
"DestinationCidrBlock",
|
|
20355
20355
|
"DestinationIpv6CidrBlock",
|
|
20356
20356
|
"DestinationPrefixListId"
|
|
@@ -20377,7 +20377,7 @@ const ROUTE_DESTINATION_KEYS = [
|
|
|
20377
20377
|
* `resolvedProps`, which it records for every resource that does NOT narrow.
|
|
20378
20378
|
*/
|
|
20379
20379
|
function narrowRouteDestinations(properties) {
|
|
20380
|
-
const declared = ROUTE_DESTINATION_KEYS.filter((key) => Boolean(properties[key]));
|
|
20380
|
+
const declared = ROUTE_DESTINATION_KEYS$1.filter((key) => Boolean(properties[key]));
|
|
20381
20381
|
const narrowed = { ...properties };
|
|
20382
20382
|
for (const losingKey of declared.slice(1)) delete narrowed[losingKey];
|
|
20383
20383
|
return {
|
|
@@ -59107,6 +59107,36 @@ const COMPOSITE_ID_SPLITTERS = {
|
|
|
59107
59107
|
propertiesOverlay: { VpcId: vpcId }
|
|
59108
59108
|
};
|
|
59109
59109
|
},
|
|
59110
|
+
"AWS::EC2::Route": (physicalId, properties) => {
|
|
59111
|
+
const parts = physicalId.split("|");
|
|
59112
|
+
if (parts.length !== 2) throw new Error(`expected 2 parts ('<routeTableId>|<destination>'), got ${parts.length}: '${physicalId}'`);
|
|
59113
|
+
const [routeTableId, destination] = parts;
|
|
59114
|
+
if (!routeTableId.trim() || !destination.trim()) throw new Error(`empty part in '<routeTableId>|<destination>': '${physicalId}'`);
|
|
59115
|
+
return {
|
|
59116
|
+
resourceIdentifier: {
|
|
59117
|
+
RouteTableId: routeTableId,
|
|
59118
|
+
CidrBlock: resolveRouteDestination(destination, properties)
|
|
59119
|
+
},
|
|
59120
|
+
propertiesOverlay: { RouteTableId: routeTableId }
|
|
59121
|
+
};
|
|
59122
|
+
},
|
|
59123
|
+
"AWS::EC2::EIP": (physicalId) => {
|
|
59124
|
+
const parts = physicalId.split("|");
|
|
59125
|
+
if (parts.length !== 2) throw new Error(`expected 2 parts ('<publicIp>|<allocationId>'), got ${parts.length}: '${physicalId}'. CloudFormation identifies an AWS::EC2::EIP by BOTH fields, and neither can be recovered from the other; re-deploy the resource to refresh state`);
|
|
59126
|
+
const [first, second] = parts;
|
|
59127
|
+
if (!first.trim() || !second.trim()) throw new Error(`empty part in '<publicIp>|<allocationId>': '${physicalId}'`);
|
|
59128
|
+
const allocationFirst = first.startsWith(EIP_ALLOCATION_ID_PREFIX);
|
|
59129
|
+
const publicIp = allocationFirst ? second : first;
|
|
59130
|
+
const allocationId = allocationFirst ? first : second;
|
|
59131
|
+
if (!allocationId.startsWith(EIP_ALLOCATION_ID_PREFIX) || !EIP_PUBLIC_IP_PATTERN.test(publicIp)) throw new Error(`'${physicalId}' is not an '<publicIp>|<allocationId>' pair: CloudFormation identifies an AWS::EC2::EIP by [PublicIp, AllocationId], so one segment must be an allocation id ('${EIP_ALLOCATION_ID_PREFIX}…') and the other a dotted-quad public IP. State entry may be corrupt or written by an older cdkd binary; re-deploy the resource to refresh state`);
|
|
59132
|
+
return {
|
|
59133
|
+
resourceIdentifier: {
|
|
59134
|
+
PublicIp: publicIp,
|
|
59135
|
+
AllocationId: allocationId
|
|
59136
|
+
},
|
|
59137
|
+
propertiesOverlay: {}
|
|
59138
|
+
};
|
|
59139
|
+
},
|
|
59110
59140
|
"AWS::ApiGateway::Deployment": restApiChildSplitter({
|
|
59111
59141
|
resourceType: "AWS::ApiGateway::Deployment",
|
|
59112
59142
|
childField: "DeploymentId",
|
|
@@ -59167,6 +59197,21 @@ const COMPOSITE_ID_SPLITTERS = {
|
|
|
59167
59197
|
Namespace: namespace
|
|
59168
59198
|
} };
|
|
59169
59199
|
},
|
|
59200
|
+
"AWS::Lambda::EventInvokeConfig": (physicalId) => {
|
|
59201
|
+
if (!physicalId.trim()) throw new Error("empty physical id for AWS::Lambda::EventInvokeConfig (expected '<functionName>|<qualifier>' or a bare function name)");
|
|
59202
|
+
const separator = physicalId.indexOf("|");
|
|
59203
|
+
if (separator === -1) return { resourceIdentifier: {
|
|
59204
|
+
FunctionName: physicalId,
|
|
59205
|
+
Qualifier: "$LATEST"
|
|
59206
|
+
} };
|
|
59207
|
+
const functionName = physicalId.slice(0, separator);
|
|
59208
|
+
const qualifier = physicalId.slice(separator + 1);
|
|
59209
|
+
if (!functionName.trim() || !qualifier.trim()) throw new Error(`empty part in '<functionName>|<qualifier>': '${physicalId}'`);
|
|
59210
|
+
return { resourceIdentifier: {
|
|
59211
|
+
FunctionName: functionName,
|
|
59212
|
+
Qualifier: qualifier
|
|
59213
|
+
} };
|
|
59214
|
+
},
|
|
59170
59215
|
"AWS::Lambda::Permission": (physicalId, properties) => {
|
|
59171
59216
|
const functionName = readStringProperty(properties, "FunctionName", "AWS::Lambda::Permission");
|
|
59172
59217
|
return {
|
|
@@ -59179,11 +59224,44 @@ const COMPOSITE_ID_SPLITTERS = {
|
|
|
59179
59224
|
}
|
|
59180
59225
|
};
|
|
59181
59226
|
/**
|
|
59182
|
-
* The
|
|
59183
|
-
*
|
|
59184
|
-
*
|
|
59185
|
-
*/
|
|
59186
|
-
const
|
|
59227
|
+
* The prefix every EC2 Elastic IP allocation id carries. Used to discriminate
|
|
59228
|
+
* the two segments of an `AWS::EC2::EIP` physicalId by SHAPE rather than by
|
|
59229
|
+
* position — see the splitter for why the order is not relied on.
|
|
59230
|
+
*/
|
|
59231
|
+
const EIP_ALLOCATION_ID_PREFIX = "eipalloc-";
|
|
59232
|
+
/**
|
|
59233
|
+
* The other half of the same discriminator: an Elastic IP's public address is
|
|
59234
|
+
* always a dotted quad (EIPs are IPv4-only). Shape-only — the octet RANGES are
|
|
59235
|
+
* not checked, because this exists to tell the two segments apart, not to
|
|
59236
|
+
* validate an address AWS itself minted.
|
|
59237
|
+
*/
|
|
59238
|
+
const EIP_PUBLIC_IP_PATTERN = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
|
|
59239
|
+
const GATEWAY_ATTACHMENT_TYPE_IGW = "IGW";
|
|
59240
|
+
const GATEWAY_ATTACHMENT_TYPE_VGW = "VGW";
|
|
59241
|
+
/**
|
|
59242
|
+
* The values AWS actually uses for `AWS::EC2::VPCGatewayAttachment`'s
|
|
59243
|
+
* `AttachmentType`, plus the two spellings issue #1691 guessed.
|
|
59244
|
+
*
|
|
59245
|
+
* `IGW` / `VGW` are what every real writer produces: Cloud Control stores the
|
|
59246
|
+
* primaryIdentifier verbatim, so a CC-written cdkd state record carries one of
|
|
59247
|
+
* them as segment 0. `InternetGateway` / `VPN` were never written by anything —
|
|
59248
|
+
* they were produced by THIS table on the way OUT, and CloudFormation rejects
|
|
59249
|
+
* them (`Invalid request provided: Invalid Attachment Type 'InternetGateway'`;
|
|
59250
|
+
* the IMPORT changeset never reaches CREATE_COMPLETE). They are kept purely as
|
|
59251
|
+
* input compatibility, so a physicalId hand-written from the old comment, or
|
|
59252
|
+
* supplied via `cdkd import --resource`, normalizes instead of falling through
|
|
59253
|
+
* to the property-derivation arms. Nothing in cdkd can put them in state.
|
|
59254
|
+
*
|
|
59255
|
+
* `Object.hasOwn` at the lookup site, not a bare index: a bare index on an
|
|
59256
|
+
* object literal answers for inherited members too, so a first segment of
|
|
59257
|
+
* `constructor` would resolve to a function rather than missing.
|
|
59258
|
+
*/
|
|
59259
|
+
const GATEWAY_ATTACHMENT_TYPE_ALIASES = {
|
|
59260
|
+
[GATEWAY_ATTACHMENT_TYPE_IGW]: GATEWAY_ATTACHMENT_TYPE_IGW,
|
|
59261
|
+
[GATEWAY_ATTACHMENT_TYPE_VGW]: GATEWAY_ATTACHMENT_TYPE_VGW,
|
|
59262
|
+
InternetGateway: GATEWAY_ATTACHMENT_TYPE_IGW,
|
|
59263
|
+
VPN: GATEWAY_ATTACHMENT_TYPE_VGW
|
|
59264
|
+
};
|
|
59187
59265
|
/**
|
|
59188
59266
|
* Resolve `AttachmentType` for an `AWS::EC2::VPCGatewayAttachment` from the
|
|
59189
59267
|
* first segment of cdkd's composite physicalId plus the recorded properties.
|
|
@@ -59191,19 +59269,154 @@ const GATEWAY_ATTACHMENT_TYPES = ["InternetGateway", "VPN"];
|
|
|
59191
59269
|
* The Cloud-Control-written shape already carries the attachment type verbatim
|
|
59192
59270
|
* (it is the CFn primaryIdentifier's first field). The SDK-written shape
|
|
59193
59271
|
* carries the gateway id instead, so the type is derived from WHICH gateway
|
|
59194
|
-
* property cdkd recorded — never hardcoded to
|
|
59195
|
-
* ship a wrong identifier for a VPN attachment and make CFn's
|
|
59196
|
-
* reject the import.
|
|
59272
|
+
* property cdkd recorded — never hardcoded to the internet-gateway value, which
|
|
59273
|
+
* would ship a wrong identifier for a VPN attachment and make CFn's
|
|
59274
|
+
* identifier-match reject the import.
|
|
59275
|
+
*
|
|
59276
|
+
* The VALUES are `IGW` / `VGW`, measured live (Cloud Control `ListResources`,
|
|
59277
|
+
* us-east-1, 2026-08-13) against a VPC carrying both an internet-gateway and a
|
|
59278
|
+
* virtual-private-gateway attachment:
|
|
59279
|
+
*
|
|
59280
|
+
* `IGW|vpc-…` -> {"AttachmentType":"IGW","VpcId":"vpc-…"}
|
|
59281
|
+
* `VGW|vpc-…` -> {"AttachmentType":"VGW","VpcId":"vpc-…"}
|
|
59282
|
+
*
|
|
59283
|
+
* The registry schema does not enumerate them (`AttachmentType` is a bare
|
|
59284
|
+
* `{"type": "string"}` whose description only says it distinguishes the two
|
|
59285
|
+
* kinds), which is how the spelled-out `InternetGateway` / `VPN` guesses this
|
|
59286
|
+
* function shipped with in issue #1691 went unnoticed: they are plausible, they
|
|
59287
|
+
* satisfy every unit test written against them, and CFn only rejects them at
|
|
59288
|
+
* changeset-create time — measured 2026-08-13 as `Invalid request provided:
|
|
59289
|
+
* Invalid Attachment Type 'InternetGateway'` (issue #1771).
|
|
59197
59290
|
*/
|
|
59198
59291
|
function resolveGatewayAttachmentType(firstSegment, properties) {
|
|
59199
|
-
if (
|
|
59200
|
-
if (typeof properties["InternetGatewayId"] === "string" && properties["InternetGatewayId"]) return
|
|
59201
|
-
if (typeof properties["VpnGatewayId"] === "string" && properties["VpnGatewayId"]) return
|
|
59202
|
-
if (firstSegment.startsWith("igw-")) return
|
|
59203
|
-
if (firstSegment.startsWith("vgw-")) return
|
|
59292
|
+
if (Object.hasOwn(GATEWAY_ATTACHMENT_TYPE_ALIASES, firstSegment)) return GATEWAY_ATTACHMENT_TYPE_ALIASES[firstSegment];
|
|
59293
|
+
if (typeof properties["InternetGatewayId"] === "string" && properties["InternetGatewayId"]) return GATEWAY_ATTACHMENT_TYPE_IGW;
|
|
59294
|
+
if (typeof properties["VpnGatewayId"] === "string" && properties["VpnGatewayId"]) return GATEWAY_ATTACHMENT_TYPE_VGW;
|
|
59295
|
+
if (firstSegment.startsWith("igw-")) return GATEWAY_ATTACHMENT_TYPE_IGW;
|
|
59296
|
+
if (firstSegment.startsWith("vgw-")) return GATEWAY_ATTACHMENT_TYPE_VGW;
|
|
59204
59297
|
throw new Error(`cannot determine AttachmentType for AWS::EC2::VPCGatewayAttachment: cdkd state's properties carry neither 'InternetGatewayId' nor 'VpnGatewayId', and the physical id segment '${firstSegment}' is not a recognized gateway id. State entry may be corrupt or written by an older cdkd binary; re-deploy the resource to refresh state.`);
|
|
59205
59298
|
}
|
|
59206
59299
|
/**
|
|
59300
|
+
* The `AWS::EC2::Route` destination keys, in CloudFormation's own precedence
|
|
59301
|
+
* order — the same order (and the same list) `narrowRouteDestinations` in
|
|
59302
|
+
* `src/provisioning/providers/ec2-provider.ts` resolves them in when it decides
|
|
59303
|
+
* which one `createRoute` actually sends, i.e. which one ends up in the
|
|
59304
|
+
* physicalId's destination segment. Restated here rather than imported so this
|
|
59305
|
+
* command does not pull the EC2 provider (and its SDK client) into the export
|
|
59306
|
+
* module graph.
|
|
59307
|
+
*/
|
|
59308
|
+
const ROUTE_DESTINATION_KEYS = [
|
|
59309
|
+
"DestinationCidrBlock",
|
|
59310
|
+
"DestinationIpv6CidrBlock",
|
|
59311
|
+
"DestinationPrefixListId"
|
|
59312
|
+
];
|
|
59313
|
+
/**
|
|
59314
|
+
* Resolve the value CFn's read-only `AWS::EC2::Route.CidrBlock` identifier
|
|
59315
|
+
* field holds, from cdkd's physicalId destination segment plus the recorded
|
|
59316
|
+
* properties.
|
|
59317
|
+
*
|
|
59318
|
+
* The segment is the starting point — it is the destination cdkd sent to
|
|
59319
|
+
* `CreateRoute` (SDK path) or the `CidrBlock` AWS itself reported (Cloud Control
|
|
59320
|
+
* path), and `CidrBlock` holds whichever destination kind the route declares,
|
|
59321
|
+
* measured live; see the splitter's comment. But it is NOT returned verbatim:
|
|
59322
|
+
* EC2 clears host bits on the way in, so the SDK path can have stored a
|
|
59323
|
+
* destination AWS never held, and the identifier is always the CANONICAL form.
|
|
59324
|
+
*
|
|
59325
|
+
* The recorded properties are then read to CROSS-CHECK it, the way
|
|
59326
|
+
* {@link resolveGatewayAttachmentType} reads them to recover a field cdkd never
|
|
59327
|
+
* stores. Two very different things can make them disagree, and conflating them
|
|
59328
|
+
* is why this is not a plain warn:
|
|
59329
|
+
*
|
|
59330
|
+
* - **Benign.** One side carries AWS's CANONICALIZED CIDR and the other what
|
|
59331
|
+
* the user wrote; CFn documents rewriting e.g. `100.68.0.18/18` to
|
|
59332
|
+
* `100.68.0.0/18`. The identifier is CORRECT here, so refusing would block an
|
|
59333
|
+
* export that would have succeeded. Both sides are compared in canonical
|
|
59334
|
+
* form, so this case never even registers as a divergence.
|
|
59335
|
+
* - **Dangerous.** If state is merely stale, the id's destination can name a
|
|
59336
|
+
* DIFFERENT route that still exists in the same table. IMPORT then succeeds
|
|
59337
|
+
* against the wrong resource, and phase 2's UPDATE reconciles it to the
|
|
59338
|
+
* template — REPLACING, i.e. DELETING, a route the user never targeted.
|
|
59339
|
+
* Silently continuing here trades an opaque failure for data loss.
|
|
59340
|
+
*
|
|
59341
|
+
* So the outcome depends on whether the benign explanation is DECIDABLE, which
|
|
59342
|
+
* {@link routeDestinationNormalizationIsModelled} answers per declared value.
|
|
59343
|
+
* When every declared destination is a shape cdkd models — an IPv4 CIDR or a
|
|
59344
|
+
* prefix-list id — normalization either explains the difference or it does not,
|
|
59345
|
+
* and a non-match is refused. When any declared destination is an IPv6 CIDR,
|
|
59346
|
+
* whose AWS-side canonicalization cdkd does not reproduce, the divergence is
|
|
59347
|
+
* reported as a WARNING naming the replace-the-wrong-route outcome, because
|
|
59348
|
+
* refusing on an undecidable signal would block exports that are fine.
|
|
59349
|
+
*
|
|
59350
|
+
* Properties that declare NO destination at all are NOT treated as suspicious:
|
|
59351
|
+
* a partial / hand-edited state record must not become a refusal, and the id
|
|
59352
|
+
* alone is enough to build the identifier.
|
|
59353
|
+
*/
|
|
59354
|
+
function resolveRouteDestination(segment, properties) {
|
|
59355
|
+
const identifier = canonicalizeIpv4Cidr(segment) ?? segment;
|
|
59356
|
+
const declared = ROUTE_DESTINATION_KEYS.filter((key) => typeof properties[key] === "string" && properties[key] !== "");
|
|
59357
|
+
if (declared.length === 0) return identifier;
|
|
59358
|
+
const declaredValues = declared.map((key) => String(properties[key]));
|
|
59359
|
+
if (declaredValues.some((value) => (canonicalizeIpv4Cidr(value) ?? value) === identifier)) return identifier;
|
|
59360
|
+
const shared = `AWS::EC2::Route: cdkd state's recorded properties declare ${declared.map((key) => `${key}='${String(properties[key])}'`).join(", ")}, but the physical id's destination segment is '${segment}'. CloudFormation identifies the route by the destination, so IMPORT would adopt whatever route currently sits at '${identifier}' — and if that is a DIFFERENT route than the template declares, phase 2 would then REPLACE (delete) it. The state entry is stale; re-deploy the resource to refresh it`;
|
|
59361
|
+
if (declaredValues.every((value) => routeDestinationNormalizationIsModelled(value))) throw new Error(`${shared}.`);
|
|
59362
|
+
getLogger().warn(`${shared}, or pass the resource through 'cdkd import --resource' with the correct id. Continuing with the physical id because at least one recorded destination is an IPv6 CIDR, whose AWS-side canonicalization cdkd does not model — so the difference may be benign.`);
|
|
59363
|
+
return identifier;
|
|
59364
|
+
}
|
|
59365
|
+
/**
|
|
59366
|
+
* An EC2 managed prefix list id (`pl-` + hex). Matched EXACTLY rather than by
|
|
59367
|
+
* prefix so a malformed value falls into the unmodelled class instead of being
|
|
59368
|
+
* treated as a comparable destination.
|
|
59369
|
+
*/
|
|
59370
|
+
const ROUTE_PREFIX_LIST_ID_PATTERN = /^pl-[0-9a-f]+$/;
|
|
59371
|
+
/**
|
|
59372
|
+
* True when cdkd models how AWS normalizes this destination value, i.e. when a
|
|
59373
|
+
* mismatch against the physical id's segment is CONCLUSIVE rather than possibly
|
|
59374
|
+
* explained by a rewrite cdkd cannot reproduce.
|
|
59375
|
+
*
|
|
59376
|
+
* Two classes qualify:
|
|
59377
|
+
* - an IPv4 CIDR, whose host-bit rewrite {@link canonicalizeIpv4Cidr} reproduces;
|
|
59378
|
+
* - a prefix-list id, measured to be stored verbatim on both sides, so a
|
|
59379
|
+
* `pl-AAA` vs `pl-BBB` difference is a genuine wrong-route signal.
|
|
59380
|
+
*
|
|
59381
|
+
* An IPv6 CIDR does not: AWS canonicalizes those too (zero-run compression,
|
|
59382
|
+
* host-bit clearing) and cdkd does not reproduce it, so a mismatch there could
|
|
59383
|
+
* still be the same route written two ways.
|
|
59384
|
+
*/
|
|
59385
|
+
function routeDestinationNormalizationIsModelled(value) {
|
|
59386
|
+
return canonicalizeIpv4Cidr(value) !== void 0 || ROUTE_PREFIX_LIST_ID_PATTERN.test(value);
|
|
59387
|
+
}
|
|
59388
|
+
/**
|
|
59389
|
+
* Return the host-bit-cleared form of an IPv4 CIDR (`100.68.0.18/18` ->
|
|
59390
|
+
* `100.68.0.0/18`), or `undefined` when the input is not an IPv4 CIDR at all
|
|
59391
|
+
* (an IPv6 CIDR, a `pl-…` prefix-list id, or anything malformed).
|
|
59392
|
+
*
|
|
59393
|
+
* This exists to recognize the ONE benign reason an `AWS::EC2::Route`'s stored
|
|
59394
|
+
* destination can differ from its physicalId segment: AWS rewrites a
|
|
59395
|
+
* non-canonical CIDR on `CreateRoute`, and the Cloud Control path records what
|
|
59396
|
+
* AWS returned while the template kept what the user wrote. Returning
|
|
59397
|
+
* `undefined` for the shapes it does not model is load-bearing — the caller
|
|
59398
|
+
* uses it to decide whether a divergence is conclusive or merely unexplained.
|
|
59399
|
+
*/
|
|
59400
|
+
function canonicalizeIpv4Cidr(value) {
|
|
59401
|
+
const match = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\/(\d{1,2})$/.exec(value);
|
|
59402
|
+
if (!match) return void 0;
|
|
59403
|
+
const octets = [
|
|
59404
|
+
match[1],
|
|
59405
|
+
match[2],
|
|
59406
|
+
match[3],
|
|
59407
|
+
match[4]
|
|
59408
|
+
].map(Number);
|
|
59409
|
+
const prefixLength = Number(match[5]);
|
|
59410
|
+
if (prefixLength > 32 || octets.some((octet) => octet > 255)) return void 0;
|
|
59411
|
+
const network = ((octets[0] << 24 | octets[1] << 16 | octets[2] << 8 | octets[3]) >>> 0 & (prefixLength === 0 ? 0 : 4294967295 << 32 - prefixLength >>> 0)) >>> 0;
|
|
59412
|
+
return `${[
|
|
59413
|
+
network >>> 24,
|
|
59414
|
+
network >>> 16 & 255,
|
|
59415
|
+
network >>> 8 & 255,
|
|
59416
|
+
network & 255
|
|
59417
|
+
].join(".")}/${prefixLength}`;
|
|
59418
|
+
}
|
|
59419
|
+
/**
|
|
59207
59420
|
* Build a splitter for an `AWS::ApiGateway::*` child type whose CFn primary
|
|
59208
59421
|
* identifier is the parent `RestApiId` plus one child field.
|
|
59209
59422
|
*
|
|
@@ -60201,7 +60414,7 @@ async function buildImportPlan(state, template, cfnClient, parentStackName, opti
|
|
|
60201
60414
|
* IMPORT pre-flight and this resolution.
|
|
60202
60415
|
*/
|
|
60203
60416
|
function resolveResourceIdentifier(resourceType, logicalId, physicalId, properties, attributes, entry) {
|
|
60204
|
-
const compositeIdentifier = COMPOSITE_PHYSICAL_ID_IDENTIFIERS[resourceType];
|
|
60417
|
+
const compositeIdentifier = Object.hasOwn(COMPOSITE_PHYSICAL_ID_IDENTIFIERS, resourceType) ? COMPOSITE_PHYSICAL_ID_IDENTIFIERS[resourceType] : void 0;
|
|
60205
60418
|
if (compositeIdentifier) {
|
|
60206
60419
|
if (entry.fields.length !== 1 || entry.fields[0] !== compositeIdentifier.field) throw new Error(`${resourceType} is registered in COMPOSITE_PHYSICAL_ID_IDENTIFIERS as identified by '${compositeIdentifier.field}', but CloudFormation now reports primaryIdentifier [${entry.fields.join(", ")}]. The registry schema changed under cdkd — update the entry in src/cli/commands/export.ts (or move the type to COMPOSITE_ID_SPLITTERS if its identifier is now composite too)`);
|
|
60207
60420
|
const value = compositeIdentifier.resolve({
|
|
@@ -60215,7 +60428,7 @@ function resolveResourceIdentifier(resourceType, logicalId, physicalId, properti
|
|
|
60215
60428
|
};
|
|
60216
60429
|
}
|
|
60217
60430
|
if (entry.fields.length === 1) return { resourceIdentifier: { [entry.fields[0]]: physicalId } };
|
|
60218
|
-
const splitter = COMPOSITE_ID_SPLITTERS[resourceType];
|
|
60431
|
+
const splitter = Object.hasOwn(COMPOSITE_ID_SPLITTERS, resourceType) ? COMPOSITE_ID_SPLITTERS[resourceType] : void 0;
|
|
60219
60432
|
if (!splitter) throw new Error(`resource type uses a composite primary identifier (${entry.fields.length} fields: ${entry.fields.join(", ")}); add an entry to COMPOSITE_ID_SPLITTERS in src/cli/commands/export.ts that parses cdkd's physicalId for this type, or destroy the resource first and let CFn create it fresh`);
|
|
60220
60433
|
let result;
|
|
60221
60434
|
try {
|
|
@@ -68186,20 +68399,64 @@ function ecrUrlSuffix(region) {
|
|
|
68186
68399
|
return derivePartitionAndUrlSuffix(region).urlSuffix;
|
|
68187
68400
|
}
|
|
68188
68401
|
/**
|
|
68402
|
+
* Lower-case the REGISTRY HOST of an image reference and leave the repository
|
|
68403
|
+
* path and tag byte-identical.
|
|
68404
|
+
*
|
|
68405
|
+
* A registry host is a DNS name and therefore case-INSENSITIVE, but docker's
|
|
68406
|
+
* credential store is keyed on the hostname VERBATIM: measured against a real
|
|
68407
|
+
* daemon with a `DOCKER_CONFIG` holding auth for
|
|
68408
|
+
* `<acct>.dkr.ecr.us-east-1.amazonaws.com`, a pull of
|
|
68409
|
+
* `<acct>.dkr.ecr.US-EAST-1.amazonaws.com/...` sent NO credentials at all
|
|
68410
|
+
* (`no basic auth credentials`) while the lower-cased spelling authenticated
|
|
68411
|
+
* and failed with a token error instead. So cdkd logging in to one spelling
|
|
68412
|
+
* and pulling from another authenticates against neither.
|
|
68413
|
+
*
|
|
68414
|
+
* The repository path and tag are deliberately NOT folded: only the domain is
|
|
68415
|
+
* case-insensitive, docker already requires the path to be lower case, and
|
|
68416
|
+
* rewriting it would change WHICH image is pulled.
|
|
68417
|
+
*
|
|
68418
|
+
* "Everything before the first `/`" is NOT the same thing as "the host", which
|
|
68419
|
+
* is why the first component is tested rather than assumed. Docker treats it
|
|
68420
|
+
* as a registry only when it contains a `.` or a `:` or is exactly
|
|
68421
|
+
* `localhost`; otherwise it is the first segment of a Docker Hub repository
|
|
68422
|
+
* PATH (`MyOrg/MyRepo:tag` is `docker.io/MyOrg/MyRepo:tag`). Folding that
|
|
68423
|
+
* would name a DIFFERENT image. Today every caller is behind the strict ECR
|
|
68424
|
+
* host check so the distinction is inert, but this is exported under a generic
|
|
68425
|
+
* name and the contract has to be the real one.
|
|
68426
|
+
*/
|
|
68427
|
+
function canonicalizeImageUriHost(imageUri) {
|
|
68428
|
+
const slash = imageUri.indexOf("/");
|
|
68429
|
+
if (slash < 0) return imageUri;
|
|
68430
|
+
const host = imageUri.slice(0, slash);
|
|
68431
|
+
if (!isRegistryHostComponent(host)) return imageUri;
|
|
68432
|
+
return host.toLowerCase() + imageUri.slice(slash);
|
|
68433
|
+
}
|
|
68434
|
+
/** Docker's rule for "component 1 is a registry, not a repository segment". */
|
|
68435
|
+
function isRegistryHostComponent(component) {
|
|
68436
|
+
return component.includes(".") || component.includes(":") || component === "localhost";
|
|
68437
|
+
}
|
|
68438
|
+
/**
|
|
68189
68439
|
* Parse an ECR image URI. Returns `undefined` for non-ECR URIs (typically:
|
|
68190
68440
|
* Docker Hub, public.ecr.aws, gcr.io, ...) — those are user-managed
|
|
68191
68441
|
* images we don't try to authenticate against.
|
|
68442
|
+
*
|
|
68443
|
+
* The host is canonicalized BEFORE the registry-host match, so a mixed-case
|
|
68444
|
+
* genuine ECR host classifies as ECR (and its `region` comes back in the
|
|
68445
|
+
* spelling the ECR endpoint and the `docker login` both use) rather than
|
|
68446
|
+
* falling through to the anonymous-pull path.
|
|
68192
68447
|
*/
|
|
68193
68448
|
function parseEcrUri(imageUri) {
|
|
68194
|
-
const
|
|
68449
|
+
const canonicalUri = canonicalizeImageUriHost(imageUri);
|
|
68450
|
+
const host = parseEcrRegistryHost(canonicalUri);
|
|
68195
68451
|
if (!host) return void 0;
|
|
68196
|
-
const m = /^([^:]+):(.+)$/.exec(
|
|
68452
|
+
const m = /^([^:]+):(.+)$/.exec(canonicalUri.slice(canonicalUri.indexOf("/") + 1));
|
|
68197
68453
|
if (!m) return void 0;
|
|
68198
68454
|
return {
|
|
68199
68455
|
accountId: host.accountId,
|
|
68200
|
-
region: host.region,
|
|
68456
|
+
region: canonicalizeRegion(host.region),
|
|
68201
68457
|
repository: m[1],
|
|
68202
|
-
tag: m[2]
|
|
68458
|
+
tag: m[2],
|
|
68459
|
+
canonicalUri
|
|
68203
68460
|
};
|
|
68204
68461
|
}
|
|
68205
68462
|
/**
|
|
@@ -68239,17 +68496,24 @@ function isCredentialFresh(creds) {
|
|
|
68239
68496
|
*
|
|
68240
68497
|
* Auto-detects cross-account from `STS:GetCallerIdentity` and assumes
|
|
68241
68498
|
* the supplied role when set. Returns the image URI the caller should
|
|
68242
|
-
* pass to `docker run
|
|
68499
|
+
* pass to `docker run`: the input with its registry HOST lower-cased and
|
|
68500
|
+
* its repository path + tag untouched (issue #1801). That is the SAME
|
|
68501
|
+
* spelling `docker pull` / `docker image inspect` were handed here, and
|
|
68502
|
+
* the same one the DERIVED `docker login` endpoint names — an
|
|
68503
|
+
* AWS-reported `proxyEndpoint` still wins over that fallback (it can be
|
|
68504
|
+
* a VPC-endpoint host), which is correct: AWS names the endpoint its own
|
|
68505
|
+
* token authenticates, and it reports it lower-cased.
|
|
68243
68506
|
*/
|
|
68244
68507
|
async function pullEcrImage(imageUri, options) {
|
|
68245
68508
|
const logger = getLogger().child("ecr-puller");
|
|
68246
68509
|
const parsed = parseEcrUri(imageUri);
|
|
68247
68510
|
if (!parsed) throw new LocalInvokeBuildError$1(`Image URI '${imageUri}' is not an ECR URI. cdkd local invoke v1 only authenticates against ECR for the deployed-image fallback path.`);
|
|
68248
|
-
const
|
|
68511
|
+
const canonicalUri = parsed.canonicalUri;
|
|
68512
|
+
const callerRegion = canonicalizeRegion(options.region ?? process.env["AWS_REGION"] ?? process.env["AWS_DEFAULT_REGION"]);
|
|
68249
68513
|
if (options.skipPull) {
|
|
68250
|
-
logger.info(`Skipping ECR pull (--no-pull). Verifying ${
|
|
68251
|
-
await verifyImageInLocalCache(
|
|
68252
|
-
return
|
|
68514
|
+
logger.info(`Skipping ECR pull (--no-pull). Verifying ${canonicalUri} is in local cache...`);
|
|
68515
|
+
await verifyImageInLocalCache(canonicalUri);
|
|
68516
|
+
return canonicalUri;
|
|
68253
68517
|
}
|
|
68254
68518
|
const callerIdentityKey = callerRegion ?? "_unset";
|
|
68255
68519
|
let callerAccount = CALLER_IDENTITY_CACHE.get(callerIdentityKey);
|
|
@@ -68289,13 +68553,13 @@ async function pullEcrImage(imageUri, options) {
|
|
|
68289
68553
|
} finally {
|
|
68290
68554
|
ecr.destroy();
|
|
68291
68555
|
}
|
|
68292
|
-
logger.info(`Pulling ${
|
|
68556
|
+
logger.info(`Pulling ${canonicalUri}...`);
|
|
68293
68557
|
try {
|
|
68294
|
-
await runDockerForeground(["pull",
|
|
68558
|
+
await runDockerForeground(["pull", canonicalUri]);
|
|
68295
68559
|
} catch (err) {
|
|
68296
|
-
throw new LocalInvokeBuildError$1(`docker pull ${
|
|
68560
|
+
throw new LocalInvokeBuildError$1(`docker pull ${canonicalUri} failed: ${err.message}`);
|
|
68297
68561
|
}
|
|
68298
|
-
return
|
|
68562
|
+
return canonicalUri;
|
|
68299
68563
|
}
|
|
68300
68564
|
/**
|
|
68301
68565
|
* Assume the supplied role via the SDK default credential chain and
|
|
@@ -69509,6 +69773,7 @@ function clampConcurrency(input) {
|
|
|
69509
69773
|
async function localStartApiCommand(target, options) {
|
|
69510
69774
|
const logger = getLogger();
|
|
69511
69775
|
if (options.verbose) logger.setLevel("debug");
|
|
69776
|
+
if (options.region !== void 0) options.region = canonicalizeRegion(options.region);
|
|
69512
69777
|
let apiFilter = target;
|
|
69513
69778
|
if (options.api !== void 0) {
|
|
69514
69779
|
if (target !== void 0) throw new Error(`Cannot specify both positional target ('${target}') and --api flag ('${options.api}'). Use one or the other. The positional form is preferred — '--api' is a deprecated alias.`);
|
|
@@ -70915,10 +71180,18 @@ async function loadStateForRoutedStacks(stacks, routes, routesWithAuth, options)
|
|
|
70915
71180
|
*
|
|
70916
71181
|
* Region precedence: `--region` > `AWS_REGION` > `AWS_DEFAULT_REGION` >
|
|
70917
71182
|
* the state record's region (returned by the active `LocalStateProvider`).
|
|
71183
|
+
*
|
|
71184
|
+
* The resolved region is CANONICALIZED (issue #1795) before anything consumes
|
|
71185
|
+
* it. That covers all four sources — `--region`, both env vars, and the state
|
|
71186
|
+
* record's region — and all three consumers: the STS client built for
|
|
71187
|
+
* `${AWS::AccountId}`, the `${AWS::URLSuffix}` / `${AWS::Partition}`
|
|
71188
|
+
* derivation, and the `${AWS::Region}` value itself.
|
|
71189
|
+
*
|
|
71190
|
+
* @internal exported for unit tests.
|
|
70918
71191
|
*/
|
|
70919
71192
|
async function resolvePseudoParametersForStartApi(stateRegion, options) {
|
|
70920
71193
|
const logger = getLogger();
|
|
70921
|
-
const region = options.region ?? process.env["AWS_REGION"] ?? process.env["AWS_DEFAULT_REGION"] ?? stateRegion;
|
|
71194
|
+
const region = canonicalizeRegion(options.region ?? process.env["AWS_REGION"] ?? process.env["AWS_DEFAULT_REGION"] ?? stateRegion);
|
|
70922
71195
|
let accountId;
|
|
70923
71196
|
try {
|
|
70924
71197
|
const { STSClient, GetCallerIdentityCommand } = await import("@aws-sdk/client-sts");
|
|
@@ -71842,6 +72115,7 @@ async function localRunTaskCommand(target, options) {
|
|
|
71842
72115
|
const logger = getLogger();
|
|
71843
72116
|
if (options.verbose) logger.setLevel("debug");
|
|
71844
72117
|
warnIfDeprecatedRegion(options);
|
|
72118
|
+
if (options.region !== void 0) options.region = canonicalizeRegion(options.region);
|
|
71845
72119
|
const state = createEcsRunState();
|
|
71846
72120
|
let sigintHandler;
|
|
71847
72121
|
let sigintCount = 0;
|
|
@@ -72011,6 +72285,14 @@ async function assumeTaskRole(roleArn, region) {
|
|
|
72011
72285
|
* load) routes through the active {@link LocalStateProvider} so both
|
|
72012
72286
|
* `--from-state` and `--from-cfn-stack` produce the same downstream
|
|
72013
72287
|
* context shape (issue #606).
|
|
72288
|
+
*
|
|
72289
|
+
* The resolved region is CANONICALIZED (issue #1795) before anything consumes
|
|
72290
|
+
* it. That covers all four sources — `--region`, both env vars, and the
|
|
72291
|
+
* synth-derived stack region — and all three consumers: the STS client built
|
|
72292
|
+
* for `${AWS::AccountId}`, the `${AWS::URLSuffix}` / `${AWS::Partition}`
|
|
72293
|
+
* derivation, and the `${AWS::Region}` value itself.
|
|
72294
|
+
*
|
|
72295
|
+
* @internal exported for unit tests.
|
|
72014
72296
|
*/
|
|
72015
72297
|
async function buildEcsImageResolutionContext$1(candidate, stateProvider, options) {
|
|
72016
72298
|
const logger = getLogger();
|
|
@@ -72020,7 +72302,7 @@ async function buildEcsImageResolutionContext$1(candidate, stateProvider, option
|
|
|
72020
72302
|
const ctx = {};
|
|
72021
72303
|
const wantsPseudoForEnvOrSecret = !!stateProvider && needs.needsEnvOrSecretSubstitution;
|
|
72022
72304
|
if (needs.needsPseudoParameters || wantsPseudoForEnvOrSecret) {
|
|
72023
|
-
const region = options.region ?? process.env["AWS_REGION"] ?? process.env["AWS_DEFAULT_REGION"] ?? candidate.region;
|
|
72305
|
+
const region = canonicalizeRegion(options.region ?? process.env["AWS_REGION"] ?? process.env["AWS_DEFAULT_REGION"] ?? candidate.region);
|
|
72024
72306
|
if (!region) logger.warn("Resolver references ${AWS::Region} but cdkd could not determine the target region. Pass --region, set AWS_REGION, or declare env.region on the CDK stack.");
|
|
72025
72307
|
let accountId;
|
|
72026
72308
|
try {
|
|
@@ -73688,6 +73970,7 @@ async function localInvokeCommand(target, options) {
|
|
|
73688
73970
|
const logger = getLogger();
|
|
73689
73971
|
if (options.verbose) logger.setLevel("debug");
|
|
73690
73972
|
warnIfDeprecatedRegion(options);
|
|
73973
|
+
if (options.region !== void 0) options.region = canonicalizeRegion(options.region);
|
|
73691
73974
|
let imagePlan;
|
|
73692
73975
|
let containerId;
|
|
73693
73976
|
let stopLogs;
|
|
@@ -74168,10 +74451,18 @@ function envHasCrossStackIntrinsic(templateEnv) {
|
|
|
74168
74451
|
*
|
|
74169
74452
|
* Region precedence (mirrors `local-run-task`): `--region` > `AWS_REGION`
|
|
74170
74453
|
* > `AWS_DEFAULT_REGION` > the synth-derived stack region.
|
|
74454
|
+
*
|
|
74455
|
+
* The resolved region is CANONICALIZED (issue #1795) before anything consumes
|
|
74456
|
+
* it. That covers all four sources — `--region`, both env vars, and the
|
|
74457
|
+
* synth-derived stack region — and all three consumers: the STS client built
|
|
74458
|
+
* for `${AWS::AccountId}`, the `${AWS::URLSuffix}` / `${AWS::Partition}`
|
|
74459
|
+
* derivation, and the `${AWS::Region}` value itself.
|
|
74460
|
+
*
|
|
74461
|
+
* @internal exported for unit tests.
|
|
74171
74462
|
*/
|
|
74172
74463
|
async function resolvePseudoParametersForInvoke(stackRegion, options) {
|
|
74173
74464
|
const logger = getLogger();
|
|
74174
|
-
const region = options.region ?? process.env["AWS_REGION"] ?? process.env["AWS_DEFAULT_REGION"] ?? stackRegion;
|
|
74465
|
+
const region = canonicalizeRegion(options.region ?? process.env["AWS_REGION"] ?? process.env["AWS_DEFAULT_REGION"] ?? stackRegion);
|
|
74175
74466
|
if (!region) logger.warn("--from-state: resolver references ${AWS::Region} but cdkd could not determine the target region. Pass --region, set AWS_REGION, or declare env.region on the CDK stack.");
|
|
74176
74467
|
let accountId;
|
|
74177
74468
|
try {
|
|
@@ -75550,7 +75841,7 @@ function createMigrateCommand() {
|
|
|
75550
75841
|
*/
|
|
75551
75842
|
function buildProgram() {
|
|
75552
75843
|
const program = new Command();
|
|
75553
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.282.
|
|
75844
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.282.5");
|
|
75554
75845
|
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
75555
75846
|
const { profile } = actionCommand.optsWithGlobals();
|
|
75556
75847
|
if (profile !== void 0) process.env["AWS_PROFILE"] = profile;
|