@go-to-k/cdkd 0.278.25 → 0.278.27
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-BRlawK4H.js → asg-provider-C2V8DwC0.js} +2 -2
- package/dist/{asg-provider-BRlawK4H.js.map → asg-provider-C2V8DwC0.js.map} +1 -1
- package/dist/cli.js +136 -23
- package/dist/cli.js.map +1 -1
- package/dist/{deploy-engine-B65VTlrZ.js → deploy-engine-0SZS30V4.js} +31 -5
- package/dist/deploy-engine-0SZS30V4.js.map +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/deploy-engine-B65VTlrZ.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as isThrottlingError, $t as setAwsClients, A as red, At as getLegacyStateBucketName, B as isTerminationProtectionPropagationError, Bt as CFN_TEMPLATE_BODY_LIMIT, C as isStatefulRecreateTargetSync, Ct as runDockerForeground, D as cyan, Dt as Synthesizer, E as bold, Et as getDockerImageBySourceHash, F as ProviderRegistry, Ft as resolveStateBucketWithDefault, G as normalizeAwsTagsToCfn, Gt as expectedOwnerParam, H as cfnRefValueFromPhysicalId, Ht as MIGRATE_TMP_PREFIX, I as findActionableSilentDrops, It as resolveStateBucketWithDefaultAndSource, J as applyRoleArnIfSet, K as resolveExplicitPhysicalId, Kt as AssemblyReader, L as CloudControlProvider, Lt as resolveUseCdkBootstrapAssets, M as IAMRoleProvider, Mt as resolveAutoAssetStorage, N as collectInlinePolicyNamesManagedBySiblings, Nt as resolveCaptureObservedState, O as gray, Ot as synthesisStatusMessage, P as clearOnUpdateRemoval, Pt as resolveSkipPrefix, Q as isRetryableTransientError, Qt as resetAwsClients, R as slowCcOperationTimeoutMs, Rt as stateBucketExistenceConfirmed, S as MULTI_REGION_RECREATE_BLOCKED_TYPES, Sn as withErrorHandling, St as getDockerCmd, T as formatResourceLine, Tt as AssetManifestLoader, U as refStateLookupFromResource, Ut as findLargeInlineResources, V as IntrinsicFunctionResolver, Vt as CFN_TEMPLATE_URL_LIMIT, W as WAFv2WebACLProvider, Wt as uploadCfnTemplate, X as describeTypeWithThrottleRetry, Xt as AwsClients, Y as DiffCalculator, Yt as resolveBucketRegion, Z as withRetry, Zt as getAwsClients, _ as createPreDeleteFinalSnapshot, _t as parseBootstrapMarker, a as DeploymentEventsStore, an as LocalInvokeBuildError$1, at as shouldRetainResource, b as unsupportedFinalSnapshotError, bt as buildDockerImage, c as replayFailedOperations, ct as WorkGraph, d as IMPLICIT_DELETE_DEPENDENCIES, dn as PartialFailureError, dt as loadPublishableAssetManifest, et as DagBuilder, f as computeImplicitDeleteEdges, fn as ProvisioningError, ft as rewriteTemplateAssetReferences, g as ccRoutedFinalSnapshotError, gn as StackTerminationProtectionError, gt as getBootstrapMarkerKey, h as buildFinalSnapshotIdentifier, hn as StackHasActiveImportsError, ht as ensureAssetStorage, i as DeploymentEventsReader, in as DeployCancelledError, it as rebuildClientForBucketRegion, j as yellow, jt as resolveApp, k as green, kt as getDefaultStateBucketName, l as replayRollback, ln as MissingCdkCliError, lt as buildAssetRedirectMap, m as PRE_DELETE_SNAPSHOT_TYPES, mn as ResourceUpdateNotSupportedError, mt as BOOTSTRAP_MARKER_PREFIX, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as LockManager, o as planFailedOps, on as LocalMigrateError, ot as AssetPublisher, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as ResourceTimeoutError, pt as AssetModeResolver, q as assertRegionMatch, qt as processStackMessages, r as DeployEngine, rt as S3StateBackend, s as planRollback, sn as LocalStartServiceError, st as stringifyValue, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as CdkdError, tt as TemplateParser, u as withResourceDeadline, un as NestedStackChildDirectDestroyError, ut as createAssetRedirectResolver, v as isFinalSnapshotError, vt as validateAssetBucketName, w as renderStatefulReason, wt as runDockerStreaming, x as extractDeploymentEventError, xn as normalizeAwsError, xt as formatDockerLoginError, y as refusesFinalSnapshot, yt as validateContainerRepoName, z as disableInstanceApiTermination, zt as warnDeprecatedNoPrefixCliFlag } from "./deploy-engine-
|
|
2
|
+
import { $ as isThrottlingError, $t as setAwsClients, A as red, At as getLegacyStateBucketName, B as isTerminationProtectionPropagationError, Bt as CFN_TEMPLATE_BODY_LIMIT, C as isStatefulRecreateTargetSync, Ct as runDockerForeground, D as cyan, Dt as Synthesizer, E as bold, Et as getDockerImageBySourceHash, F as ProviderRegistry, Ft as resolveStateBucketWithDefault, G as normalizeAwsTagsToCfn, Gt as expectedOwnerParam, H as cfnRefValueFromPhysicalId, Ht as MIGRATE_TMP_PREFIX, I as findActionableSilentDrops, It as resolveStateBucketWithDefaultAndSource, J as applyRoleArnIfSet, K as resolveExplicitPhysicalId, Kt as AssemblyReader, L as CloudControlProvider, Lt as resolveUseCdkBootstrapAssets, M as IAMRoleProvider, Mt as resolveAutoAssetStorage, N as collectInlinePolicyNamesManagedBySiblings, Nt as resolveCaptureObservedState, O as gray, Ot as synthesisStatusMessage, P as clearOnUpdateRemoval, Pt as resolveSkipPrefix, Q as isRetryableTransientError, Qt as resetAwsClients, R as slowCcOperationTimeoutMs, Rt as stateBucketExistenceConfirmed, S as MULTI_REGION_RECREATE_BLOCKED_TYPES, Sn as withErrorHandling, St as getDockerCmd, T as formatResourceLine, Tt as AssetManifestLoader, U as refStateLookupFromResource, Ut as findLargeInlineResources, V as IntrinsicFunctionResolver, Vt as CFN_TEMPLATE_URL_LIMIT, W as WAFv2WebACLProvider, Wt as uploadCfnTemplate, X as describeTypeWithThrottleRetry, Xt as AwsClients, Y as DiffCalculator, Yt as resolveBucketRegion, Z as withRetry, Zt as getAwsClients, _ as createPreDeleteFinalSnapshot, _t as parseBootstrapMarker, a as DeploymentEventsStore, an as LocalInvokeBuildError$1, at as shouldRetainResource, b as unsupportedFinalSnapshotError, bt as buildDockerImage, c as replayFailedOperations, ct as WorkGraph, d as IMPLICIT_DELETE_DEPENDENCIES, dn as PartialFailureError, dt as loadPublishableAssetManifest, et as DagBuilder, f as computeImplicitDeleteEdges, fn as ProvisioningError, ft as rewriteTemplateAssetReferences, g as ccRoutedFinalSnapshotError, gn as StackTerminationProtectionError, gt as getBootstrapMarkerKey, h as buildFinalSnapshotIdentifier, hn as StackHasActiveImportsError, ht as ensureAssetStorage, i as DeploymentEventsReader, in as DeployCancelledError, it as rebuildClientForBucketRegion, j as yellow, jt as resolveApp, k as green, kt as getDefaultStateBucketName, l as replayRollback, ln as MissingCdkCliError, lt as buildAssetRedirectMap, m as PRE_DELETE_SNAPSHOT_TYPES, mn as ResourceUpdateNotSupportedError, mt as BOOTSTRAP_MARKER_PREFIX, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as LockManager, o as planFailedOps, on as LocalMigrateError, ot as AssetPublisher, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as ResourceTimeoutError, pt as AssetModeResolver, q as assertRegionMatch, qt as processStackMessages, r as DeployEngine, rt as S3StateBackend, s as planRollback, sn as LocalStartServiceError, st as stringifyValue, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as CdkdError, tt as TemplateParser, u as withResourceDeadline, un as NestedStackChildDirectDestroyError, ut as createAssetRedirectResolver, v as isFinalSnapshotError, vt as validateAssetBucketName, w as renderStatefulReason, wt as runDockerStreaming, x as extractDeploymentEventError, xn as normalizeAwsError, xt as formatDockerLoginError, y as refusesFinalSnapshot, yt as validateContainerRepoName, z as disableInstanceApiTermination, zt as warnDeprecatedNoPrefixCliFlag } from "./deploy-engine-0SZS30V4.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-C2V8DwC0.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";
|
|
@@ -33105,10 +33105,10 @@ var GlueProvider = class {
|
|
|
33105
33105
|
if (!this.client) this.client = new GlueClient(this.providerRegion ? { region: this.providerRegion } : {});
|
|
33106
33106
|
return this.client;
|
|
33107
33107
|
}
|
|
33108
|
-
async create(logicalId, resourceType, properties) {
|
|
33108
|
+
async create(logicalId, resourceType, properties, context) {
|
|
33109
33109
|
switch (resourceType) {
|
|
33110
33110
|
case "AWS::Glue::Database": return this.createDatabase(logicalId, resourceType, properties);
|
|
33111
|
-
case "AWS::Glue::Table": return this.createTable(logicalId, resourceType, properties);
|
|
33111
|
+
case "AWS::Glue::Table": return this.createTable(logicalId, resourceType, properties, context);
|
|
33112
33112
|
default: throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId);
|
|
33113
33113
|
}
|
|
33114
33114
|
}
|
|
@@ -33191,7 +33191,7 @@ var GlueProvider = class {
|
|
|
33191
33191
|
throw new ProvisioningError(`Failed to delete Glue Database ${logicalId}: ${error instanceof Error ? error.message : String(error)}`, resourceType, logicalId, physicalId, cause);
|
|
33192
33192
|
}
|
|
33193
33193
|
}
|
|
33194
|
-
async createTable(logicalId, resourceType, properties) {
|
|
33194
|
+
async createTable(logicalId, resourceType, properties, context) {
|
|
33195
33195
|
this.logger.debug(`Creating Glue Table ${logicalId}`);
|
|
33196
33196
|
const databaseName = properties["DatabaseName"];
|
|
33197
33197
|
if (!databaseName) throw new ProvisioningError(`DatabaseName is required for Glue Table ${logicalId}`, resourceType, logicalId);
|
|
@@ -33200,7 +33200,10 @@ var GlueProvider = class {
|
|
|
33200
33200
|
const tableName = tableInput["Name"] ?? properties["Name"];
|
|
33201
33201
|
if (!tableName) throw new ProvisioningError(`TableInput.Name or top-level Name is required for Glue Table ${logicalId}`, resourceType, logicalId);
|
|
33202
33202
|
const catalogId = properties["CatalogId"];
|
|
33203
|
-
|
|
33203
|
+
enforceIcebergTableInputAbsent(logicalId, resourceType, properties, {
|
|
33204
|
+
warn: (message) => this.logger.warn(message),
|
|
33205
|
+
replayingState: context?.replayingState === true
|
|
33206
|
+
});
|
|
33204
33207
|
const openTableFormatInput = properties["OpenTableFormatInput"];
|
|
33205
33208
|
try {
|
|
33206
33209
|
await this.getClient().send(new CreateTableCommand$1({
|
|
@@ -33990,15 +33993,35 @@ function findIcebergTableInputKey(properties) {
|
|
|
33990
33993
|
* produce a late, cryptic AWS error. Failing fast with the working shape spelled
|
|
33991
33994
|
* out is strictly more useful.
|
|
33992
33995
|
*
|
|
33993
|
-
* **
|
|
33994
|
-
*
|
|
33995
|
-
*
|
|
33996
|
-
*
|
|
33997
|
-
*
|
|
33998
|
-
*
|
|
33999
|
-
*
|
|
34000
|
-
*
|
|
34001
|
-
*
|
|
33996
|
+
* **TEMPLATE creates only — every STATE REPLAY warns instead.** The refusal is
|
|
33997
|
+
* conditioned on the ORIGIN of the properties, not on the operation name:
|
|
33998
|
+
*
|
|
33999
|
+
* - `update()` warns unconditionally. Rollback replays from cdkd STATE, and a
|
|
34000
|
+
* table created by a pre-#1390 build carries the key in its state record, so
|
|
34001
|
+
* refusing there would make such a table unrollbackable with no
|
|
34002
|
+
* template-side remedy. cdkd does not wire Glue's update-only
|
|
34003
|
+
* `UpdateOpenTableFormatInput` shape and `buildTableInput` is an explicit
|
|
34004
|
+
* allow-list, so warning forwards nothing and loses no protection.
|
|
34005
|
+
* - `create()` warns when {@link CreateContext.replayingState} is set — the
|
|
34006
|
+
* rollback executor's reverse-replacement arm, which revives the OLD
|
|
34007
|
+
* resource from `previousState.properties` (issue #1463). Same reasoning:
|
|
34008
|
+
* the user cannot edit a state record from the template. Unlike the update
|
|
34009
|
+
* path this one DOES forward the value, so the re-created table is degraded
|
|
34010
|
+
* in exactly the way the original was (the CFn spelling is dropped by the
|
|
34011
|
+
* SDK serializer per #1390; the SDK spelling is sent and Glue rejects it) —
|
|
34012
|
+
* the warning says so, and the fix-forward is a `cdkd deploy`.
|
|
34013
|
+
* - Every deploy-engine `create()` refuses: the CREATE branch, the
|
|
34014
|
+
* property-driven replacement, the `--recreate-via-*` destroy-then-create,
|
|
34015
|
+
* the `--replace` delete-first fallback, and the update-failure replacement.
|
|
34016
|
+
* All are driven by freshly resolved TEMPLATE properties, so the user CAN
|
|
34017
|
+
* fix the input and a fast, actionable refusal is strictly better.
|
|
34018
|
+
*
|
|
34019
|
+
* The asymmetry constrains where this provider may re-create. `GlueProvider`
|
|
34020
|
+
* must never call `this.create()` from inside its own `update()` the way ACM /
|
|
34021
|
+
* IAM / Lambda-permission / SNS-subscription do: those internal re-creates
|
|
34022
|
+
* forward `update()`'s `properties` — a STATE record during a rollback replay —
|
|
34023
|
+
* and `update()` has no context parameter to carry the flag, so this refusal
|
|
34024
|
+
* would fire on a replay with no way to detect it.
|
|
34002
34025
|
*
|
|
34003
34026
|
* **Known bypass: the sticky Cloud Control route.** This is a GlueProvider
|
|
34004
34027
|
* pre-flight, so it only runs on the SDK route. When a table's state record
|
|
@@ -34019,19 +34042,23 @@ function findIcebergTableInputKey(properties) {
|
|
|
34019
34042
|
* relaxed, the rename MUST be restored in the same change — otherwise the
|
|
34020
34043
|
* silent-drop bug of #1390 comes straight back.
|
|
34021
34044
|
*/
|
|
34022
|
-
function
|
|
34045
|
+
function enforceIcebergTableInputAbsent(logicalId, resourceType, properties, options) {
|
|
34023
34046
|
const key = findIcebergTableInputKey(properties);
|
|
34024
34047
|
if (key === void 0) return;
|
|
34025
|
-
|
|
34048
|
+
if (options.replayingState) {
|
|
34049
|
+
options.warn(icebergTableInputRefusalMessage(logicalId, key, "create-replay"));
|
|
34050
|
+
return;
|
|
34051
|
+
}
|
|
34052
|
+
throw new ProvisioningError(icebergTableInputRefusalMessage(logicalId, key, "create"), resourceType, logicalId);
|
|
34026
34053
|
}
|
|
34027
34054
|
/**
|
|
34028
|
-
* The shared #1454 message body, so the CREATE refusal
|
|
34029
|
-
* cannot drift apart. `mode` only changes
|
|
34030
|
-
*
|
|
34031
|
-
* next action is the same either way.
|
|
34055
|
+
* The shared #1454 message body, so the CREATE refusal, the UPDATE warning and
|
|
34056
|
+
* the rollback-replay CREATE warning cannot drift apart. `mode` only changes
|
|
34057
|
+
* the lead clause — everything after it (the probe evidence and the working
|
|
34058
|
+
* shape) is identical, because the user's next action is the same either way.
|
|
34032
34059
|
*/
|
|
34033
34060
|
function icebergTableInputRefusalMessage(logicalId, key, mode) {
|
|
34034
|
-
return `AWS::Glue::Table ${logicalId}: OpenTableFormatInput.IcebergInput.${key} ${mode === "create" ? `cannot be deployed by AWS in any shape, so cdkd refuses it before calling Glue (issue #1454).` : "cannot be deployed by AWS in any shape and is IGNORED on update — cdkd does not wire Glue's update-only UpdateOpenTableFormatInput shape, so it forwards nothing here and only warns (issue #1454). A CREATE of this table would be refused outright."}\n Live-probed 2026-08-09 in us-east-1 (issue #1408): glue:CreateTable — the API cdkd calls — rejects every Iceberg table spec ("Location information cannot be null while creating an iceberg table" without a TableInput.StorageDescriptor, "Table metadata information present at multiple parts of input request" with one), and CloudFormation rolls the same template back with "Table metadata is expected only via TableInput or via IcebergTableInputProperties inside OpenTableFormatInput" — a property name that exists in neither the CFn registry schema (IcebergInput.IcebergTableInput) nor @aws-sdk/client-glue (IcebergInput.CreateIcebergTableInput).\n Working shape — put the table metadata in TableInput and leave IcebergInput carrying only the create-time directive:\n TableInput: { Name, TableType: 'EXTERNAL_TABLE', StorageDescriptor: { Location: 's3://your-bucket/prefix/', Columns: [...] } }\n OpenTableFormatInput: { IcebergInput: { MetadataOperation: 'CREATE' } } // Version: '2' is also accepted\n Glue then writes the Iceberg metadata itself — the created table comes back with Parameters.table_type = ICEBERG and a populated Parameters.metadata_location.`;
|
|
34061
|
+
return `AWS::Glue::Table ${logicalId}: OpenTableFormatInput.IcebergInput.${key} ${mode === "create" ? `cannot be deployed by AWS in any shape, so cdkd refuses it before calling Glue (issue #1454).` : mode === "create-replay" ? "cannot be deployed by AWS in any shape, so cdkd normally refuses it before calling Glue (issue #1454) — but this create is REPLAYING a historical cdkd STATE record (a rollback reverse-replacement re-creating the OLD table), not your template, and refusing would leave that table unrestorable with no template-side remedy, only a hand-edit of state.json. cdkd therefore warns and proceeds (issue #1463). The re-created table is DEGRADED exactly as the original was: under the CFn spelling IcebergTableInput the AWS SDK serializer drops the unknown member (issue #1390), so the table comes back without its Iceberg metadata; under the SDK spelling CreateIcebergTableInput the value IS sent and Glue rejects the call, failing this one rollback operation. Either way, fix it forward with 'cdkd deploy' using the working shape below." : "cannot be deployed by AWS in any shape and is IGNORED on update — cdkd does not wire Glue's update-only UpdateOpenTableFormatInput shape, so it forwards nothing here and only warns (issue #1454). A CREATE of this table would be refused outright."}\n Live-probed 2026-08-09 in us-east-1 (issue #1408): glue:CreateTable — the API cdkd calls — rejects every Iceberg table spec ("Location information cannot be null while creating an iceberg table" without a TableInput.StorageDescriptor, "Table metadata information present at multiple parts of input request" with one), and CloudFormation rolls the same template back with "Table metadata is expected only via TableInput or via IcebergTableInputProperties inside OpenTableFormatInput" — a property name that exists in neither the CFn registry schema (IcebergInput.IcebergTableInput) nor @aws-sdk/client-glue (IcebergInput.CreateIcebergTableInput).\n Working shape — put the table metadata in TableInput and leave IcebergInput carrying only the create-time directive:\n TableInput: { Name, TableType: 'EXTERNAL_TABLE', StorageDescriptor: { Location: 's3://your-bucket/prefix/', Columns: [...] } }\n OpenTableFormatInput: { IcebergInput: { MetadataOperation: 'CREATE' } } // Version: '2' is also accepted\n Glue then writes the Iceberg metadata itself — the created table comes back with Parameters.table_type = ICEBERG and a populated Parameters.metadata_location.`;
|
|
34035
34062
|
}
|
|
34036
34063
|
/**
|
|
34037
34064
|
* Build the SDK `EncryptionConfiguration` from the CFn-shape input
|
|
@@ -48774,6 +48801,82 @@ async function runAccept(reports, stateBackend, stateConfig, awsClients, options
|
|
|
48774
48801
|
* parent path — so `path.split('.', 1)` is always safe to extract the
|
|
48775
48802
|
* top-level key.
|
|
48776
48803
|
*/
|
|
48804
|
+
/**
|
|
48805
|
+
* The AWS-authored property paths a `--revert` is about to DROP, for a
|
|
48806
|
+
* resource whose state predates observed-capture (issue #1478).
|
|
48807
|
+
*
|
|
48808
|
+
* The mechanism, and why this is not a Glue fix: `runRevert` picks the revert
|
|
48809
|
+
* baseline as `observedProperties ?? properties`. When `observedProperties` is
|
|
48810
|
+
* absent, the desired side is the raw TEMPLATE while the previous side is the
|
|
48811
|
+
* AWS-CURRENT snapshot — so {@link buildRevertNewProperties}, which overwrites
|
|
48812
|
+
* each drifted top-level key with the desired sub-shape wholesale, replaces
|
|
48813
|
+
* every AWS-authored key inside that subtree with the template's version. For
|
|
48814
|
+
* a Glue Iceberg table that silently wipes `table_type` /
|
|
48815
|
+
* `metadata_location`, the same outcome as issue #1461 reached by a different
|
|
48816
|
+
* trigger. The exposure is general: ANY resource where AWS writes into a bag
|
|
48817
|
+
* the template does not fully declare, on state written before
|
|
48818
|
+
* observed-capture.
|
|
48819
|
+
*
|
|
48820
|
+
* The user DID ask to push state over AWS, so this is not silent-wrong the way
|
|
48821
|
+
* #1461 was — but it is almost certainly not what they meant, and nothing told
|
|
48822
|
+
* them. So the chosen semantic is **warn and proceed**: it is the cheapest
|
|
48823
|
+
* honest step, preserves today's behavior, and does not foreclose the stricter
|
|
48824
|
+
* options (refuse outright, or treat "no observedProperties" as "previous is
|
|
48825
|
+
* unknown" so the merge preserves).
|
|
48826
|
+
*
|
|
48827
|
+
* Scoped deliberately:
|
|
48828
|
+
*
|
|
48829
|
+
* - **Only drifted top-level keys.** Non-drifted keys keep their AWS-current
|
|
48830
|
+
* value in `buildRevertNewProperties`, so nothing under them is dropped.
|
|
48831
|
+
* - **Only when `observedProperties` is absent.** With it present the desired
|
|
48832
|
+
* side is the deploy-time AWS snapshot, which already carries AWS-authored
|
|
48833
|
+
* fields — dropping one there is a legitimate revert of a real console
|
|
48834
|
+
* change, and warning about it would be noise on every run.
|
|
48835
|
+
* - **Only keys that vanish.** A key present on both sides with a different
|
|
48836
|
+
* VALUE is the drift the user asked to revert, not a silent loss.
|
|
48837
|
+
*
|
|
48838
|
+
* @returns dotted paths, sorted, e.g. `['Parameters.metadata_location']`.
|
|
48839
|
+
*/
|
|
48840
|
+
function findRevertDroppedAwsKeys(drifts, desiredProperties, awsProperties) {
|
|
48841
|
+
const dropped = /* @__PURE__ */ new Set();
|
|
48842
|
+
const driftedTopLevelKeys = /* @__PURE__ */ new Set();
|
|
48843
|
+
for (const d of drifts) {
|
|
48844
|
+
const topLevelKey = d.path.split(".", 1)[0];
|
|
48845
|
+
if (topLevelKey) driftedTopLevelKeys.add(topLevelKey);
|
|
48846
|
+
}
|
|
48847
|
+
for (const key of driftedTopLevelKeys) {
|
|
48848
|
+
if (!(key in desiredProperties)) continue;
|
|
48849
|
+
collectMissingPaths(awsProperties[key], desiredProperties[key], key, dropped);
|
|
48850
|
+
}
|
|
48851
|
+
return [...dropped].sort();
|
|
48852
|
+
}
|
|
48853
|
+
/**
|
|
48854
|
+
* Walk the AWS-side value against the desired-side value, recording every path
|
|
48855
|
+
* present on the AWS side and absent on the desired side.
|
|
48856
|
+
*
|
|
48857
|
+
* Only plain objects are descended into. An ARRAY is compared wholesale — the
|
|
48858
|
+
* drift comparator itself treats arrays as single values (its paths never
|
|
48859
|
+
* carry an index), so an element-wise walk here would report positions the
|
|
48860
|
+
* rest of the revert path cannot reason about.
|
|
48861
|
+
*/
|
|
48862
|
+
function collectMissingPaths(awsValue, desiredValue, path, out) {
|
|
48863
|
+
if (!isPlainRecord(awsValue)) return;
|
|
48864
|
+
if (!isPlainRecord(desiredValue)) {
|
|
48865
|
+
if (desiredValue === void 0) out.add(path);
|
|
48866
|
+
return;
|
|
48867
|
+
}
|
|
48868
|
+
for (const [key, value] of Object.entries(awsValue)) {
|
|
48869
|
+
const childPath = `${path}.${key}`;
|
|
48870
|
+
if (!(key in desiredValue)) {
|
|
48871
|
+
out.add(childPath);
|
|
48872
|
+
continue;
|
|
48873
|
+
}
|
|
48874
|
+
collectMissingPaths(value, desiredValue[key], childPath, out);
|
|
48875
|
+
}
|
|
48876
|
+
}
|
|
48877
|
+
function isPlainRecord(value) {
|
|
48878
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
48879
|
+
}
|
|
48777
48880
|
function buildRevertNewProperties(drifts, desiredProperties, awsProperties) {
|
|
48778
48881
|
const result = { ...awsProperties };
|
|
48779
48882
|
for (const d of drifts) {
|
|
@@ -48901,6 +49004,16 @@ function printRevertPlan(reports) {
|
|
|
48901
49004
|
const word = o.changes.length === 1 ? "property path" : "property paths";
|
|
48902
49005
|
process.stdout.write(` → provider.update on ${o.logicalId} (${o.resourceType}): revert ${o.changes.length} ${word}\n`);
|
|
48903
49006
|
for (const change of o.changes) process.stdout.write(` ${change.path}: ${formatScalar(change.awsValue)} -> ${formatScalar(change.stateValue)}\n`);
|
|
49007
|
+
const stateResource = report.state.resources[o.logicalId];
|
|
49008
|
+
if (stateResource && stateResource.observedProperties === void 0) {
|
|
49009
|
+
const dropped = findRevertDroppedAwsKeys(o.changes, stateResource.properties ?? {}, o.awsProperties);
|
|
49010
|
+
if (dropped.length > 0) {
|
|
49011
|
+
const word = dropped.length === 1 ? "value" : "values";
|
|
49012
|
+
process.stdout.write(` ! this resource has no observed-capture baseline, so the revert pushes the raw TEMPLATE and will DROP ${dropped.length} AWS-authored ${word}:\n`);
|
|
49013
|
+
for (const path of dropped) process.stdout.write(` ${path}\n`);
|
|
49014
|
+
process.stdout.write(" Re-deploy the stack first to populate observedProperties if you want these preserved.\n");
|
|
49015
|
+
}
|
|
49016
|
+
}
|
|
48904
49017
|
}
|
|
48905
49018
|
}
|
|
48906
49019
|
}
|
|
@@ -65850,7 +65963,7 @@ function createMigrateCommand() {
|
|
|
65850
65963
|
*/
|
|
65851
65964
|
function buildProgram() {
|
|
65852
65965
|
const program = new Command();
|
|
65853
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.278.
|
|
65966
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.278.27");
|
|
65854
65967
|
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
65855
65968
|
const { profile } = actionCommand.optsWithGlobals();
|
|
65856
65969
|
if (profile !== void 0) process.env["AWS_PROFILE"] = profile;
|