@go-to-k/cdkd 0.278.36 → 0.278.37
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-5hYG8VHd.js → asg-provider-BTeSlton.js} +2 -2
- package/dist/{asg-provider-5hYG8VHd.js.map → asg-provider-BTeSlton.js.map} +1 -1
- package/dist/cli.js +215 -24
- package/dist/cli.js.map +1 -1
- package/dist/{deploy-engine-iHGY-Q_U.js → deploy-engine-bEhHOGVR.js} +3 -3
- package/dist/{deploy-engine-iHGY-Q_U.js.map → deploy-engine-bEhHOGVR.js.map} +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as describeTypeWithThrottleRetry, $t as AwsClients, A as red, At as Synthesizer, B as isTerminationProtectionPropagationError, Bt as resolveUseCdkBootstrapAssets, C as isStatefulRecreateTargetSync, Ct as buildDockerImage, D as cyan, Dt as runDockerStreaming, E as bold, Et as runDockerForeground, F as ProviderRegistry, Ft as resolveAutoAssetStorage, G as normalizeAwsTagsToCfn, Gt as MIGRATE_TMP_PREFIX, H as cfnRefValueFromPhysicalId, Ht as warnDeprecatedNoPrefixCliFlag, I as findActionableSilentDrops, It as resolveCaptureObservedState, J as readConfigString, Jt as expectedOwnerParam, K as resolveExplicitPhysicalId, Kt as findLargeInlineResources, L as CloudControlProvider, Lt as resolveSkipPrefix, M as IAMRoleProvider, Mt as getDefaultStateBucketName, N as collectInlinePolicyNamesManagedBySiblings, Nt as getLegacyStateBucketName, O as gray, Ot as AssetManifestLoader, P as clearOnUpdateRemoval, Pt as resolveApp, Q as DiffCalculator, Qt as resolveBucketRegion, R as slowCcOperationTimeoutMs, Rt as resolveStateBucketWithDefault, S as MULTI_REGION_RECREATE_BLOCKED_TYPES, St as validateContainerRepoName, T as formatResourceLine, Tn as withErrorHandling, Tt as getDockerCmd, U as refStateLookupFromResource, Ut as CFN_TEMPLATE_BODY_LIMIT, V as IntrinsicFunctionResolver, Vt as stateBucketExistenceConfirmed, W as WAFv2WebACLProvider, Wt as CFN_TEMPLATE_URL_LIMIT, X as requireConfigString, Xt as processStackMessages, Y as requireConfigArray, Yt as AssemblyReader, Z as applyRoleArnIfSet, _ as createPreDeleteFinalSnapshot, _n as ResourceUpdateNotSupportedError, _t as BOOTSTRAP_MARKER_PREFIX, a as DeploymentEventsStore, at as LockManager, b as unsupportedFinalSnapshotError, bt as parseBootstrapMarker, c as replayFailedOperations, cn as LocalInvokeBuildError$1, ct as shouldRetainResource, d as IMPLICIT_DELETE_DEPENDENCIES, dt as WorkGraph, en as getAwsClients, et as withRetry, f as computeImplicitDeleteEdges, fn as MissingCdkCliError, ft as buildAssetRedirectMap, g as ccRoutedFinalSnapshotError, gn as ResourceTimeoutError, gt as AssetModeResolver, h as buildFinalSnapshotIdentifier, hn as ProvisioningError, ht as rewriteTemplateAssetReferences, i as DeploymentEventsReader, in as CdkdError, it as TemplateParser, j as yellow, jt as synthesisStatusMessage, k as green, kt as getDockerImageBySourceHash, l as replayRollback, ln as LocalMigrateError, lt as AssetPublisher, m as PRE_DELETE_SNAPSHOT_TYPES, mn as PartialFailureError, mt as loadPublishableAssetManifest, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as setAwsClients, nt as isThrottlingError, o as planFailedOps, ot as S3StateBackend, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as NestedStackChildDirectDestroyError, pt as createAssetRedirectResolver, q as assertRegionMatch, qt as uploadCfnTemplate, r as DeployEngine, rt as DagBuilder, s as planRollback, sn as DeployCancelledError, st as rebuildClientForBucketRegion, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as resetAwsClients, tt as isRetryableTransientError, u as withResourceDeadline, un as LocalStartServiceError, ut as stringifyValue, v as isFinalSnapshotError, vn as StackHasActiveImportsError, vt as ensureAssetStorage, w as renderStatefulReason, wn as normalizeAwsError, wt as formatDockerLoginError, x as extractDeploymentEventError, xt as validateAssetBucketName, y as refusesFinalSnapshot, yn as StackTerminationProtectionError, yt as getBootstrapMarkerKey, z as disableInstanceApiTermination, zt as resolveStateBucketWithDefaultAndSource } from "./deploy-engine-
|
|
2
|
+
import { $ as describeTypeWithThrottleRetry, $t as AwsClients, A as red, At as Synthesizer, B as isTerminationProtectionPropagationError, Bt as resolveUseCdkBootstrapAssets, C as isStatefulRecreateTargetSync, Ct as buildDockerImage, D as cyan, Dt as runDockerStreaming, E as bold, Et as runDockerForeground, F as ProviderRegistry, Ft as resolveAutoAssetStorage, G as normalizeAwsTagsToCfn, Gt as MIGRATE_TMP_PREFIX, H as cfnRefValueFromPhysicalId, Ht as warnDeprecatedNoPrefixCliFlag, I as findActionableSilentDrops, It as resolveCaptureObservedState, J as readConfigString, Jt as expectedOwnerParam, K as resolveExplicitPhysicalId, Kt as findLargeInlineResources, L as CloudControlProvider, Lt as resolveSkipPrefix, M as IAMRoleProvider, Mt as getDefaultStateBucketName, N as collectInlinePolicyNamesManagedBySiblings, Nt as getLegacyStateBucketName, O as gray, Ot as AssetManifestLoader, P as clearOnUpdateRemoval, Pt as resolveApp, Q as DiffCalculator, Qt as resolveBucketRegion, R as slowCcOperationTimeoutMs, Rt as resolveStateBucketWithDefault, S as MULTI_REGION_RECREATE_BLOCKED_TYPES, St as validateContainerRepoName, T as formatResourceLine, Tn as withErrorHandling, Tt as getDockerCmd, U as refStateLookupFromResource, Ut as CFN_TEMPLATE_BODY_LIMIT, V as IntrinsicFunctionResolver, Vt as stateBucketExistenceConfirmed, W as WAFv2WebACLProvider, Wt as CFN_TEMPLATE_URL_LIMIT, X as requireConfigString, Xt as processStackMessages, Y as requireConfigArray, Yt as AssemblyReader, Z as applyRoleArnIfSet, _ as createPreDeleteFinalSnapshot, _n as ResourceUpdateNotSupportedError, _t as BOOTSTRAP_MARKER_PREFIX, a as DeploymentEventsStore, at as LockManager, b as unsupportedFinalSnapshotError, bt as parseBootstrapMarker, c as replayFailedOperations, cn as LocalInvokeBuildError$1, ct as shouldRetainResource, d as IMPLICIT_DELETE_DEPENDENCIES, dt as WorkGraph, en as getAwsClients, et as withRetry, f as computeImplicitDeleteEdges, fn as MissingCdkCliError, ft as buildAssetRedirectMap, g as ccRoutedFinalSnapshotError, gn as ResourceTimeoutError, gt as AssetModeResolver, h as buildFinalSnapshotIdentifier, hn as ProvisioningError, ht as rewriteTemplateAssetReferences, i as DeploymentEventsReader, in as CdkdError, it as TemplateParser, j as yellow, jt as synthesisStatusMessage, k as green, kt as getDockerImageBySourceHash, l as replayRollback, ln as LocalMigrateError, lt as AssetPublisher, m as PRE_DELETE_SNAPSHOT_TYPES, mn as PartialFailureError, mt as loadPublishableAssetManifest, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as setAwsClients, nt as isThrottlingError, o as planFailedOps, ot as S3StateBackend, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as NestedStackChildDirectDestroyError, pt as createAssetRedirectResolver, q as assertRegionMatch, qt as uploadCfnTemplate, r as DeployEngine, rt as DagBuilder, s as planRollback, sn as DeployCancelledError, st as rebuildClientForBucketRegion, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as resetAwsClients, tt as isRetryableTransientError, u as withResourceDeadline, un as LocalStartServiceError, ut as stringifyValue, v as isFinalSnapshotError, vn as StackHasActiveImportsError, vt as ensureAssetStorage, w as renderStatefulReason, wn as normalizeAwsError, wt as formatDockerLoginError, x as extractDeploymentEventError, xt as validateAssetBucketName, y as refusesFinalSnapshot, yn as StackTerminationProtectionError, yt as getBootstrapMarkerKey, z as disableInstanceApiTermination, zt as resolveStateBucketWithDefaultAndSource } from "./deploy-engine-bEhHOGVR.js";
|
|
3
3
|
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-BYMEE-BS.js";
|
|
4
|
-
import { t as ASGProvider } from "./asg-provider-
|
|
4
|
+
import { t as ASGProvider } from "./asg-provider-BTeSlton.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";
|
|
@@ -12315,7 +12315,8 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
12315
12315
|
AttributeDefinitions: attributeDefinitions,
|
|
12316
12316
|
BillingMode: billingMode
|
|
12317
12317
|
};
|
|
12318
|
-
|
|
12318
|
+
const diagnostics = [];
|
|
12319
|
+
if (billingMode === "PROVISIONED") createParams.ProvisionedThroughput = derivePerCallProvisionedThroughput(properties, currentRegion, "min", diagnostics);
|
|
12319
12320
|
const streamSpecInput = properties["StreamSpecification"];
|
|
12320
12321
|
const needsStream = replicas.some((r) => r["Region"] !== currentRegion) || replicas.length > 1;
|
|
12321
12322
|
if (streamSpecInput != null) {
|
|
@@ -12336,7 +12337,6 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
12336
12337
|
StreamViewType: "NEW_AND_OLD_IMAGES"
|
|
12337
12338
|
};
|
|
12338
12339
|
}
|
|
12339
|
-
const diagnostics = [];
|
|
12340
12340
|
let sdkIndexes;
|
|
12341
12341
|
try {
|
|
12342
12342
|
sdkIndexes = toSdkGlobalSecondaryIndexes(properties, currentRegion, billingMode, "min", diagnostics);
|
|
@@ -12552,7 +12552,10 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
12552
12552
|
const onDemandCeilingLive = oldBilling === "PAY_PER_REQUEST" && newBilling === "PAY_PER_REQUEST";
|
|
12553
12553
|
const diagnostics = [];
|
|
12554
12554
|
const desiredCeilings = collectTableOnDemandCeilings(properties, currentRegion, diagnostics);
|
|
12555
|
-
const
|
|
12555
|
+
const flippingToProvisioned = oldBilling !== newBilling && newBilling === "PROVISIONED";
|
|
12556
|
+
if (flippingToProvisioned) derivePerCallProvisionedThroughput(properties, currentRegion, "seed", diagnostics);
|
|
12557
|
+
const desiredSdkIndexes = toSdkGlobalSecondaryIndexes(properties, currentRegion, newBilling, "min", flippingToProvisioned ? void 0 : diagnostics);
|
|
12558
|
+
if (flippingToProvisioned) toSdkGlobalSecondaryIndexes(properties, currentRegion, newBilling, "seed", diagnostics);
|
|
12556
12559
|
for (const replica of properties["Replicas"] ?? []) {
|
|
12557
12560
|
const replicaRegion = asRecord$1(replica)?.["Region"];
|
|
12558
12561
|
if (typeof replicaRegion !== "string" || replicaRegion === currentRegion) continue;
|
|
@@ -13232,9 +13235,11 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
13232
13235
|
const cause = regionErr instanceof Error ? regionErr : void 0;
|
|
13233
13236
|
throw new ProvisioningError(`Could not resolve client region for DynamoDB GlobalTable ${logicalId} delete — would risk dropping the local replica`, resourceType, logicalId, physicalId, cause);
|
|
13234
13237
|
}
|
|
13238
|
+
let preDeleteIndexes;
|
|
13235
13239
|
try {
|
|
13236
13240
|
const describe = await this.dynamoDBClient.send(new DescribeTableCommand({ TableName: physicalId }));
|
|
13237
13241
|
const replicas = describe.Table?.Replicas ?? [];
|
|
13242
|
+
preDeleteIndexes = describe.Table?.GlobalSecondaryIndexes;
|
|
13238
13243
|
const tableIndexNames = (describe.Table?.GlobalSecondaryIndexes ?? []).map((gsi) => gsi.IndexName).filter((name) => typeof name === "string");
|
|
13239
13244
|
for (const replica of replicas) {
|
|
13240
13245
|
const region = replica.RegionName;
|
|
@@ -13265,6 +13270,10 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
13265
13270
|
}
|
|
13266
13271
|
}
|
|
13267
13272
|
try {
|
|
13273
|
+
if (hasTransitionalIndex(preDeleteIndexes)) {
|
|
13274
|
+
this.logger.debug(`Waiting for indexes on ${physicalId} to settle before DeleteTable (issue #1521)`);
|
|
13275
|
+
await this.waitForIndexesActive(physicalId, logicalId);
|
|
13276
|
+
}
|
|
13268
13277
|
await this.dynamoDBClient.send(new DeleteTableCommand({ TableName: physicalId }));
|
|
13269
13278
|
await this.waitForTableGone(physicalId, logicalId);
|
|
13270
13279
|
this.logger.debug(`Successfully deleted DynamoDB GlobalTable ${logicalId}`);
|
|
@@ -13679,34 +13688,78 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
13679
13688
|
* `waitForTableActive`, this tolerates any non-terminal status — the
|
|
13680
13689
|
* table may already be ACTIVE on the no-op path (already-disabled
|
|
13681
13690
|
* protection) or transition through UPDATING.
|
|
13691
|
+
*
|
|
13692
|
+
* **A table is ACTIVE while one of its INDEXES is still transitioning**, and
|
|
13693
|
+
* the next `UpdateTable` in the serialized sequence is then rejected with
|
|
13694
|
+
* `Attempt to change a resource which is still in use: Index is being
|
|
13695
|
+
* updated` (issue #1521). That is not hypothetical: it broke the
|
|
13696
|
+
* `PAY_PER_REQUEST -> PROVISIONED` flip that also drops a GSI — AWS applies
|
|
13697
|
+
* the flip to every index, and cdkd issued the index DELETE while the index
|
|
13698
|
+
* was still absorbing it. Reproduced on pristine `main`, three runs out of
|
|
13699
|
+
* four on 2026-08-10, and the failed deploy's own `cdkd destroy` then
|
|
13700
|
+
* ORPHANED the table for the same reason.
|
|
13701
|
+
*
|
|
13702
|
+
* So the wait has TWO conditions read off the SAME response (an extra
|
|
13703
|
+
* `DescribeTable` per wait would double this path's API traffic for
|
|
13704
|
+
* something the response already carries) — but they keep DIFFERENT failure
|
|
13705
|
+
* semantics, and conflating them is a real regression rather than a
|
|
13706
|
+
* simplification. A table that never reaches ACTIVE is a hard error: nothing
|
|
13707
|
+
* can proceed. A still-transitioning INDEX is best-effort: `IndexStatus`
|
|
13708
|
+
* stays `CREATING` for the whole BACKFILL of a newly added GSI, which on a
|
|
13709
|
+
* populated table routinely outlives any cap — so throwing there would fail
|
|
13710
|
+
* a deploy whose resources are all correct, and would do it on an unrelated
|
|
13711
|
+
* tag-only edit that merely ran while an earlier index was still building.
|
|
13712
|
+
* Past the cap the index half warns and proceeds, leaving AWS's own
|
|
13713
|
+
* rejection as the backstop, which is the behavior it had before #1521 for
|
|
13714
|
+
* every case except the one the wait exists to fix.
|
|
13682
13715
|
*/
|
|
13683
13716
|
async waitForTableActiveAfterUpdate(tableName, logicalId, maxAttempts = 600) {
|
|
13717
|
+
let tableReachedActive = false;
|
|
13684
13718
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
13685
|
-
|
|
13719
|
+
const response = await this.dynamoDBClient.send(new DescribeTableCommand({ TableName: tableName }));
|
|
13720
|
+
if (response.Table?.TableStatus === "ACTIVE") {
|
|
13721
|
+
tableReachedActive = true;
|
|
13722
|
+
if (!hasTransitionalIndex(response.Table?.GlobalSecondaryIndexes)) return;
|
|
13723
|
+
}
|
|
13686
13724
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
13687
13725
|
}
|
|
13726
|
+
if (tableReachedActive) {
|
|
13727
|
+
this.logger.warn(`Indexes on ${tableName} (${logicalId}) were still transitioning after ${maxAttempts}s — a large index backfill can outlive this wait. Proceeding; AWS rejects the next call if it is still too early.`);
|
|
13728
|
+
return;
|
|
13729
|
+
}
|
|
13688
13730
|
throw new ProvisioningError(`Table ${tableName} did not reach ACTIVE within ${maxAttempts}s after UpdateTable`, "AWS::DynamoDB::GlobalTable", logicalId, tableName);
|
|
13689
13731
|
}
|
|
13690
13732
|
/**
|
|
13691
13733
|
* Wait until every GSI reports `IndexStatus: ACTIVE` (Issue #1419).
|
|
13692
13734
|
*
|
|
13693
|
-
* `
|
|
13694
|
-
*
|
|
13695
|
-
* is
|
|
13696
|
-
* resource is not ready, so registering right after the GSI-add loop
|
|
13735
|
+
* A GSI added by `UpdateTable` leaves the TABLE ACTIVE while the index
|
|
13736
|
+
* itself is still `CREATING` — application-autoscaling rejects a target
|
|
13737
|
+
* whose resource is not ready, so registering right after the GSI-add loop
|
|
13697
13738
|
* would skip the very index the deploy just introduced.
|
|
13698
13739
|
*
|
|
13740
|
+
* Since issue #1521 the same distinction is enforced INSIDE
|
|
13741
|
+
* {@link waitForTableActiveAfterUpdate} (which now reads both conditions off
|
|
13742
|
+
* its own response), so this helper is no longer the only place that knows
|
|
13743
|
+
* it. It remains the explicit wait for the two callers that have no
|
|
13744
|
+
* table-status wait to piggyback on: the autoscaling registration above and
|
|
13745
|
+
* the pre-`DeleteTable` gate, which AWS rejects while an index is
|
|
13746
|
+
* transitioning. An index that is `DELETING` still reports, so the shared
|
|
13747
|
+
* {@link hasTransitionalIndex} predicate covers `CREATING` / `UPDATING` /
|
|
13748
|
+
* `DELETING` alike.
|
|
13749
|
+
*
|
|
13699
13750
|
* **Best-effort by design**: on timeout it warns and returns rather than
|
|
13700
13751
|
* throwing. A missed registration self-heals on the next deploy (the
|
|
13701
13752
|
* reconcile re-asserts anything not already present), whereas throwing
|
|
13702
13753
|
* here would fail a deploy whose actual resources are all correct. Index
|
|
13703
13754
|
* backfill on a large table can take a long time, hence the 15-minute cap.
|
|
13755
|
+
* The caller that follows it with a mutating call keeps AWS's own error as
|
|
13756
|
+
* the backstop for the case where even that cap is not enough.
|
|
13704
13757
|
*/
|
|
13705
13758
|
async waitForIndexesActive(tableName, logicalId) {
|
|
13706
13759
|
const maxAttempts = 900;
|
|
13707
13760
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
13708
13761
|
try {
|
|
13709
|
-
if (((await this.dynamoDBClient.send(new DescribeTableCommand({ TableName: tableName }))).Table?.GlobalSecondaryIndexes ?? [])
|
|
13762
|
+
if (!hasTransitionalIndex((await this.dynamoDBClient.send(new DescribeTableCommand({ TableName: tableName }))).Table?.GlobalSecondaryIndexes ?? [])) return;
|
|
13710
13763
|
} catch (err) {
|
|
13711
13764
|
this.logger.debug(`DescribeTable while waiting for indexes on ${tableName}: ${err instanceof Error ? err.message : String(err)}`);
|
|
13712
13765
|
return;
|
|
@@ -13810,10 +13863,17 @@ function extractLocalDeletionProtection(props, region) {
|
|
|
13810
13863
|
* literal `ReadCapacityUnits`, which is taken before its auto-scaling
|
|
13811
13864
|
* members; 5 if absent.
|
|
13812
13865
|
*/
|
|
13813
|
-
function derivePerCallProvisionedThroughput(properties, region, source = "min") {
|
|
13866
|
+
function derivePerCallProvisionedThroughput(properties, region, source = "min", diagnostics) {
|
|
13867
|
+
const rawReplicas = properties["Replicas"];
|
|
13868
|
+
const rawRead = (Array.isArray(rawReplicas) ? rawReplicas : []).find((r) => asRecord$1(r)?.["Region"] === region)?.["ReadProvisionedThroughputSettings"];
|
|
13869
|
+
const rawWrite = properties["WriteProvisionedThroughputSettings"];
|
|
13870
|
+
const read = deriveReadCapacityUnits(asRecord$1(rawRead), source);
|
|
13871
|
+
const write = deriveWriteCapacityUnits(asRecord$1(rawWrite), source);
|
|
13872
|
+
if (read === void 0) reportUnresolvedProvisionedCapacity(rawRead, "Read", source, { appliedUnits: DEFAULT_CAPACITY_UNITS }, diagnostics, { blockName: "Replicas[local].ReadProvisionedThroughputSettings" });
|
|
13873
|
+
if (write === void 0) reportUnresolvedProvisionedCapacity(rawWrite, "Write", source, { appliedUnits: DEFAULT_CAPACITY_UNITS }, diagnostics, { blockName: "WriteProvisionedThroughputSettings" });
|
|
13814
13874
|
return {
|
|
13815
|
-
ReadCapacityUnits:
|
|
13816
|
-
WriteCapacityUnits:
|
|
13875
|
+
ReadCapacityUnits: read ?? DEFAULT_CAPACITY_UNITS,
|
|
13876
|
+
WriteCapacityUnits: write ?? DEFAULT_CAPACITY_UNITS
|
|
13817
13877
|
};
|
|
13818
13878
|
}
|
|
13819
13879
|
/**
|
|
@@ -13968,6 +14028,26 @@ function asRecord$1(value) {
|
|
|
13968
14028
|
* read-back comparison must therefore expect ABSENCE, not this value.
|
|
13969
14029
|
*/
|
|
13970
14030
|
const ON_DEMAND_LIMIT_RESET = -1;
|
|
14031
|
+
/**
|
|
14032
|
+
* The GSI states during which AWS refuses another `UpdateTable` or a
|
|
14033
|
+
* `DeleteTable` on the table (issue #1521) — a table is ACTIVE while one of
|
|
14034
|
+
* its indexes is still transitioning, which is what made the serialized
|
|
14035
|
+
* update sequence race and what left a table ORPHANED when the follow-up
|
|
14036
|
+
* destroy hit the same rule.
|
|
14037
|
+
*
|
|
14038
|
+
* `DELETING` is included because a dropped index keeps reporting until it is
|
|
14039
|
+
* actually gone. The test is on the TRANSITIONAL values rather than on
|
|
14040
|
+
* `!== 'ACTIVE'`: an absent or unrecognized status must not park the caller
|
|
14041
|
+
* for its whole cap on a table that is fine.
|
|
14042
|
+
*/
|
|
14043
|
+
const INDEX_TRANSITIONAL_STATUSES = /* @__PURE__ */ new Set([
|
|
14044
|
+
"CREATING",
|
|
14045
|
+
"UPDATING",
|
|
14046
|
+
"DELETING"
|
|
14047
|
+
]);
|
|
14048
|
+
function hasTransitionalIndex(indexes) {
|
|
14049
|
+
return (indexes ?? []).some((gsi) => INDEX_TRANSITIONAL_STATUSES.has(gsi.IndexStatus ?? ""));
|
|
14050
|
+
}
|
|
13971
14051
|
/** Coerce a CFn numeric (CFn is stringly-typed) to a finite number. */
|
|
13972
14052
|
function toFiniteNumber(value) {
|
|
13973
14053
|
if (value === void 0 || value === null || value === "") return void 0;
|
|
@@ -14058,6 +14138,94 @@ function reportUnresolvedRawMember(rawValue, diagnostics, context) {
|
|
|
14058
14138
|
});
|
|
14059
14139
|
}
|
|
14060
14140
|
/**
|
|
14141
|
+
* Which member of a `*ProvisionedThroughputSettings` block to blame when the
|
|
14142
|
+
* derivation came back `undefined` (issue #1511).
|
|
14143
|
+
*
|
|
14144
|
+
* The derivation reports only "no number", so the member is re-derived here in
|
|
14145
|
+
* the SAME order {@link deriveWriteCapacityUnits} / {@link deriveReadCapacityUnits}
|
|
14146
|
+
* / {@link pickAutoScalingCapacity} consult members — the literal first, then
|
|
14147
|
+
* the auto-scaling block's `source`-selected member. Reaching this function at
|
|
14148
|
+
* all means every one of them failed, so the first DECLARED one is the value
|
|
14149
|
+
* the user was trying to set.
|
|
14150
|
+
*
|
|
14151
|
+
* `relPath` is relative to the block, `''` meaning the block ITSELF is the
|
|
14152
|
+
* unusable value (a string / array / bare unresolved intrinsic, or an object
|
|
14153
|
+
* carrying no capacity member at all).
|
|
14154
|
+
*
|
|
14155
|
+
* Returns `undefined` for an ABSENT block: defaulting there is the documented
|
|
14156
|
+
* pre-existing behavior for a template that never asked for a capacity, and
|
|
14157
|
+
* warning about it would shout on every deploy of a table that is fine.
|
|
14158
|
+
*/
|
|
14159
|
+
function blameUnresolvedProvisionedMember(rawSettings, side, source) {
|
|
14160
|
+
if (rawSettings === void 0) return void 0;
|
|
14161
|
+
const settings = asRecord$1(rawSettings);
|
|
14162
|
+
if (!settings || isUnresolvedIntrinsicBlock(settings)) return {
|
|
14163
|
+
relPath: "",
|
|
14164
|
+
value: rawSettings
|
|
14165
|
+
};
|
|
14166
|
+
const literal = settings[`${side}CapacityUnits`];
|
|
14167
|
+
if (literal !== void 0) return {
|
|
14168
|
+
relPath: `${side}CapacityUnits`,
|
|
14169
|
+
value: literal
|
|
14170
|
+
};
|
|
14171
|
+
const autoKey = `${side}CapacityAutoScalingSettings`;
|
|
14172
|
+
const rawAutoScaling = settings[autoKey];
|
|
14173
|
+
if (rawAutoScaling === void 0) return {
|
|
14174
|
+
relPath: "",
|
|
14175
|
+
value: rawSettings
|
|
14176
|
+
};
|
|
14177
|
+
const autoScaling = asRecord$1(rawAutoScaling);
|
|
14178
|
+
if (!autoScaling || isUnresolvedIntrinsicBlock(autoScaling)) return {
|
|
14179
|
+
relPath: autoKey,
|
|
14180
|
+
value: rawAutoScaling
|
|
14181
|
+
};
|
|
14182
|
+
const order = source === "seed" ? ["SeedCapacity", "MinCapacity"] : ["MinCapacity", "SeedCapacity"];
|
|
14183
|
+
for (const member of order) {
|
|
14184
|
+
const value = autoScaling[member];
|
|
14185
|
+
if (value !== void 0) return {
|
|
14186
|
+
relPath: `${autoKey}.${member}`,
|
|
14187
|
+
value
|
|
14188
|
+
};
|
|
14189
|
+
}
|
|
14190
|
+
return {
|
|
14191
|
+
relPath: autoKey,
|
|
14192
|
+
value: rawAutoScaling
|
|
14193
|
+
};
|
|
14194
|
+
}
|
|
14195
|
+
/**
|
|
14196
|
+
* Report a DECLARED provisioned capacity the template could not resolve — the
|
|
14197
|
+
* PROVISIONED twin of {@link reportUnresolvedRawMember} (issue #1511).
|
|
14198
|
+
*
|
|
14199
|
+
* The two sides need different wording because they have different outcomes,
|
|
14200
|
+
* which is exactly why #1503 deferred this half. An unreadable ON-DEMAND
|
|
14201
|
+
* ceiling is SUPPRESSED (nothing is sent, the live ceiling stands), so its
|
|
14202
|
+
* diagnostic says "nothing was sent". A provisioned table cannot suppress —
|
|
14203
|
+
* AWS requires `ProvisionedThroughput` on the table and on every GSI of it —
|
|
14204
|
+
* so the derivation falls through to {@link DEFAULT_CAPACITY_UNITS} and a
|
|
14205
|
+
* table the template explicitly sized is deployed at 5/5. That is a throttling
|
|
14206
|
+
* symptom days later rather than an error, which is what makes naming it here
|
|
14207
|
+
* worth a warning at all. The one provisioned site that CAN suppress is a
|
|
14208
|
+
* replica's `ProvisionedThroughputOverride` (absent = inherit the source
|
|
14209
|
+
* table), hence the `suppressed` outcome arm.
|
|
14210
|
+
*
|
|
14211
|
+
* Caller decides WHEN: only when the derivation returned `undefined` AND no
|
|
14212
|
+
* explicit SDK-shaped member is standing in for it, so the warning always
|
|
14213
|
+
* describes what actually reached AWS.
|
|
14214
|
+
*/
|
|
14215
|
+
function reportUnresolvedProvisionedCapacity(rawSettings, side, source, outcome, diagnostics, context) {
|
|
14216
|
+
if (!diagnostics) return;
|
|
14217
|
+
const blame = blameUnresolvedProvisionedMember(rawSettings, side, source);
|
|
14218
|
+
if (!blame) return;
|
|
14219
|
+
const path = blame.relPath ? `${context.blockName}.${blame.relPath}` : context.blockName;
|
|
14220
|
+
const consequence = "appliedUnits" in outcome ? `so cdkd sent ${outcome.appliedUnits} capacity units instead (its default — AWS requires a concrete provisioned capacity here, so there was nothing to suppress)` : outcome.suppressed;
|
|
14221
|
+
diagnostics.push({
|
|
14222
|
+
kind: "unresolved-member",
|
|
14223
|
+
...context.indexName !== void 0 && { indexName: context.indexName },
|
|
14224
|
+
member: blame.relPath ? blame.relPath.slice(blame.relPath.lastIndexOf(".") + 1) : context.blockName.slice(context.blockName.lastIndexOf(".") + 1),
|
|
14225
|
+
message: `${path} is declared but did not resolve to a number (${JSON.stringify(blame.value)?.slice(0, 80)}), ${consequence}. This is usually an unresolved intrinsic; resolve it to a literal to apply the capacity you declared.`
|
|
14226
|
+
});
|
|
14227
|
+
}
|
|
14228
|
+
/**
|
|
14061
14229
|
* Derive a single WRITE capacity number from a CFn
|
|
14062
14230
|
* `WriteProvisionedThroughputSettings` block.
|
|
14063
14231
|
*
|
|
@@ -14188,14 +14356,32 @@ function toSdkGlobalSecondaryIndexes(properties, region, billingMode, source = "
|
|
|
14188
14356
|
member: "OnDemandThroughput",
|
|
14189
14357
|
message: "an explicit OnDemandThroughput block was dropped because the table's BillingMode is PROVISIONED; AWS rejects on-demand ceilings on a provisioned table. Remove the block, or set BillingMode: PAY_PER_REQUEST."
|
|
14190
14358
|
});
|
|
14191
|
-
if (billingMode === "PROVISIONED")
|
|
14192
|
-
|
|
14193
|
-
|
|
14194
|
-
|
|
14195
|
-
|
|
14196
|
-
|
|
14197
|
-
|
|
14198
|
-
|
|
14359
|
+
if (billingMode === "PROVISIONED") {
|
|
14360
|
+
const rawLocalRead = localEntry?.["ReadProvisionedThroughputSettings"];
|
|
14361
|
+
const rawGsiRead = gsi["ReadProvisionedThroughputSettings"];
|
|
14362
|
+
const rawWrite = gsi["WriteProvisionedThroughputSettings"];
|
|
14363
|
+
const derivedRead = deriveReadCapacityUnits(asRecord$1(rawLocalRead), source) ?? deriveReadCapacityUnits(asRecord$1(rawGsiRead), source);
|
|
14364
|
+
const derivedWrite = deriveWriteCapacityUnits(asRecord$1(rawWrite), source);
|
|
14365
|
+
const explicitCovers = (member) => explicitProvisioned !== void 0 && toFiniteNumber(explicitProvisioned[member]) !== void 0;
|
|
14366
|
+
if (derivedRead === void 0 && !explicitCovers("ReadCapacityUnits")) {
|
|
14367
|
+
const fromReplica = rawLocalRead !== void 0;
|
|
14368
|
+
reportUnresolvedProvisionedCapacity(fromReplica ? rawLocalRead : rawGsiRead, "Read", source, { appliedUnits: DEFAULT_CAPACITY_UNITS }, diagnostics, {
|
|
14369
|
+
...typeof indexName === "string" && { indexName },
|
|
14370
|
+
blockName: fromReplica ? "Replicas[local].GlobalSecondaryIndexes[].ReadProvisionedThroughputSettings" : "ReadProvisionedThroughputSettings"
|
|
14371
|
+
});
|
|
14372
|
+
}
|
|
14373
|
+
if (derivedWrite === void 0 && !explicitCovers("WriteCapacityUnits")) reportUnresolvedProvisionedCapacity(rawWrite, "Write", source, { appliedUnits: DEFAULT_CAPACITY_UNITS }, diagnostics, {
|
|
14374
|
+
...typeof indexName === "string" && { indexName },
|
|
14375
|
+
blockName: "WriteProvisionedThroughputSettings"
|
|
14376
|
+
});
|
|
14377
|
+
sdk.ProvisionedThroughput = mergeExplicitThroughputBlock(explicitProvisioned, {
|
|
14378
|
+
ReadCapacityUnits: derivedRead ?? DEFAULT_CAPACITY_UNITS,
|
|
14379
|
+
WriteCapacityUnits: derivedWrite ?? DEFAULT_CAPACITY_UNITS
|
|
14380
|
+
}, ["ReadCapacityUnits", "WriteCapacityUnits"], diagnostics, {
|
|
14381
|
+
...typeof indexName === "string" && { indexName },
|
|
14382
|
+
blockName: "ProvisionedThroughput"
|
|
14383
|
+
});
|
|
14384
|
+
} else {
|
|
14199
14385
|
const rawWrite = asRecord$1(gsi["WriteOnDemandThroughputSettings"])?.["MaxWriteRequestUnits"];
|
|
14200
14386
|
const rawReadLocal = asRecord$1(localEntry?.["ReadOnDemandThroughputSettings"])?.["MaxReadRequestUnits"];
|
|
14201
14387
|
const rawReadGsi = asRecord$1(gsi["ReadOnDemandThroughputSettings"])?.["MaxReadRequestUnits"];
|
|
@@ -14364,7 +14550,12 @@ function toSdkReplicaThroughputOverrides(cfn, billingMode, diagnostics, context)
|
|
|
14364
14550
|
message: "an explicit OnDemandThroughputOverride was dropped because the table's BillingMode is PROVISIONED; AWS rejects on-demand ceilings on a provisioned table."
|
|
14365
14551
|
});
|
|
14366
14552
|
if (billingMode === "PROVISIONED") {
|
|
14367
|
-
const
|
|
14553
|
+
const rawRead = cfn["ReadProvisionedThroughputSettings"];
|
|
14554
|
+
const readCapacity = deriveReadCapacityUnits(asRecord$1(rawRead));
|
|
14555
|
+
if (readCapacity === void 0 && toFiniteNumber(explicitProvisioned?.["ReadCapacityUnits"]) === void 0) reportUnresolvedProvisionedCapacity(rawRead, "Read", "min", { suppressed: "so no ProvisionedThroughputOverride was sent and the replica keeps the source table's read capacity" }, diagnostics, {
|
|
14556
|
+
...context,
|
|
14557
|
+
blockName: "ReadProvisionedThroughputSettings"
|
|
14558
|
+
});
|
|
14368
14559
|
const merged = mergeExplicitThroughputBlock(explicitProvisioned, readCapacity !== void 0 ? { ReadCapacityUnits: readCapacity } : void 0, ["ReadCapacityUnits"], diagnostics, {
|
|
14369
14560
|
...context,
|
|
14370
14561
|
blockName: "ProvisionedThroughputOverride"
|
|
@@ -66706,7 +66897,7 @@ function createMigrateCommand() {
|
|
|
66706
66897
|
*/
|
|
66707
66898
|
function buildProgram() {
|
|
66708
66899
|
const program = new Command();
|
|
66709
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.278.
|
|
66900
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.278.37");
|
|
66710
66901
|
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
66711
66902
|
const { profile } = actionCommand.optsWithGlobals();
|
|
66712
66903
|
if (profile !== void 0) process.env["AWS_PROFILE"] = profile;
|