@go-to-k/cdkd 0.280.28 → 0.280.29
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-C3rBE_Ni.js → asg-provider-CcomwF89.js} +2 -2
- package/dist/{asg-provider-C3rBE_Ni.js.map → asg-provider-CcomwF89.js.map} +1 -1
- package/dist/cli.js +156 -47
- package/dist/cli.js.map +1 -1
- package/dist/{deploy-engine-Dkep5i7x.js → deploy-engine-wfKhhyCg.js} +3 -3
- package/dist/{deploy-engine-Dkep5i7x.js.map → deploy-engine-wfKhhyCg.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 requireConfigObject, $t as AssemblyReader, A as green, At as runDockerForeground, B as disableInstanceApiTermination, Bt as resolveCaptureObservedState, C as MULTI_REGION_RECREATE_BLOCKED_TYPES, Cn as StackTerminationProtectionError, Ct as getBootstrapMarkerKey, D as bold, Dt as buildDockerImage, E as formatResourceLine, Et as validateContainerRepoName, F as clearOnUpdateRemoval, Ft as synthesisStatusMessage, G as WAFv2WebACLProvider, Gt as stateBucketExistenceConfirmed, H as IntrinsicFunctionResolver, Ht as resolveStateBucketWithDefault, I as ProviderRegistry, It as getDefaultStateBucketName, J as assertRegionMatch, Jt as CFN_TEMPLATE_URL_LIMIT, K as normalizeAwsTagsToCfn, Kt as warnDeprecatedNoPrefixCliFlag, L as findActionableSilentDrops, Lt as getLegacyStateBucketName, M as yellow, Mt as AssetManifestLoader, N as IAMRoleProvider, Nt as getDockerImageBySourceHash, O as cyan, On as normalizeAwsError, Ot as formatDockerLoginError, P as collectInlinePolicyNamesManagedBySiblings, Pt as Synthesizer, Q as requireConfigArray, Qt as expectedOwnerParam, R as CloudControlProvider, Rt as resolveApp, S as extractDeploymentEventError, Sn as StackHasActiveImportsError, St as ensureAssetStorage, T as renderStatefulReason, Tt as validateAssetBucketName, U as cfnRefValueFromPhysicalId, Ut as resolveStateBucketWithDefaultAndSource, V as isTerminationProtectionPropagationError, Vt as resolveSkipPrefix, W as refStateLookupFromResource, Wt as resolveUseCdkBootstrapAssets, X as readConfigString, Xt as findLargeInlineResources, Y as configStringRefusal, Yt as MIGRATE_TMP_PREFIX, Z as replayWarn, Zt as uploadCfnTemplate, _ as createPreDeleteFinalSnapshot, _n as NestedStackChildDirectDestroyError, _t as createAssetRedirectResolver, a as DeploymentEventsStore, an as resetAwsClients, at as isRetryableTransientError, b as unsupportedFinalSnapshotError, bn as ResourceTimeoutError, bt as AssetModeResolver, c as replayFailedOperations, cn as CdkdError, ct as TemplateParser, d as IMPLICIT_DELETE_DEPENDENCIES, dn as DeployCancelledError, dt as rebuildClientForBucketRegion, en as processStackMessages, et as requireConfigString, f as computeImplicitDeleteEdges, fn as LocalInvokeBuildError$1, ft as shouldRetainResource, g as ccRoutedFinalSnapshotError, gn as MissingCdkCliError, gt as buildAssetRedirectMap, h as buildFinalSnapshotIdentifier, ht as WorkGraph, i as DeploymentEventsReader, in as getAwsClients, it as withRetry, j as red, jt as runDockerStreaming, k as gray, kn as withErrorHandling, kt as getDockerCmd, l as replayRollback, lt as LockManager, m as PRE_DELETE_SNAPSHOT_TYPES, mn as LocalStartServiceError, mt as stringifyValue, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as resolveBucketRegion, nt as DiffCalculator, o as planFailedOps, on as setAwsClients, ot as isThrottlingError, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as LocalMigrateError, pt as AssetPublisher, q as resolveExplicitPhysicalId, qt as CFN_TEMPLATE_BODY_LIMIT, r as DeployEngine, rn as AwsClients, rt as describeTypeWithThrottleRetry, s as planRollback, st as DagBuilder, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as applyRoleArnIfSet, u as withResourceDeadline, ut as S3StateBackend, v as isFinalSnapshotError, vn as PartialFailureError, vt as loadPublishableAssetManifest, w as isStatefulRecreateTargetSync, wt as parseBootstrapMarker, x as makeCanonicalizePropertiesFn, xn as ResourceUpdateNotSupportedError, xt as BOOTSTRAP_MARKER_PREFIX, y as refusesFinalSnapshot, yn as ProvisioningError, yt as rewriteTemplateAssetReferences, z as slowCcOperationTimeoutMs, zt as resolveAutoAssetStorage } from "./deploy-engine-
|
|
2
|
+
import { $ as requireConfigObject, $t as AssemblyReader, A as green, At as runDockerForeground, B as disableInstanceApiTermination, Bt as resolveCaptureObservedState, C as MULTI_REGION_RECREATE_BLOCKED_TYPES, Cn as StackTerminationProtectionError, Ct as getBootstrapMarkerKey, D as bold, Dt as buildDockerImage, E as formatResourceLine, Et as validateContainerRepoName, F as clearOnUpdateRemoval, Ft as synthesisStatusMessage, G as WAFv2WebACLProvider, Gt as stateBucketExistenceConfirmed, H as IntrinsicFunctionResolver, Ht as resolveStateBucketWithDefault, I as ProviderRegistry, It as getDefaultStateBucketName, J as assertRegionMatch, Jt as CFN_TEMPLATE_URL_LIMIT, K as normalizeAwsTagsToCfn, Kt as warnDeprecatedNoPrefixCliFlag, L as findActionableSilentDrops, Lt as getLegacyStateBucketName, M as yellow, Mt as AssetManifestLoader, N as IAMRoleProvider, Nt as getDockerImageBySourceHash, O as cyan, On as normalizeAwsError, Ot as formatDockerLoginError, P as collectInlinePolicyNamesManagedBySiblings, Pt as Synthesizer, Q as requireConfigArray, Qt as expectedOwnerParam, R as CloudControlProvider, Rt as resolveApp, S as extractDeploymentEventError, Sn as StackHasActiveImportsError, St as ensureAssetStorage, T as renderStatefulReason, Tt as validateAssetBucketName, U as cfnRefValueFromPhysicalId, Ut as resolveStateBucketWithDefaultAndSource, V as isTerminationProtectionPropagationError, Vt as resolveSkipPrefix, W as refStateLookupFromResource, Wt as resolveUseCdkBootstrapAssets, X as readConfigString, Xt as findLargeInlineResources, Y as configStringRefusal, Yt as MIGRATE_TMP_PREFIX, Z as replayWarn, Zt as uploadCfnTemplate, _ as createPreDeleteFinalSnapshot, _n as NestedStackChildDirectDestroyError, _t as createAssetRedirectResolver, a as DeploymentEventsStore, an as resetAwsClients, at as isRetryableTransientError, b as unsupportedFinalSnapshotError, bn as ResourceTimeoutError, bt as AssetModeResolver, c as replayFailedOperations, cn as CdkdError, ct as TemplateParser, d as IMPLICIT_DELETE_DEPENDENCIES, dn as DeployCancelledError, dt as rebuildClientForBucketRegion, en as processStackMessages, et as requireConfigString, f as computeImplicitDeleteEdges, fn as LocalInvokeBuildError$1, ft as shouldRetainResource, g as ccRoutedFinalSnapshotError, gn as MissingCdkCliError, gt as buildAssetRedirectMap, h as buildFinalSnapshotIdentifier, ht as WorkGraph, i as DeploymentEventsReader, in as getAwsClients, it as withRetry, j as red, jt as runDockerStreaming, k as gray, kn as withErrorHandling, kt as getDockerCmd, l as replayRollback, lt as LockManager, m as PRE_DELETE_SNAPSHOT_TYPES, mn as LocalStartServiceError, mt as stringifyValue, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as resolveBucketRegion, nt as DiffCalculator, o as planFailedOps, on as setAwsClients, ot as isThrottlingError, p as ATOMIC_FINAL_SNAPSHOT_TYPES, pn as LocalMigrateError, pt as AssetPublisher, q as resolveExplicitPhysicalId, qt as CFN_TEMPLATE_BODY_LIMIT, r as DeployEngine, rn as AwsClients, rt as describeTypeWithThrottleRetry, s as planRollback, st as DagBuilder, t as DEFAULT_RESOURCE_TIMEOUT_MS, tt as applyRoleArnIfSet, u as withResourceDeadline, ut as S3StateBackend, v as isFinalSnapshotError, vn as PartialFailureError, vt as loadPublishableAssetManifest, w as isStatefulRecreateTargetSync, wt as parseBootstrapMarker, x as makeCanonicalizePropertiesFn, xn as ResourceUpdateNotSupportedError, xt as BOOTSTRAP_MARKER_PREFIX, y as refusesFinalSnapshot, yn as ProvisioningError, yt as rewriteTemplateAssetReferences, z as slowCcOperationTimeoutMs, zt as resolveAutoAssetStorage } from "./deploy-engine-wfKhhyCg.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-CcomwF89.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";
|
|
@@ -53260,7 +53260,7 @@ function isServiceManagedTagKey(key) {
|
|
|
53260
53260
|
* provider binds it, and that tag is REQUIRED for managed scaling. Because any
|
|
53261
53261
|
* CDK ASG declares at least a `Name` tag, `Tags` is template-DECLARED, so the
|
|
53262
53262
|
* #1498 carve-out (undeclared + captured-empty) correctly does not apply — and
|
|
53263
|
-
* the tag list is an ARRAY, which {@link
|
|
53263
|
+
* the tag list is an ARRAY, which {@link findRevertUnbaselinedAwsKeys}'s walk
|
|
53264
53264
|
* compares wholesale and never descends into. Post-revert the ASG kept the
|
|
53265
53265
|
* capacity provider with its managed scaling silently broken (verified live
|
|
53266
53266
|
* 2026-08-10).
|
|
@@ -53332,43 +53332,48 @@ function findRevertPreservedTagKeys(drifts, desiredProperties, awsProperties) {
|
|
|
53332
53332
|
return [...preserved].sort();
|
|
53333
53333
|
}
|
|
53334
53334
|
/**
|
|
53335
|
-
* The AWS-authored property paths a `--revert`
|
|
53336
|
-
* resource whose state predates observed-capture (issue #1478
|
|
53335
|
+
* The AWS-authored property paths a `--revert` LEAVES UNTOUCHED, for a
|
|
53336
|
+
* resource whose state predates observed-capture (issue #1478, semantics
|
|
53337
|
+
* settled by issue #1626).
|
|
53337
53338
|
*
|
|
53338
|
-
* The mechanism
|
|
53339
|
-
*
|
|
53340
|
-
*
|
|
53341
|
-
*
|
|
53342
|
-
*
|
|
53343
|
-
*
|
|
53344
|
-
*
|
|
53345
|
-
*
|
|
53346
|
-
*
|
|
53347
|
-
* the template does not fully declare, on state written before
|
|
53339
|
+
* The mechanism: `runRevert` picks the revert baseline as
|
|
53340
|
+
* `observedProperties ?? properties`. When `observedProperties` is absent, the
|
|
53341
|
+
* desired side is the raw TEMPLATE while the previous side is the AWS-CURRENT
|
|
53342
|
+
* snapshot — so {@link buildRevertNewProperties}, which overwrites each drifted
|
|
53343
|
+
* top-level key with the desired sub-shape wholesale, has no value to carry for
|
|
53344
|
+
* any AWS-authored key inside that subtree. For a Glue Iceberg table that
|
|
53345
|
+
* reaches `table_type` / `metadata_location`, the same exposure as issue #1461
|
|
53346
|
+
* by a different trigger; the general case is ANY resource where AWS writes
|
|
53347
|
+
* into a bag the template does not fully declare, on state written before
|
|
53348
53348
|
* observed-capture.
|
|
53349
53349
|
*
|
|
53350
|
-
*
|
|
53351
|
-
*
|
|
53352
|
-
*
|
|
53353
|
-
*
|
|
53354
|
-
*
|
|
53355
|
-
*
|
|
53350
|
+
* #1478 shipped the **warn and proceed** semantic — the values were still
|
|
53351
|
+
* erased, the user was merely told first — while explicitly leaving the door
|
|
53352
|
+
* open to "treat 'no observedProperties' as 'previous is unknown' so the merge
|
|
53353
|
+
* preserves". Issue #1626 walked through that door for the reasons in
|
|
53354
|
+
* {@link mergeUntemplatedValue}: on this baseline cdkd cannot tell an
|
|
53355
|
+
* AWS-authored value from an out-of-band change, and resetting on a coin flip
|
|
53356
|
+
* is the worse error. So the paths below are now REPORTED AS PRESERVED, and
|
|
53357
|
+
* `mergeUntemplatedValue` is what makes that true by merging them into the bag
|
|
53358
|
+
* `--revert` actually SENDS — which is the only side a wholesale-replace
|
|
53359
|
+
* provider consults. This function is unchanged in what it computes — only in
|
|
53360
|
+
* what the caller does about it.
|
|
53356
53361
|
*
|
|
53357
53362
|
* Scoped deliberately:
|
|
53358
53363
|
*
|
|
53359
53364
|
* - **Only drifted top-level keys.** Non-drifted keys keep their AWS-current
|
|
53360
|
-
* value in `buildRevertNewProperties`, so nothing under them is
|
|
53365
|
+
* value in `buildRevertNewProperties`, so nothing under them is at stake.
|
|
53361
53366
|
* - **Only when `observedProperties` is absent.** With it present the desired
|
|
53362
53367
|
* side is the deploy-time AWS snapshot, which already carries AWS-authored
|
|
53363
|
-
* fields —
|
|
53364
|
-
* change, and
|
|
53368
|
+
* fields — removing one there is a legitimate revert of a real console
|
|
53369
|
+
* change, and reporting it would be noise on every run.
|
|
53365
53370
|
* - **Only keys that vanish.** A key present on both sides with a different
|
|
53366
|
-
* VALUE is the drift the user asked to revert,
|
|
53371
|
+
* VALUE is the drift the user asked to revert, and it reverts normally.
|
|
53367
53372
|
*
|
|
53368
53373
|
* @returns dotted paths, sorted, e.g. `['Parameters.metadata_location']`.
|
|
53369
53374
|
*/
|
|
53370
|
-
function
|
|
53371
|
-
const
|
|
53375
|
+
function findRevertUnbaselinedAwsKeys(drifts, desiredProperties, awsProperties) {
|
|
53376
|
+
const missing = /* @__PURE__ */ new Set();
|
|
53372
53377
|
const driftedTopLevelKeys = /* @__PURE__ */ new Set();
|
|
53373
53378
|
for (const d of drifts) {
|
|
53374
53379
|
const topLevelKey = d.path.split(".", 1)[0];
|
|
@@ -53376,9 +53381,9 @@ function findRevertDroppedAwsKeys(drifts, desiredProperties, awsProperties) {
|
|
|
53376
53381
|
}
|
|
53377
53382
|
for (const key of driftedTopLevelKeys) {
|
|
53378
53383
|
if (!(key in desiredProperties)) continue;
|
|
53379
|
-
collectMissingPaths(awsProperties[key], desiredProperties[key], key,
|
|
53384
|
+
collectMissingPaths(awsProperties[key], desiredProperties[key], key, missing, isTagListKey(key) ? isServiceManagedTagKey : void 0);
|
|
53380
53385
|
}
|
|
53381
|
-
return [...
|
|
53386
|
+
return [...missing].sort();
|
|
53382
53387
|
}
|
|
53383
53388
|
/**
|
|
53384
53389
|
* Walk the AWS-side value against the desired-side value, recording every path
|
|
@@ -53412,11 +53417,12 @@ function findRevertDroppedAwsKeys(drifts, desiredProperties, awsProperties) {
|
|
|
53412
53417
|
*/
|
|
53413
53418
|
function collectMissingPaths(awsValue, desiredValue, path, out, isPreservedKey) {
|
|
53414
53419
|
if (isKeyedList(awsValue)) {
|
|
53415
|
-
|
|
53420
|
+
const desiredIsEmptyArray = Array.isArray(desiredValue) && desiredValue.length === 0;
|
|
53421
|
+
if (!isKeyedList(desiredValue) && !desiredIsEmptyArray) {
|
|
53416
53422
|
if (desiredValue === void 0) out.add(path);
|
|
53417
53423
|
return;
|
|
53418
53424
|
}
|
|
53419
|
-
const desiredKeys = new Set(desiredValue.map((e) => e.Key));
|
|
53425
|
+
const desiredKeys = new Set(isKeyedList(desiredValue) ? desiredValue.map((e) => e.Key) : []);
|
|
53420
53426
|
for (const entry of awsValue) {
|
|
53421
53427
|
if (desiredKeys.has(entry.Key)) continue;
|
|
53422
53428
|
if (isPreservedKey?.(entry.Key)) continue;
|
|
@@ -53441,10 +53447,12 @@ function collectMissingPaths(awsValue, desiredValue, path, out, isPreservedKey)
|
|
|
53441
53447
|
/**
|
|
53442
53448
|
* A NON-EMPTY array whose every element is an object carrying a string `Key`.
|
|
53443
53449
|
*
|
|
53444
|
-
* Emptiness is
|
|
53445
|
-
*
|
|
53446
|
-
*
|
|
53447
|
-
*
|
|
53450
|
+
* Emptiness is excluded on the AWS side: `[]` carries no identities, so there
|
|
53451
|
+
* is nothing to report. It is NOT excluded on the DESIRED side any more
|
|
53452
|
+
* (issue #1626) — an empty baseline list means every AWS entry is unbaselined,
|
|
53453
|
+
* and since the only caller runs on the template-only baseline where
|
|
53454
|
+
* {@link mergeUntemplatedValue} PRESERVES all of them, reporting nothing would
|
|
53455
|
+
* leave the plan under-claiming what survives.
|
|
53448
53456
|
*/
|
|
53449
53457
|
function isKeyedList(value) {
|
|
53450
53458
|
return Array.isArray(value) && value.length > 0 && value.every((e) => typeof e === "object" && e !== null && typeof e.Key === "string");
|
|
@@ -53453,6 +53461,95 @@ function isPlainRecord(value) {
|
|
|
53453
53461
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
53454
53462
|
}
|
|
53455
53463
|
/**
|
|
53464
|
+
* Merge the AWS-current value with the revert baseline, KEEPING every path the
|
|
53465
|
+
* baseline does not declare (issue
|
|
53466
|
+
* [#1626](https://github.com/go-to-k/cdkd/issues/1626) items 2 + 3).
|
|
53467
|
+
*
|
|
53468
|
+
* ## The contract this settles
|
|
53469
|
+
*
|
|
53470
|
+
* `provider.update(logicalId, physicalId, type, newProperties,
|
|
53471
|
+
* previousProperties)` has ONE parameter list and TWO callers:
|
|
53472
|
+
*
|
|
53473
|
+
* - the deploy engine passes the state-recorded `properties` — the
|
|
53474
|
+
* LAST-DEPLOYED TEMPLATE — so a path present on the previous side and absent
|
|
53475
|
+
* from the desired side means exactly one thing: **the user removed it from
|
|
53476
|
+
* the template**;
|
|
53477
|
+
* - `runRevert` passes the FULL `readCurrentState` snapshot, so the same
|
|
53478
|
+
* absence ALSO covers **a path the template never declared at all**.
|
|
53479
|
+
*
|
|
53480
|
+
* Both provider shapes then destroy that path, by different routes. One that
|
|
53481
|
+
* KEY-DIFFS a collection reads the absence as a REMOVAL — ELBv2's
|
|
53482
|
+
* `LoadBalancerAttributes`, where `readCurrentState` deliberately emits every
|
|
53483
|
+
* attribute AWS reports, puts ~18 untemplated attributes on the removal path
|
|
53484
|
+
* against a template declaring one or two. One that REPLACES a bag wholesale
|
|
53485
|
+
* (`PutBucketTagging` is documented full-replace; the same holds for every
|
|
53486
|
+
* `Put*Configuration`) never consults the previous side at all and simply
|
|
53487
|
+
* sends a bag the untemplated path is missing from.
|
|
53488
|
+
*
|
|
53489
|
+
* That second shape is why the fix lands on the DESIRED side rather than by
|
|
53490
|
+
* trimming `previousProperties`: trimming stops the key-diffing removal but
|
|
53491
|
+
* leaves the wholesale-replace drop untouched, so half the reported paths
|
|
53492
|
+
* would still be erased while the plan claimed otherwise. Merging into the bag
|
|
53493
|
+
* cdkd actually SENDS covers both, and is what makes the plan's "left
|
|
53494
|
+
* untouched" line true rather than aspirational.
|
|
53495
|
+
*
|
|
53496
|
+
* ## Scoped to the baseline that cannot tell the two apart
|
|
53497
|
+
*
|
|
53498
|
+
* Applied ONLY when `observedProperties` is absent — the same gate as
|
|
53499
|
+
* {@link findRevertUnbaselinedAwsKeys}'s notice, and for the same reason. With
|
|
53500
|
+
* observed-capture present the baseline IS a deploy-time AWS snapshot, so a
|
|
53501
|
+
* path AWS reports and the baseline lacks was genuinely added out-of-band and
|
|
53502
|
+
* removing it is the revert the user asked for (the `drift-revert` integ
|
|
53503
|
+
* fixture requires exactly that for an injected tag). Without it the baseline
|
|
53504
|
+
* is the raw TEMPLATE, and "AWS has it, the template does not" is
|
|
53505
|
+
* indistinguishable from "AWS authored it" — so the honest answer is to leave
|
|
53506
|
+
* it alone. `findRevertUnbaselinedAwsKeys`'s docstring already named this as
|
|
53507
|
+
* one of the stricter options #1478 did not foreclose ("treat 'no
|
|
53508
|
+
* observedProperties' as 'previous is unknown' so the merge preserves"); this
|
|
53509
|
+
* is that option.
|
|
53510
|
+
*
|
|
53511
|
+
* The structural rules mirror {@link collectMissingPaths} case for case —
|
|
53512
|
+
* plain records descend, KEYED `[{Key, Value}]` lists merge by `Key`,
|
|
53513
|
+
* positional arrays and scalars are taken from the baseline wholesale — so
|
|
53514
|
+
* every path the plan names as preserved IS kept, and a unit test pins that
|
|
53515
|
+
* correspondence by diffing the flag-on and flag-off outputs.
|
|
53516
|
+
*
|
|
53517
|
+
* A service-authored tag is absent from both sides of that comparison and
|
|
53518
|
+
* stays consistent: `findRevertUnbaselinedAwsKeys` omits it
|
|
53519
|
+
* (`isServiceManagedTagKey`) because the #1501 carve-out already preserves it
|
|
53520
|
+
* on the DEFAULT path, so it is not something this flag rescues and reporting
|
|
53521
|
+
* it would warn about a loss that cannot happen. The test pins that it
|
|
53522
|
+
* survives under BOTH settings.
|
|
53523
|
+
*
|
|
53524
|
+
* A path the baseline DOES declare always wins, which is what keeps the revert
|
|
53525
|
+
* a revert: a drifted value is reset, and one AWS dropped is re-added.
|
|
53526
|
+
*/
|
|
53527
|
+
function mergeUntemplatedValue(awsValue, desiredValue) {
|
|
53528
|
+
const desiredIsEmptyArray = Array.isArray(desiredValue) && desiredValue.length === 0;
|
|
53529
|
+
if (isKeyedList(awsValue) && (isKeyedList(desiredValue) || desiredIsEmptyArray)) {
|
|
53530
|
+
const desiredEntries = isKeyedList(desiredValue) ? desiredValue : [];
|
|
53531
|
+
const desiredByKey = new Map(desiredEntries.map((e) => [e.Key, e]));
|
|
53532
|
+
const merged = [];
|
|
53533
|
+
const emitted = /* @__PURE__ */ new Set();
|
|
53534
|
+
for (const entry of awsValue) {
|
|
53535
|
+
if (emitted.has(entry.Key)) continue;
|
|
53536
|
+
emitted.add(entry.Key);
|
|
53537
|
+
merged.push(desiredByKey.get(entry.Key) ?? entry);
|
|
53538
|
+
}
|
|
53539
|
+
for (const entry of desiredEntries) {
|
|
53540
|
+
if (emitted.has(entry.Key)) continue;
|
|
53541
|
+
emitted.add(entry.Key);
|
|
53542
|
+
merged.push(entry);
|
|
53543
|
+
}
|
|
53544
|
+
return merged;
|
|
53545
|
+
}
|
|
53546
|
+
if (!isPlainRecord(awsValue) || !isPlainRecord(desiredValue)) return desiredValue;
|
|
53547
|
+
const merged = {};
|
|
53548
|
+
for (const [key, value] of Object.entries(awsValue)) merged[key] = key in desiredValue ? mergeUntemplatedValue(value, desiredValue[key]) : value;
|
|
53549
|
+
for (const [key, value] of Object.entries(desiredValue)) if (!(key in awsValue)) merged[key] = value;
|
|
53550
|
+
return merged;
|
|
53551
|
+
}
|
|
53552
|
+
/**
|
|
53456
53553
|
* Build the `newProperties` object passed to `provider.update` during
|
|
53457
53554
|
* `--revert`. Strategy:
|
|
53458
53555
|
*
|
|
@@ -53494,8 +53591,16 @@ function isPlainRecord(value) {
|
|
|
53494
53591
|
* (`Tags[0].Value`) — array drifts surface as a single entry on the
|
|
53495
53592
|
* parent path — so `path.split('.', 1)` is always safe to extract the
|
|
53496
53593
|
* top-level key.
|
|
53594
|
+
*
|
|
53595
|
+
* `preserveUntemplated` (issue #1626) switches the overlay from WHOLESALE to a
|
|
53596
|
+
* deep merge for the drifted subtrees, keeping every path the baseline does
|
|
53597
|
+
* not declare. `runRevert` sets it exactly when the resource has no
|
|
53598
|
+
* `observedProperties` — see {@link mergeUntemplatedValue} for why that is the
|
|
53599
|
+
* only baseline on which it is correct, and why the fix has to live on this
|
|
53600
|
+
* side rather than on `previousProperties`.
|
|
53497
53601
|
*/
|
|
53498
|
-
function buildRevertNewProperties(drifts, desiredProperties, awsProperties) {
|
|
53602
|
+
function buildRevertNewProperties(drifts, desiredProperties, awsProperties, options = {}) {
|
|
53603
|
+
const preserveUntemplated = options.preserveUntemplated === true;
|
|
53499
53604
|
const result = { ...awsProperties };
|
|
53500
53605
|
for (const d of drifts) {
|
|
53501
53606
|
const topLevelKey = d.path.split(".", 1)[0];
|
|
@@ -53503,8 +53608,11 @@ function buildRevertNewProperties(drifts, desiredProperties, awsProperties) {
|
|
|
53503
53608
|
if (topLevelKey in desiredProperties) {
|
|
53504
53609
|
const desiredValue = desiredProperties[topLevelKey];
|
|
53505
53610
|
const awsValue = awsProperties[topLevelKey];
|
|
53506
|
-
|
|
53507
|
-
|
|
53611
|
+
if (preserveUntemplated) result[topLevelKey] = mergeUntemplatedValue(awsValue, desiredValue);
|
|
53612
|
+
else {
|
|
53613
|
+
const baselineIsTagList = isCfnTagList(desiredValue) || Array.isArray(desiredValue) && desiredValue.length === 0;
|
|
53614
|
+
result[topLevelKey] = isTagListKey(topLevelKey) && baselineIsTagList && isCfnTagList(awsValue) ? mergeTagListForRevert(desiredValue, awsValue) : desiredValue;
|
|
53615
|
+
}
|
|
53508
53616
|
}
|
|
53509
53617
|
}
|
|
53510
53618
|
return result;
|
|
@@ -53567,7 +53675,7 @@ async function runRevert(reports, providerRegistry, stateConfig, awsClients, opt
|
|
|
53567
53675
|
provisionedBy: stateResource.provisionedBy
|
|
53568
53676
|
}).provider;
|
|
53569
53677
|
const desiredProperties = stateResource.observedProperties ?? stateResource.properties ?? {};
|
|
53570
|
-
const newProperties = buildRevertNewProperties(outcome.changes, desiredProperties, outcome.awsProperties);
|
|
53678
|
+
const newProperties = buildRevertNewProperties(outcome.changes, desiredProperties, outcome.awsProperties, { preserveUntemplated: stateResource.observedProperties === void 0 });
|
|
53571
53679
|
try {
|
|
53572
53680
|
await withRetry(() => provider.update(outcome.logicalId, stateResource.physicalId, outcome.resourceType, newProperties, outcome.awsProperties), outcome.logicalId, { logger: { debug: (msg) => logger.debug(msg) } });
|
|
53573
53681
|
totalSucceeded++;
|
|
@@ -53634,16 +53742,17 @@ function printRevertPlan(reports) {
|
|
|
53634
53742
|
const tagWord = preserved.length === 1 ? "tag" : "tags";
|
|
53635
53743
|
process.stdout.write(` ! reverting this tag list KEEPS ${preserved.length} AWS-authored ${tagWord} the baseline does not carry:\n`);
|
|
53636
53744
|
for (const path of preserved) process.stdout.write(` ${path}\n`);
|
|
53637
|
-
|
|
53745
|
+
const othersRevert = stateResource.observedProperties === void 0 ? "" : `Every other tag reverts normally. `;
|
|
53746
|
+
process.stdout.write(` ${othersRevert}A service may require these (ECS needs AmazonECSManaged for managed scaling); 'aws:'-prefixed keys are AWS-reserved and cannot be removed by hand.\n`);
|
|
53638
53747
|
}
|
|
53639
53748
|
}
|
|
53640
53749
|
if (stateResource && stateResource.observedProperties === void 0) {
|
|
53641
|
-
const
|
|
53642
|
-
if (
|
|
53643
|
-
const word =
|
|
53644
|
-
process.stdout.write(` ! this resource has no observed-capture baseline, so the revert pushes the raw TEMPLATE and
|
|
53645
|
-
for (const path of
|
|
53646
|
-
process.stdout.write(
|
|
53750
|
+
const unbaselined = findRevertUnbaselinedAwsKeys(o.changes, stateResource.properties ?? {}, o.awsProperties);
|
|
53751
|
+
if (unbaselined.length > 0) {
|
|
53752
|
+
const word = unbaselined.length === 1 ? "value" : "values";
|
|
53753
|
+
process.stdout.write(` ! this resource has no observed-capture baseline, so the revert pushes the raw TEMPLATE and LEAVES ${unbaselined.length} AWS-authored ${word} untouched:\n`);
|
|
53754
|
+
for (const path of unbaselined) process.stdout.write(` ${path}\n`);
|
|
53755
|
+
process.stdout.write(` The template does not declare these, so cdkd cannot tell an AWS-authored value from an out-of-band change and will not reset either (issue #1626). Run 'cdkd state refresh-observed ${report.stackName}' (or re-deploy) to populate observedProperties if you want them reverted too.\n`);
|
|
53647
53756
|
}
|
|
53648
53757
|
}
|
|
53649
53758
|
}
|
|
@@ -70595,7 +70704,7 @@ function createMigrateCommand() {
|
|
|
70595
70704
|
*/
|
|
70596
70705
|
function buildProgram() {
|
|
70597
70706
|
const program = new Command();
|
|
70598
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.280.
|
|
70707
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.280.29");
|
|
70599
70708
|
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
70600
70709
|
const { profile } = actionCommand.optsWithGlobals();
|
|
70601
70710
|
if (profile !== void 0) process.env["AWS_PROFILE"] = profile;
|