@go-to-k/cdkd 0.291.27 → 0.291.28
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-CWCv370K.js → asg-provider-DaYT8UPi.js} +2 -2
- package/dist/{asg-provider-CWCv370K.js.map → asg-provider-DaYT8UPi.js.map} +1 -1
- package/dist/cli.js +2 -2
- package/dist/{deploy-engine-DIZztJy5.js → deploy-engine-CidtgaFr.js} +920 -96
- package/dist/deploy-engine-CidtgaFr.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/{program-WCBWtvb0.js → program-DP27UiVh.js} +531 -128
- package/dist/{program-WCBWtvb0.js.map → program-DP27UiVh.js.map} +1 -1
- package/dist/{version-CuKFdkKV.js → version-CyFoAN6V.js} +2 -2
- package/dist/{version-CuKFdkKV.js.map → version-CyFoAN6V.js.map} +1 -1
- package/package.json +1 -1
- package/dist/deploy-engine-DIZztJy5.js.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { $ as yellow, $a as CdkdError, $i as synthesisStatusMessage, $n as refuseMalformedOrphanRecordsForDestroy, $r as forceQuitRecoveryClause, $t as configIntegerRefusal, A as createPreDeleteFinalSnapshot, Aa as credentialFingerprint, Ai as validateContainerRepoName, An as hasReadableOutputs, Ao as isTransientServerError, Ar as TEMPLATE_SOURCED_RULES, At as deleteSkipReason, B as isStatefulRecreateTargetSync, Ba as absoluteAssemblyPathEscape, Bi as getDockerCmd, Bn as malformedOrphansRefusalMessage, Br as maskSecretsInText, Bt as isImpossibleEmptyStoredAttribute, C as namesAnyDeclaredParameter, Ca as expectedOwnerParam, Ci as assertAssetBucketRegion, Cn as STATE_REGION_DIVERGED, Co as commandHole, Cr as describeTypeWithThrottleRetry, Ct as compositeIdSkipResult, D as PRE_DELETE_SNAPSHOT_TYPES, Da as ambientClientDefaults, Di as parseBootstrapMarker, Dn as deployRefusesOrphanRowsReason, Do as isMarkedNonRetryable, Dr as STATE_SOURCED_BASELINE_RULES, Dt as maskerOrIdentity, E as ATOMIC_FINAL_SNAPSHOT_TYPES, Ea as derivePartitionAndUrlSuffix, Ei as isCrossRegionRedirect, En as UNREADABLE_RESOURCES_MAP_ROW, Eo as withheldTargetClause, Er as TemplateParser, Et as maskDeep, F as extractDeploymentEventError, Fa as defineOwnKey, Fi as describeDockerExecFailure, Fn as malformedExportSourceWarning, Fo as safeStringify, Fr as identityKeyFor, Ft as carriesDynamicReference, G as toCfnInteger, Gi as runDockerForeground, Gn as malformedResourceEntriesWarning, Gr as redactSecretsForState, Gt as isSettledInstanceState, H as WARM_THROUGHPUT_MEMBERS, Ha as displayAssemblyPath, Hi as isMalformedEnvKey, Hn as malformedOutputsRefusalMessage, Hr as recordMaskOnlyValue, Ht as isUnboundTemplateParameter, I as makeSiblingClaimReader, Ia as hasOwnKey, Ii as describeDockerFailure, In as malformedLocalOutputsWarning, Ir as isSingleDynamicReferenceToken, It as carriesFetchableDynamicReference, J as bold, Ja as getAwsClients, Ji as escapeRegExp, Jn as malformedStateRefusalMessage, Jr as S3StateBackend, Jt as resolveExplicitPhysicalId, K as toFiniteNumber, Ka as resolveBucketRegion, Ki as runDockerStreaming, Kn as malformedResourcePropertiesWarning, Kr as scrubResourceRecord, Kt as WAFv2WebACLProvider, L as planOrphanAdoption, La as hasPlainPrototype, Li as dockerSpawnEnvWithSensitive, Ln as malformedOrphanRecordsRefusalMessage, Lr as isUncertifiedBaselineMaskPosition, Lt as cfnRefValueFromPhysicalId, M as refusesFinalSnapshot, Ma as failedStageNote, Mi as buildDockerImage, Mn as isReadableOrphanRecord, Mo as markRedactedCause, Mr as createSecretMasker, Mt as disableInstanceApiTermination, N as unsupportedFinalSnapshotError, Na as globMatches, Ni as resolveDockerContextDirectory, Nn as isReadableResourceEntry, No as retryClassificationText, Nr as dynamicReferenceTokens, Nt as isTerminationProtectionPropagationError, O as buildFinalSnapshotIdentifier, Oa as ambientCredentialConfig, Oi as readBootstrapMarkerBody, On as displayLogicalId, Oo as isRetryableTransientError, Or as STATE_SOURCED_CROSS_GENERATION_RULES, Ot as UNSPECIFIED_SKIP_REASON, P as makeCanonicalizePropertiesFn, Pa as processStackMessages, Pi as describeDockerCapturedOutput, Pn as malformedExportNamesWarning, Po as describeAwsFailure, Pr as errorCauseChain, Pt as IntrinsicFunctionResolver, Q as red, Qi as Synthesizer, Qn as refuseMalformedOrphanRecords, Qr as buildLockContentionMessage, Qt as configBooleanRefusal, R as MULTI_REGION_RECREATE_BLOCKED_TYPES, Ra as nullPrototypeRecord, Ri as finchSecretArgvRefusal, Rn as malformedOrphanRecordsWarning, Rr as markSameGenerationBag, Rt as coerceParameterTypedValue, S as computeParameterTaint, Sa as decodeListingKey, Si as BOOTSTRAP_MARKER_PREFIX, Sn as INTRINSIC_KEYS, So as withErrorHandling, Sr as findSilentDropProperties, St as compositeIdSeparatorRefusal, T as resourcesNamingDeclaredParameter, Ta as canonicalizeRegion, Ti as getBootstrapMarkerKey, Tn as UNREADABLE_ORPHANS_CONTAINER_ROW, To as shellQuote, Tr as DagBuilder, Tt as createMaskedRetryLogger, U as coerceWarmThroughput$1, Ua as renderAssemblyPathEscape, Ui as partitionSensitiveEnv, Un as malformedOutputsWarning, Ur as recordMaskOnlyValuesIn, Ut as parameterTypeMayLoseSecretIdentity, V as renderStatefulReason, Va as describeFileReadFailure, Vi as isDockerClientEnvKey, Vn as malformedOrphansWarning, Vr as pathCrossesDottedKey, Vt as isNamelessDynamicReferenceError, W as isWarmThroughputDecrease, Wa as resolveAssemblyPath, Wi as redactDockerArgvValues, Wn as malformedRenderedContainersWarning, Wr as recoverMaskedOutput, Wt as refStateLookupFromResource, X as gray, Xa as runWithStackAwsClients, Xi as AssetManifestLoader, Xn as refuseDivergentRecordRegionForDestroy, Xr as UNREPRODUCIBLE_LOCK_CLAUSE, Xt as coerceCfnBoolean, Y as cyan, Ya as resetAwsClients, Yi as stripControlChars, Yn as previewableOrphanRecords, Yr as rebuildClientForBucketRegion, Yt as assertRegionMatch, Z as green, Za as setAwsClients, Zi as getDockerImageBySourceHash, Zn as refuseMalformedNestedChildOutputs, Zr as buildForceUnlockCommand, Zt as coerceCfnInteger, _ as bagHoldsSecretExpression, _a as CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION, _i as buildAssetRedirectMap, _n as AWS_CREDENTIAL_ENV_KEYS, _r as safeRegion, _t as startInterruptWatch, a as DeploymentEventsStore, aa as resolveSkipPrefix, ai as hasReadableExportSet, an as requireConfigString, ao as IntrinsicResolutionRefusalError, ar as refuseMalformedResourceAttributesForOrphan, at as secretBearingStateKeyWarning, b as mergeNoChangeOutputs, ba as producerCoordinateKey, bi as rewriteTemplateAssetReferences, bn as envCredentialsAreAssumedRole, br as unreadableOrphanRecords, bt as ccProtectionRegistryTypes, c as replayFailedOperations, ca as resolveUseCdkBootstrapAssets, ci as importableOutputKeys, cn as classifyReplaySecretRegion, cr as refuseMalformedResourcePropertiesForOrphan, ct as IAMRoleProvider, d as updatePartialMessage, da as ssmResolvedValueType, di as orphansAfterRollback, dn as s3BucketArn, do as PartialFailureError, dr as repairMalformedOrphanRecordsForReadOnly, dt as ProviderRegistry, ea as getDefaultStateBucketName, ei as formatLockExpiry, en as configStringRefusal, er as refuseMalformedOrphans, et as collectDeclaredOutputNames, f as updatePartialReason, fa as CFN_TEMPLATE_BODY_LIMIT, fi as orphansCarriedFrom, fn as s3BucketDomainName, fo as ProvisioningError, fr as repairMalformedOrphansForReadOnly, ft as wouldReturnToSdkProvider, g as computeImplicitDeleteEdges, ga as uploadCfnTemplate, gi as WorkGraph, gn as applyRoleArnIfSet, go as StackTerminationProtectionError, gr as repairMalformedResourcesForReadOnly, gt as isInterruptedWaitError, h as IMPLICIT_DELETE_DEPENDENCIES, ha as findLargeInlineResources, hi as stringifyValue, hn as s3BucketWebsiteUrl, ho as StackHasActiveImportsError, hr as repairMalformedResourcePropertiesForReadOnly, ht as interruptWatchListenerCount, i as DeploymentEventsReader, ia as resolveCaptureObservedState, ii as exportNamesCarriedFrom, in as requireConfigObject, io as DynamicReferenceRegionAmbiguousError, ir as refuseMalformedOutputsForDestroy, it as secretBearing, j as isFinalSnapshotError, ja as AssemblyReader, ji as buildDenyExternalAccessPolicy, jn as hasReadableResources, jo as markNonRetryable, jr as carriesSecretMask, jt as isWaitAbandonedError, k as ccRoutedFinalSnapshotError, ka as clientDefaultsFor, ki as validateAssetBucketName, kn as hasReadableOrphans, ko as isThrottlingError, kr as STATE_SOURCED_READBACK_RULES, kt as deleteIndeterminateGuards, l as replayRollback, la as stateBucketExistenceConfirmed, li as importableOutputs, ln as producerRegionsFromState, lo as MalformedProducerRecordRefusalError, lr as refuseMalformedResourcesForDestroy, lt as collectInlinePolicyNamesManagedBySiblings, m as maskingRetryLogger, ma as MIGRATE_TMP_PREFIX, mi as AssetPublisher, mn as s3BucketRegionalDomainName, mo as ResourceUpdateNotSupportedError, mr as repairMalformedResourceEntriesForReadOnly, mt as endCommandInterruptScope, n as DEFAULT_RESOURCE_WARN_AFTER_MS, na as resolveApp, ni as DEFAULT_STATE_PREFIX, nn as replayWarn, nr as refuseMalformedOrphansForOrphan, nt as exportAliasCollisionScrubWarning, o as planFailedOps, oa as resolveStateBucketWithDefault, oi as hasReasonlessBaselineRefusal, on as definedAttributes, oo as LocalInvokeBuildError$1, or as refuseMalformedResourceEntries, ot as secretSafeKeyDisplay, p as withResourceDeadline, pa as CFN_TEMPLATE_URL_LIMIT, pi as shouldRetainResource, pn as s3BucketDualStackDomainName, po as ResourceTimeoutError, pr as repairMalformedOutputsForReadOnly, pt as beginCommandInterruptScope, q as formatResourceLine, qa as AwsClients, qi as warnFinchArgvExposure, qn as malformedResourcesWarning, qr as LockManager, qt as normalizeAwsTagsToCfn, r as DeployEngine, ra as resolveAutoAssetStorage, ri as describeRegionValueKind, rn as requireConfigArray, ro as DeployCancelledError, rr as refuseMalformedOutputs, rt as isExportAliasCollision, s as planRollback, sa as resolveStateBucketWithDefaultAndSource, si as hasUnverifiableParameterRefusal, sn as stringifyIfAssigned, so as LocalStartServiceError, sr as refuseMalformedResourceEntriesForOrphan, st as getCurrentResourceSecrets, t as DEFAULT_RESOURCE_TIMEOUT_MS, ta as getLegacyStateBucketName, ti as CUSTOM_RESOURCE_RESPONSE_PREFIX, tn as readConfigString, to as CrossAccountSecretRefusalError, tr as refuseMalformedOrphansForDestroy, tt as collectPublishedOutputNames, u as resolveReplacementOldType, ua as warnDeprecatedNoPrefixCliFlag, ui as isReadableBag, un as withSharedDrainBudget, uo as NestedStackChildDirectDestroyError, ur as refuseMalformedState, ut as clearOnUpdateRemoval, v as isSecretBearingReferenceString, va as injectiveKey, vi as createAssetRedirectResolver, vn as applyCallerIdentityCredentials, vo as SynthesisError, vr as safeStackName, vt as CloudControlProvider, w as reachableDivergentParameters, wa as PARTITION_TABLE, wi as ensureAssetStorage, wn as STATE_RESOURCES_MALFORMED, wo as pasteableCommand, wr as withRetry, wt as packCompositeId, x as bindingSkippedOutputs, xa as producerRecordKey, xi as AssetModeResolver, xn as DiffCalculator, xo as normalizeAwsError, xr as findActionableSilentDrops, xt as compositeIdFormatMessage, y as keptWholeReasonText, ya as injectiveKeyPrefix, yi as loadPublishableAssetManifest, yn as callerEnvCredentials, yr as unpreviewableOrphanRecords, yt as slowCcOperationTimeoutMs, z as isStatefulRecreateTargetForReplace, za as ownValue, zi as formatDockerLoginError, zn as malformedOrphanRowsKeptWarning, zr as maskSecretsInError, zt as getAccountInfo } from "./deploy-engine-DIZztJy5.js";
|
|
1
|
+
import { $ as yellow, $a as setAwsClients, $i as getDockerImageBySourceHash, $n as refuseMalformedOrphanRecordsForDestroy, $r as buildForceUnlockCommand, $t as configIntegerRefusal, A as createPreDeleteFinalSnapshot, Aa as ambientCredentialConfig, Ai as readBootstrapMarkerBody, An as hasReadableOutputs, Ao as withheldTargetClause, Ar as STATE_SOURCED_CROSS_GENERATION_RULES, At as deleteSkipReason, B as isStatefulRecreateTargetSync, Ba as nullPrototypeRecord, Bi as finchSecretArgvRefusal, Bn as malformedOrphansRefusalMessage, Br as markSameGenerationBag, Bt as isImpossibleEmptyStoredAttribute, C as namesAnyDeclaredParameter, Ca as producerRecordKey, Ci as AssetModeResolver, Cn as STATE_REGION_DIVERGED, Co as normalizeAwsError, Cr as prefetchCreateOnlyPropertyPaths, Ct as compositeIdSkipResult, D as PRE_DELETE_SNAPSHOT_TYPES, Da as canonicalizeRegion, Di as getBootstrapMarkerKey, Dn as deployRefusesOrphanRowsReason, Do as plainOrDescribed, Dr as DagBuilder, Dt as maskerOrIdentity, E as ATOMIC_FINAL_SNAPSHOT_TYPES, Ea as PARTITION_TABLE, Ei as ensureAssetStorage, En as UNREADABLE_RESOURCES_MAP_ROW, Eo as pasteableCommand, Er as withRetry, Et as maskDeep, F as extractDeploymentEventError, Fa as globMatches, Fi as resolveDockerContextDirectory, Fn as malformedExportSourceWarning, Fo as markNonRetryable, Fr as dynamicReferenceTokens, Ft as carriesDynamicReference, G as toCfnInteger, Ga as renderAssemblyPathEscape, Gi as partitionSensitiveEnv, Gn as malformedResourceEntriesWarning, Gr as recordMaskOnlyValuesIn, Gt as isSettledInstanceState, H as WARM_THROUGHPUT_MEMBERS, Ha as absoluteAssemblyPathEscape, Hi as getDockerCmd, Hn as malformedOutputsRefusalMessage, Hr as maskSecretsInText, Ht as isUnboundTemplateParameter, I as makeSiblingClaimReader, Ia as processStackMessages, Ii as describeDockerCapturedOutput, In as malformedLocalOutputsWarning, Io as markRedactedCause, Ir as errorCauseChain, It as carriesFetchableDynamicReference, J as bold, Ja as resolveBucketRegion, Ji as runDockerStreaming, Jn as malformedStateRefusalMessage, Jr as scrubResourceRecord, Jt as resolveExplicitPhysicalId, K as toFiniteNumber, Ka as resolveAssemblyPath, Ki as redactDockerArgvValues, Kn as malformedResourcePropertiesWarning, Kr as recoverMaskedOutput, Kt as WAFv2WebACLProvider, L as planOrphanAdoption, La as defineOwnKey, Li as describeDockerExecFailure, Ln as malformedOrphanRecordsRefusalMessage, Lo as retryClassificationText, Lr as identityKeyFor, Lt as cfnRefValueFromPhysicalId, M as refusesFinalSnapshot, Ma as credentialFingerprint, Mi as validateContainerRepoName, Mn as isReadableOrphanRecord, Mo as isRetryableTransientError, Mr as TEMPLATE_SOURCED_RULES, Mt as disableInstanceApiTermination, N as unsupportedFinalSnapshotError, Na as AssemblyReader, Ni as buildDenyExternalAccessPolicy, Nn as isReadableResourceEntry, No as isThrottlingError, Nr as carriesSecretMask, Nt as isTerminationProtectionPropagationError, O as buildFinalSnapshotIdentifier, Oa as derivePartitionAndUrlSuffix, Oi as isCrossRegionRedirect, On as displayLogicalId, Oo as quotedOrDescribed, Or as TemplateParser, Ot as UNSPECIFIED_SKIP_REASON, P as makeCanonicalizePropertiesFn, Pa as failedStageNote, Pi as buildDockerImage, Pn as malformedExportNamesWarning, Po as isTransientServerError, Pr as createSecretMasker, Pt as IntrinsicFunctionResolver, Q as red, Qa as runWithStackAwsClients, Qi as AssetManifestLoader, Qn as refuseMalformedOrphanRecords, Qr as UNREPRODUCIBLE_LOCK_CLAUSE, Qt as configBooleanRefusal, R as MULTI_REGION_RECREATE_BLOCKED_TYPES, Ra as hasOwnKey, Ri as describeDockerFailure, Rn as malformedOrphanRecordsWarning, Ro as describeAwsFailure, Rr as isSingleDynamicReferenceToken, Rt as coerceParameterTypedValue, S as computeParameterTaint, Sa as producerCoordinateKey, Si as rewriteTemplateAssetReferences, Sn as INTRINSIC_KEYS, Sr as findSilentDropProperties, St as compositeIdSeparatorRefusal, T as resourcesNamingDeclaredParameter, Ta as expectedOwnerParam, Ti as assertAssetBucketRegion, Tn as UNREADABLE_ORPHANS_CONTAINER_ROW, To as commandHole, Tr as describeTypeWithThrottleRetry, Tt as createMaskedRetryLogger, U as coerceWarmThroughput$1, Ua as describeFileReadFailure, Ui as isDockerClientEnvKey, Un as malformedOutputsWarning, Ur as pathCrossesDottedKey, Ut as parameterTypeMayLoseSecretIdentity, V as renderStatefulReason, Va as ownValue, Vi as formatDockerLoginError, Vn as malformedOrphansWarning, Vr as maskSecretsInError, Vt as isNamelessDynamicReferenceError, W as isWarmThroughputDecrease, Wa as displayAssemblyPath, Wi as isMalformedEnvKey, Wn as malformedRenderedContainersWarning, Wr as recordMaskOnlyValue, Wt as refStateLookupFromResource, X as gray, Xa as getAwsClients, Xi as escapeRegExp, Xn as refuseDivergentRecordRegionForDestroy, Xr as S3StateBackend, Xt as coerceCfnBoolean, Y as cyan, Ya as AwsClients, Yi as warnFinchArgvExposure, Yn as previewableOrphanRecords, Yr as LockManager, Yt as assertRegionMatch, Z as green, Za as resetAwsClients, Zi as stripControlChars, Zn as refuseMalformedNestedChildOutputs, Zr as rebuildClientForBucketRegion, Zt as coerceCfnInteger, _ as bagHoldsSecretExpression, _a as findLargeInlineResources, _i as stringifyValue, _n as AWS_CREDENTIAL_ENV_KEYS, _o as StackHasActiveImportsError, _r as safeRegion, _t as startInterruptWatch, a as DeploymentEventsStore, aa as resolveAutoAssetStorage, ai as describeRegionValueKind, an as requireConfigString, ao as DeployCancelledError, ar as refuseMalformedResourceAttributesForOrphan, at as secretBearingStateKeyWarning, b as mergeNoChangeOutputs, ba as injectiveKey, bi as createAssetRedirectResolver, bn as envCredentialsAreAssumedRole, bo as SynthesisError, br as unreadableOrphanRecords, bt as ccProtectionRegistryTypes, c as replayFailedOperations, ca as resolveStateBucketWithDefault, ci as hasReasonlessBaselineRefusal, cn as classifyReplaySecretRegion, co as LocalInvokeBuildError$1, cr as refuseMalformedResourcePropertiesForOrphan, ct as IAMRoleProvider, d as updatePartialMessage, da as stateBucketExistenceConfirmed, di as importableOutputs, dn as s3BucketArn, do as MalformedProducerRecordRefusalError, dr as repairMalformedOrphanRecordsForReadOnly, dt as ProviderRegistry, ea as Synthesizer, ei as buildLockContentionMessage, en as configStringRefusal, er as refuseMalformedOrphans, et as collectDeclaredOutputNames, f as updatePartialReason, fa as warnDeprecatedNoPrefixCliFlag, fi as isReadableBag, fn as s3BucketDomainName, fo as NestedStackChildDirectDestroyError, fr as repairMalformedOrphansForReadOnly, ft as wouldReturnToSdkProvider, g as computeImplicitDeleteEdges, ga as MIGRATE_TMP_PREFIX, gi as AssetPublisher, gn as applyRoleArnIfSet, go as ResourceUpdateNotSupportedError, gr as repairMalformedResourcesForReadOnly, gt as isInterruptedWaitError, h as IMPLICIT_DELETE_DEPENDENCIES, ha as CFN_TEMPLATE_URL_LIMIT, hi as shouldRetainResource, hn as s3BucketWebsiteUrl, ho as ResourceTimeoutError, hr as repairMalformedResourcePropertiesForReadOnly, ht as interruptWatchListenerCount, i as DeploymentEventsReader, ia as resolveApp, ii as DEFAULT_STATE_PREFIX, in as requireConfigObject, ir as refuseMalformedOutputsForDestroy, it as secretBearing, j as isFinalSnapshotError, ja as clientDefaultsFor, ji as validateAssetBucketName, jn as hasReadableResources, jo as isMarkedNonRetryable, jr as STATE_SOURCED_READBACK_RULES, jt as isWaitAbandonedError, k as ccRoutedFinalSnapshotError, ka as ambientClientDefaults, ki as parseBootstrapMarker, kn as hasReadableOrphans, ko as shellQuote, kr as STATE_SOURCED_BASELINE_RULES, kt as deleteIndeterminateGuards, l as replayRollback, la as resolveStateBucketWithDefaultAndSource, li as hasUnverifiableParameterRefusal, ln as producerRegionsFromState, lo as LocalStartServiceError, lr as refuseMalformedResourcesForDestroy, lt as collectInlinePolicyNamesManagedBySiblings, m as maskingRetryLogger, ma as CFN_TEMPLATE_BODY_LIMIT, mi as orphansCarriedFrom, mn as s3BucketRegionalDomainName, mo as ProvisioningError, mr as repairMalformedResourceEntriesForReadOnly, mt as endCommandInterruptScope, n as DEFAULT_RESOURCE_WARN_AFTER_MS, na as getDefaultStateBucketName, ni as formatLockExpiry, nn as replayWarn, nr as refuseMalformedOrphansForOrphan, nt as exportAliasCollisionScrubWarning, o as planFailedOps, oa as resolveCaptureObservedState, oi as exportNamesCarriedFrom, on as definedAttributes, oo as DynamicReferenceRegionAmbiguousError, or as refuseMalformedResourceEntries, ot as secretSafeKeyDisplay, p as withResourceDeadline, pa as ssmResolvedValueType, pi as orphansAfterRollback, pn as s3BucketDualStackDomainName, po as PartialFailureError, pr as repairMalformedOutputsForReadOnly, pt as beginCommandInterruptScope, q as formatResourceLine, qi as runDockerForeground, qn as malformedResourcesWarning, qr as redactSecretsForState, qt as normalizeAwsTagsToCfn, r as DeployEngine, ra as getLegacyStateBucketName, ri as CUSTOM_RESOURCE_RESPONSE_PREFIX, rn as requireConfigArray, ro as CrossAccountSecretRefusalError, rr as refuseMalformedOutputs, rt as isExportAliasCollision, s as planRollback, sa as resolveSkipPrefix, si as hasReadableExportSet, sn as stringifyIfAssigned, so as IntrinsicResolutionRefusalError, sr as refuseMalformedResourceEntriesForOrphan, st as getCurrentResourceSecrets, t as DEFAULT_RESOURCE_TIMEOUT_MS, ta as synthesisStatusMessage, ti as forceQuitRecoveryClause, tn as readConfigString, to as CdkdError, tr as refuseMalformedOrphansForDestroy, tt as collectPublishedOutputNames, u as resolveReplacementOldType, ua as resolveUseCdkBootstrapAssets, ui as importableOutputKeys, un as withSharedDrainBudget, ur as refuseMalformedState, ut as clearOnUpdateRemoval, v as isSecretBearingReferenceString, va as uploadCfnTemplate, vi as WorkGraph, vn as applyCallerIdentityCredentials, vo as StackTerminationProtectionError, vr as safeStackName, vt as CloudControlProvider, w as reachableDivergentParameters, wa as decodeListingKey, wi as BOOTSTRAP_MARKER_PREFIX, wn as STATE_RESOURCES_MALFORMED, wo as withErrorHandling, wr as templateResourceTypes, wt as packCompositeId, x as bindingSkippedOutputs, xa as injectiveKeyPrefix, xi as loadPublishableAssetManifest, xn as DiffCalculator, xr as findActionableSilentDrops, xt as compositeIdFormatMessage, y as keptWholeReasonText, ya as CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION, yi as buildAssetRedirectMap, yn as callerEnvCredentials, yr as unpreviewableOrphanRecords, yt as slowCcOperationTimeoutMs, z as isStatefulRecreateTargetForReplace, za as hasPlainPrototype, zi as dockerSpawnEnvWithSensitive, zn as malformedOrphanRowsKeptWarning, zo as safeStringify, zr as isUncertifiedBaselineMaskPosition, zt as getAccountInfo } from "./deploy-engine-CidtgaFr.js";
|
|
2
2
|
import { C as displayAwsMessage, D as isPasteableIdent, E as displayStackName, O as truncateCodePoints, S as UNRENDERABLE, T as displaySafe, _ as withSkipPrefix, b as SECRET_REF_MAX_CODE_POINTS, c as PATTERN_B_NAME_OPTIONS, f as explicitNamePropertyFor, h as getCurrentStackName, i as reserveStdoutForPayload, l as PATTERN_B_NAME_PROPERTIES, m as generateResourceNameWithFallback, n as getLogger, o as runStackBuffered, p as generateResourceName, s as getLiveRenderer, u as PATTERN_B_RESOURCE_TYPES, v as withStackName, w as displayIdent, x as STACK_REF_MAX_CODE_POINTS } from "./logger-Bt0RGDfb.js";
|
|
3
3
|
import { n as awsClientDefaults, s as ambientRegion, u as formatAuthority } from "./aws-client-defaults-qSDe1fA_.js";
|
|
4
|
-
import { t as getCdkdVersion } from "./version-
|
|
5
|
-
import { a as renderDisableCommand, i as protectedReplacementAdvice, r as UNNAMEABLE_ID_CLAUSE, t as ASGProvider } from "./asg-provider-
|
|
4
|
+
import { t as getCdkdVersion } from "./version-CyFoAN6V.js";
|
|
5
|
+
import { a as renderDisableCommand, i as protectedReplacementAdvice, r as UNNAMEABLE_ID_CLAUSE, t as ASGProvider } from "./asg-provider-DaYT8UPi.js";
|
|
6
6
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
7
7
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
8
8
|
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, NotFound, 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";
|
|
@@ -9810,6 +9810,34 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
9810
9810
|
return Array.isArray(list) && list.length === 0;
|
|
9811
9811
|
}
|
|
9812
9812
|
/**
|
|
9813
|
+
* The refusal a TEMPLATE-path `update()` raises for a malformed
|
|
9814
|
+
* `VersioningConfiguration.Status` or `LoggingConfiguration` member, or
|
|
9815
|
+
* `undefined` (issue [#3728](https://github.com/go-to-k/cdkd/issues/3728)).
|
|
9816
|
+
*
|
|
9817
|
+
* It asks exactly what the two warn-and-skip arms in
|
|
9818
|
+
* {@link applySubConfigDiffs} ask, with the same predicate, key, fallback and
|
|
9819
|
+
* path, and only where those arms would ACT:
|
|
9820
|
+
*
|
|
9821
|
+
* - versioning: the block CHANGED (nullish on both sides, the arm's own
|
|
9822
|
+
* `versioningChanged`), and `configStringRefusal` refuses `Status`;
|
|
9823
|
+
* - logging: the block CHANGED, and `DestinationBucketName` or
|
|
9824
|
+
* `LogFilePrefix` refuses, in the applier's order. An ABSENT block (the
|
|
9825
|
+
* legitimate removal, `diffSubConfig`'s clear arm) needs no gate of its
|
|
9826
|
+
* own: `configStringRefusal` answers `undefined` for a nullish container.
|
|
9827
|
+
*
|
|
9828
|
+
* An unchanged malformed value is not a pending operation, so it is not
|
|
9829
|
+
* refused either — the same gate the arms' own warnings take.
|
|
9830
|
+
*/
|
|
9831
|
+
static versioningOrLoggingRefusal(properties, previousProperties) {
|
|
9832
|
+
const changed = (key) => JSON.stringify(previousProperties[key] ?? null) !== JSON.stringify(properties[key] ?? null);
|
|
9833
|
+
if (changed("VersioningConfiguration")) {
|
|
9834
|
+
const refusal = configStringRefusal(properties["VersioningConfiguration"], "Status", "Suspended", "AWS::S3::Bucket VersioningConfiguration");
|
|
9835
|
+
if (refusal !== void 0) return refusal;
|
|
9836
|
+
}
|
|
9837
|
+
const logging = properties["LoggingConfiguration"];
|
|
9838
|
+
if (changed("LoggingConfiguration")) return configStringRefusal(logging, "DestinationBucketName", "", "AWS::S3::Bucket LoggingConfiguration") ?? configStringRefusal(logging, "LogFilePrefix", "", "AWS::S3::Bucket LoggingConfiguration");
|
|
9839
|
+
}
|
|
9840
|
+
/**
|
|
9813
9841
|
* Turn a set of per-property overrides into the `effectiveProperties` bag the
|
|
9814
9842
|
* deploy engine records in place of the desired one (issues #1612 / #1670).
|
|
9815
9843
|
*
|
|
@@ -10696,6 +10724,10 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
10696
10724
|
wasReplaced: true
|
|
10697
10725
|
};
|
|
10698
10726
|
}
|
|
10727
|
+
if (context?.replayingState !== true && context?.desiredFromAwsReadback !== true) {
|
|
10728
|
+
const refusal = S3BucketProvider.versioningOrLoggingRefusal(properties, previousProperties);
|
|
10729
|
+
if (refusal !== void 0) throw new ProvisioningError(`${refusal}. Nothing was applied to bucket ${displaySafe(physicalId)}; fix the template value`, resourceType, logicalId, physicalId);
|
|
10730
|
+
}
|
|
10699
10731
|
await this.assertStateBucketRegion("update", logicalId, resourceType, physicalId, await this.getRegion());
|
|
10700
10732
|
try {
|
|
10701
10733
|
const effectiveOverrides = await this.applyConfiguration(physicalId, properties, {
|
|
@@ -18687,6 +18719,53 @@ function liveCeilingAlreadyMatches(live, requested) {
|
|
|
18687
18719
|
return compared > 0;
|
|
18688
18720
|
}
|
|
18689
18721
|
/**
|
|
18722
|
+
* Is this per-index capacity AWS's on-demand `{0, 0}` placeholder — BOTH
|
|
18723
|
+
* members resolving to 0 through {@link toFiniteNumber}, so a string-spelled
|
|
18724
|
+
* `{'0', '0'}` counts and a half-zero `{0, 7}` does not?
|
|
18725
|
+
*
|
|
18726
|
+
* The ONE predicate behind both answers to that value on the UPDATE path: the
|
|
18727
|
+
* template-path pre-flight refusal ({@link zeroCapacityIndexRefusal}) and the
|
|
18728
|
+
* warn-skip the two non-template callers still take
|
|
18729
|
+
* (`DynamoDBTableProvider.skipZeroCapacityIndexUpdate`). Sharing it is what
|
|
18730
|
+
* keeps the refusal from being narrower or wider than the skip it replaces on
|
|
18731
|
+
* the template path.
|
|
18732
|
+
*/
|
|
18733
|
+
function isZeroCapacityPlaceholder(requested) {
|
|
18734
|
+
if (requested === void 0 || requested === null || typeof requested !== "object") return false;
|
|
18735
|
+
return toFiniteNumber(requested.ReadCapacityUnits) === 0 && toFiniteNumber(requested.WriteCapacityUnits) === 0;
|
|
18736
|
+
}
|
|
18737
|
+
/**
|
|
18738
|
+
* The template-path pre-flight refusal for a per-index `ProvisionedThroughput`
|
|
18739
|
+
* of `{0, 0}` (issue [#3728](https://github.com/go-to-k/cdkd/issues/3728)), or
|
|
18740
|
+
* `undefined` when no index would reach `applyGsiUpdates`' capacity arms
|
|
18741
|
+
* carrying one.
|
|
18742
|
+
*
|
|
18743
|
+
* SCOPE, matched to what those arms act on rather than to every entry that
|
|
18744
|
+
* holds the value. An index is named only when its capacity is a PENDING
|
|
18745
|
+
* operation: it is absent from the recorded previous side (a new index, or the
|
|
18746
|
+
* adopted-index arm), or its `ProvisionedThroughput` differs from the recorded
|
|
18747
|
+
* one (the same-name arm's own change test, `JSON.stringify` against
|
|
18748
|
+
* `JSON.stringify`). A steady-state template that has always carried the
|
|
18749
|
+
* placeholder emits no capacity op, so refusing it would fail a deploy that
|
|
18750
|
+
* sends nothing — the same gate the `StreamSpecification` refusal takes.
|
|
18751
|
+
*
|
|
18752
|
+
* Wider than the skip in ONE direction, deliberately: a brand-new index, whose
|
|
18753
|
+
* `Create` action never consulted the skip and sent `{0, 0}` for AWS to reject
|
|
18754
|
+
* AFTER the tag diff and any billing flip had landed. Refusing it here trades
|
|
18755
|
+
* that half-applied failure for one that applied nothing.
|
|
18756
|
+
*/
|
|
18757
|
+
function zeroCapacityIndexRefusal(properties, previousProperties, logicalId, maskSecrets) {
|
|
18758
|
+
const asEntries = (value) => (Array.isArray(value) ? value : []).filter((entry) => entry !== null && typeof entry === "object" && !Array.isArray(entry));
|
|
18759
|
+
const previousByName = /* @__PURE__ */ new Map();
|
|
18760
|
+
for (const entry of asEntries(previousProperties["GlobalSecondaryIndexes"])) if (entry["IndexName"]) previousByName.set(entry["IndexName"], entry);
|
|
18761
|
+
const offending = asEntries(properties["GlobalSecondaryIndexes"]).filter((entry) => Boolean(entry["IndexName"])).filter((entry) => isZeroCapacityPlaceholder(entry["ProvisionedThroughput"])).filter((entry) => {
|
|
18762
|
+
const previous = previousByName.get(entry["IndexName"]);
|
|
18763
|
+
return previous === void 0 || JSON.stringify(previous["ProvisionedThroughput"]) !== JSON.stringify(entry["ProvisionedThroughput"]);
|
|
18764
|
+
}).map((entry) => typeof entry["IndexName"] === "string" ? maskSecrets(entry["IndexName"]) : "<unnamed>");
|
|
18765
|
+
if (offending.length === 0) return void 0;
|
|
18766
|
+
return `AWS::DynamoDB::Table ${logicalId}: GlobalSecondaryIndexes ${offending.join(", ")} declare ProvisionedThroughput {ReadCapacityUnits: 0, WriteCapacityUnits: 0}, which is AWS's on-demand placeholder rather than a capacity DynamoDB accepts (the minimum is 1). Declare a capacity of at least 1, or remove the per-index ProvisionedThroughput on a PAY_PER_REQUEST table. Nothing was applied to the table`;
|
|
18767
|
+
}
|
|
18768
|
+
/**
|
|
18690
18769
|
* The sentinel DynamoDB accepts to CLEAR an on-demand request-unit maximum
|
|
18691
18770
|
* (issue [#3373](https://github.com/go-to-k/cdkd/issues/3373)).
|
|
18692
18771
|
*
|
|
@@ -19590,6 +19669,10 @@ var DynamoDBTableProvider = class {
|
|
|
19590
19669
|
const [streamRefusal] = streamMemberRefusals(properties["StreamSpecification"]);
|
|
19591
19670
|
if (streamRefusal !== void 0) throw new ProvisioningError(`${streamRefusal}. Nothing was applied to DynamoDB table ${logicalId}; fix the template value`, resourceType, logicalId, physicalId);
|
|
19592
19671
|
}
|
|
19672
|
+
if (context?.replayingState !== true && context?.desiredFromAwsReadback !== true) {
|
|
19673
|
+
const zeroCapacityRefusal = zeroCapacityIndexRefusal(properties, previousProperties, logicalId, maskSecrets);
|
|
19674
|
+
if (zeroCapacityRefusal !== void 0) throw new ProvisioningError(zeroCapacityRefusal, resourceType, logicalId, physicalId);
|
|
19675
|
+
}
|
|
19593
19676
|
const table = (await this.dynamoDBClient.send(new DescribeTableCommand({ TableName: physicalId }))).Table;
|
|
19594
19677
|
let latestStreamArn = table?.LatestStreamArn;
|
|
19595
19678
|
if (table?.TableArn) await this.applyTagDiff(table.TableArn, previousProperties["Tags"], properties["Tags"]);
|
|
@@ -21143,43 +21226,35 @@ var DynamoDBTableProvider = class {
|
|
|
21143
21226
|
* capacity — including a half-declared or malformed one — still goes out and
|
|
21144
21227
|
* is answered by AWS, the fail-OPEN direction this file uses everywhere.
|
|
21145
21228
|
*
|
|
21146
|
-
*
|
|
21147
|
-
*
|
|
21148
|
-
*
|
|
21149
|
-
*
|
|
21150
|
-
*
|
|
21151
|
-
*
|
|
21152
|
-
* -
|
|
21153
|
-
*
|
|
21154
|
-
* `
|
|
21155
|
-
*
|
|
21156
|
-
*
|
|
21157
|
-
*
|
|
21158
|
-
*
|
|
21159
|
-
*
|
|
21160
|
-
*
|
|
21161
|
-
*
|
|
21162
|
-
*
|
|
21163
|
-
*
|
|
21164
|
-
*
|
|
21165
|
-
*
|
|
21166
|
-
*
|
|
21167
|
-
*
|
|
21168
|
-
*
|
|
21169
|
-
*
|
|
21170
|
-
*
|
|
21171
|
-
*
|
|
21172
|
-
* - The lie is bounded and self-surfacing. AWS never accepted `{0, 0}` at
|
|
21173
|
-
* create either, so no live table can be holding it; and where the value
|
|
21174
|
-
* would actually matter — a PROVISIONED table, whose indexes hold a real
|
|
21175
|
-
* capacity — recording `{0, 0}` diverges from the readback and `cdkd drift`
|
|
21176
|
-
* REPORTS it. On a PAY_PER_REQUEST table the recorded `{0, 0}` matches what
|
|
21177
|
-
* `DescribeTable` reports for every index anyway, so there is no divergence
|
|
21178
|
-
* to hide.
|
|
21229
|
+
* NOT caller-blind any more (issue #3728). A TEMPLATE-borne `{0, 0}` never
|
|
21230
|
+
* reaches this skip: `update()` REFUSES it at pre-flight, before any call —
|
|
21231
|
+
* see {@link zeroCapacityIndexRefusal} — exactly as `create()` fails loudly
|
|
21232
|
+
* on the same value. What still arrives here is the two NON-template desired
|
|
21233
|
+
* bags, and for them the warn-skip stands:
|
|
21234
|
+
*
|
|
21235
|
+
* - `cdkd drift --revert` (`UpdateContext.desiredFromAwsReadback`), the
|
|
21236
|
+
* caller this skip was written for: its desired bag is a pre-#1767
|
|
21237
|
+
* `observedProperties` blob, which the user cannot edit from the template.
|
|
21238
|
+
* - The rollback executor's two revert arms (`UpdateContext.replayingState`,
|
|
21239
|
+
* since issue #3141): their desired bag is `previousState.properties`, a
|
|
21240
|
+
* cdkd STATE record, so a refusal would make the table un-rollbackable with
|
|
21241
|
+
* no template-side remedy (issues #1545 / #1552).
|
|
21242
|
+
*
|
|
21243
|
+
* The lie the skip tells on those paths is bounded and self-surfacing. AWS
|
|
21244
|
+
* never accepted `{0, 0}` at create either, so no live table can be holding
|
|
21245
|
+
* it; and where the value would actually matter — a PROVISIONED table, whose
|
|
21246
|
+
* indexes hold a real capacity — recording `{0, 0}` diverges from the readback
|
|
21247
|
+
* and `cdkd drift` REPORTS it. On a PAY_PER_REQUEST table the recorded
|
|
21248
|
+
* `{0, 0}` matches what `DescribeTable` reports for every index anyway, so
|
|
21249
|
+
* there is no divergence to hide.
|
|
21250
|
+
*
|
|
21251
|
+
* Until issue #3728 this skip was caller-blind: when it was written no
|
|
21252
|
+
* discriminator separated a template deploy from the rollback revert arms
|
|
21253
|
+
* (they set neither flag), and the template path warn-skipped too. That
|
|
21254
|
+
* reason expired with #3141, and the template path now takes the refusal.
|
|
21179
21255
|
*/
|
|
21180
21256
|
skipZeroCapacityIndexUpdate(indexName, physicalId, requested, maskSecrets) {
|
|
21181
|
-
if (requested
|
|
21182
|
-
if (toFiniteNumber(requested.ReadCapacityUnits) !== 0 || toFiniteNumber(requested.WriteCapacityUnits) !== 0) return false;
|
|
21257
|
+
if (!isZeroCapacityPlaceholder(requested)) return false;
|
|
21183
21258
|
const warn = (message) => this.logger.warn(maskSecrets(message));
|
|
21184
21259
|
warn(`${this.indexScopeAt(indexName, physicalId, maskSecrets)}: the requested ProvisionedThroughput is {ReadCapacityUnits: 0, WriteCapacityUnits: 0}, which is AWS's on-demand placeholder rather than a capacity DynamoDB accepts (the minimum is 1), so no per-index throughput update was sent. This usually means the value came from a pre-#1767 cdkd state record — a \`cdkd drift --revert\` of such a record, or a rollback replaying it. Re-run \`cdkd deploy\` (or \`cdkd drift --accept\`) to refresh the record.`);
|
|
21185
21260
|
return true;
|
|
@@ -28896,6 +28971,14 @@ function narrowRouteDestinations(properties) {
|
|
|
28896
28971
|
narrowed
|
|
28897
28972
|
};
|
|
28898
28973
|
}
|
|
28974
|
+
/**
|
|
28975
|
+
* The multi-destination refusal sentence, shared by `createRoute`'s guard and
|
|
28976
|
+
* `updateRoute`'s template-path pre-flight (issue #3728) so the two cannot
|
|
28977
|
+
* word the same fault differently.
|
|
28978
|
+
*/
|
|
28979
|
+
function routeMultipleDestinationsMessage(logicalId, declared) {
|
|
28980
|
+
return `Route ${logicalId} declares more than one destination (${declared.join(", ")}). CloudFormation and EC2 accept exactly one of DestinationCidrBlock/DestinationIpv6CidrBlock/DestinationPrefixListId; remove the extra keys from the template.`;
|
|
28981
|
+
}
|
|
28899
28982
|
/** The `AuthorizeSecurityGroupIngress` default protocol: "all protocols". */
|
|
28900
28983
|
const SG_INGRESS_IP_PROTOCOL_DEFAULT = "-1";
|
|
28901
28984
|
/** The refusal path both the create guard and the canonicalizer report under. */
|
|
@@ -29280,7 +29363,7 @@ var EC2Provider = class {
|
|
|
29280
29363
|
case "AWS::EC2::VPCGatewayAttachment": return this.updateVpcGatewayAttachment(logicalId, physicalId);
|
|
29281
29364
|
case "AWS::EC2::NatGateway": return this.updateNatGateway(logicalId, physicalId);
|
|
29282
29365
|
case "AWS::EC2::RouteTable": return this.updateRouteTable(logicalId, physicalId);
|
|
29283
|
-
case "AWS::EC2::Route": return this.updateRoute(logicalId, physicalId, resourceType, properties, previousProperties, context
|
|
29366
|
+
case "AWS::EC2::Route": return this.updateRoute(logicalId, physicalId, resourceType, properties, previousProperties, context);
|
|
29284
29367
|
case "AWS::EC2::SubnetRouteTableAssociation": return this.updateSubnetRouteTableAssociation(logicalId, physicalId);
|
|
29285
29368
|
case "AWS::EC2::SecurityGroup": return this.updateSecurityGroup(logicalId, physicalId, resourceType, properties, previousProperties);
|
|
29286
29369
|
case "AWS::EC2::SecurityGroupIngress": return this.updateSecurityGroupIngress(logicalId, physicalId, resourceType, properties, previousProperties, context?.maskSecrets);
|
|
@@ -30009,7 +30092,7 @@ var EC2Provider = class {
|
|
|
30009
30092
|
const { declared: declaredDestinations, narrowed: narrowedProperties } = narrowRouteDestinations(properties);
|
|
30010
30093
|
let effectiveProperties;
|
|
30011
30094
|
if (declaredDestinations.length > 1) {
|
|
30012
|
-
const message =
|
|
30095
|
+
const message = routeMultipleDestinationsMessage(logicalId, declaredDestinations);
|
|
30013
30096
|
if (onMultipleDestinations) {
|
|
30014
30097
|
const usedKey = declaredDestinations[0];
|
|
30015
30098
|
effectiveProperties = narrowedProperties;
|
|
@@ -30053,12 +30136,17 @@ var EC2Provider = class {
|
|
|
30053
30136
|
throw new ProvisioningError(`Failed to create Route ${logicalId}: ${error instanceof Error ? error.message : String(error)}`, resourceType, logicalId, void 0, cause);
|
|
30054
30137
|
}
|
|
30055
30138
|
}
|
|
30056
|
-
async updateRoute(logicalId, physicalId, resourceType, properties, previousProperties,
|
|
30139
|
+
async updateRoute(logicalId, physicalId, resourceType, properties, previousProperties, context) {
|
|
30057
30140
|
this.logger.debug(`Updating Route ${logicalId}: ${physicalId}`);
|
|
30141
|
+
const maskSecrets = context?.maskSecrets;
|
|
30058
30142
|
if (JSON.stringify(properties) === JSON.stringify(previousProperties)) return {
|
|
30059
30143
|
physicalId,
|
|
30060
30144
|
wasReplaced: false
|
|
30061
30145
|
};
|
|
30146
|
+
if (context?.replayingState !== true && context?.desiredFromAwsReadback !== true) {
|
|
30147
|
+
const { declared } = narrowRouteDestinations(properties);
|
|
30148
|
+
if (declared.length > 1) throw new ProvisioningError(`${routeMultipleDestinationsMessage(logicalId, declared)} The route was not changed.`, resourceType, logicalId, physicalId);
|
|
30149
|
+
}
|
|
30062
30150
|
try {
|
|
30063
30151
|
await this.deleteRoute(logicalId, physicalId, resourceType);
|
|
30064
30152
|
const createResult = await this.createRoute(logicalId, resourceType, properties, (message) => this.logger.warn(message), maskSecrets);
|
|
@@ -33262,7 +33350,7 @@ var ApiGatewayProvider = class ApiGatewayProvider {
|
|
|
33262
33350
|
path: `/canarySettings/stageVariableOverrides/${key}`,
|
|
33263
33351
|
value
|
|
33264
33352
|
});
|
|
33265
|
-
for (const key of Object.keys(prevOverrides)) if (!(key
|
|
33353
|
+
for (const key of Object.keys(prevOverrides)) if (!Object.hasOwn(overrides, key)) patchOperations.push({
|
|
33266
33354
|
op: "remove",
|
|
33267
33355
|
path: `/canarySettings/stageVariableOverrides/${key}`
|
|
33268
33356
|
});
|
|
@@ -33274,7 +33362,7 @@ var ApiGatewayProvider = class ApiGatewayProvider {
|
|
|
33274
33362
|
path: `/variables/${key}`,
|
|
33275
33363
|
value
|
|
33276
33364
|
});
|
|
33277
|
-
for (const key of Object.keys(prevVariables)) if (!(key
|
|
33365
|
+
for (const key of Object.keys(prevVariables)) if (!Object.hasOwn(variables, key)) patchOperations.push({
|
|
33278
33366
|
op: "remove",
|
|
33279
33367
|
path: `/variables/${key}`
|
|
33280
33368
|
});
|
|
@@ -44984,7 +45072,7 @@ var Route53Provider = class {
|
|
|
44984
45072
|
async update(logicalId, physicalId, resourceType, properties, previousProperties, context) {
|
|
44985
45073
|
switch (resourceType) {
|
|
44986
45074
|
case "AWS::Route53::HostedZone": return this.updateHostedZone(logicalId, physicalId, resourceType, properties, previousProperties);
|
|
44987
|
-
case "AWS::Route53::RecordSet": return this.updateRecordSet(logicalId, physicalId, resourceType, properties, context);
|
|
45075
|
+
case "AWS::Route53::RecordSet": return this.updateRecordSet(logicalId, physicalId, resourceType, properties, previousProperties, context);
|
|
44988
45076
|
default: throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId, physicalId);
|
|
44989
45077
|
}
|
|
44990
45078
|
}
|
|
@@ -45331,12 +45419,17 @@ var Route53Provider = class {
|
|
|
45331
45419
|
throw new ProvisioningError(`Failed to create record set ${logicalId}: ${error instanceof Error ? error.message : String(error)}`, resourceType, logicalId, void 0, cause);
|
|
45332
45420
|
}
|
|
45333
45421
|
}
|
|
45334
|
-
async updateRecordSet(logicalId, physicalId, resourceType, properties, context) {
|
|
45422
|
+
async updateRecordSet(logicalId, physicalId, resourceType, properties, previousProperties, context) {
|
|
45335
45423
|
this.logger.debug(`Updating Route 53 record set ${logicalId}: ${physicalId}`);
|
|
45336
45424
|
const hostedZoneId = await this.resolveHostedZoneId(properties, logicalId, resourceType, physicalId);
|
|
45337
45425
|
const recordName = properties["Name"];
|
|
45338
45426
|
const recordType = properties["Type"];
|
|
45339
|
-
const
|
|
45427
|
+
const stateBorneDesired = context?.replayingState === true || context?.desiredFromAwsReadback === true;
|
|
45428
|
+
const recordedSegmentValues = {
|
|
45429
|
+
recordName: previousProperties["Name"],
|
|
45430
|
+
recordType: previousProperties["Type"]
|
|
45431
|
+
};
|
|
45432
|
+
const segments = [
|
|
45340
45433
|
{
|
|
45341
45434
|
name: "hostedZoneId",
|
|
45342
45435
|
value: hostedZoneId
|
|
@@ -45349,8 +45442,15 @@ var Route53Provider = class {
|
|
|
45349
45442
|
name: "recordType",
|
|
45350
45443
|
value: recordType
|
|
45351
45444
|
}
|
|
45352
|
-
]
|
|
45353
|
-
|
|
45445
|
+
];
|
|
45446
|
+
const sameRecordedSegment = (value, recorded) => {
|
|
45447
|
+
if (typeof recorded !== "string" || recorded.includes("{{resolve:")) return true;
|
|
45448
|
+
const normalize = (text) => text.replace(/\.$/, "").toLowerCase();
|
|
45449
|
+
return normalize(String(value)) === normalize(recorded);
|
|
45450
|
+
};
|
|
45451
|
+
const introducesSeparator = !stateBorneDesired && segments.some((segment) => String(segment.value).includes("|") && !sameRecordedSegment(segment.value, recordedSegmentValues[segment.name]));
|
|
45452
|
+
const compositeId = packCompositeId(resourceType, logicalId, segments, {
|
|
45453
|
+
...!introducesSeparator && { onRefusal: (message) => this.logger.warn(message) },
|
|
45354
45454
|
maskSecrets: context?.maskSecrets
|
|
45355
45455
|
});
|
|
45356
45456
|
try {
|
|
@@ -47607,19 +47707,25 @@ var CognitoUserPoolProvider = class {
|
|
|
47607
47707
|
* modify or remove an existing attribute — those changes require replacement
|
|
47608
47708
|
* and are rejected with ResourceUpdateNotSupportedError.
|
|
47609
47709
|
*
|
|
47610
|
-
* The `context` parameter is read for
|
|
47710
|
+
* The `context` parameter is read for two things: `maskSecrets` (issue
|
|
47611
47711
|
* #1932 item 3), forwarded to `applyMfaConfig` so the MFA warnings mask a
|
|
47612
|
-
* resolved secret the same way they do on the create path
|
|
47613
|
-
*
|
|
47614
|
-
*
|
|
47615
|
-
*
|
|
47616
|
-
*
|
|
47617
|
-
*
|
|
47618
|
-
*
|
|
47712
|
+
* resolved secret the same way they do on the create path; and the ORIGIN
|
|
47713
|
+
* of the desired bag (`replayingState` / `desiredFromAwsReadback`), which
|
|
47714
|
+
* decides whether the `MfaConfiguration` shape guard below refuses (a
|
|
47715
|
+
* template-path update) or warns (a rollback revert or `cdkd drift
|
|
47716
|
+
* --revert`) — issue #3728. It reads `desiredFromAwsReadback` for that
|
|
47717
|
+
* origin question ONLY: this provider has no empty-collection-means-delete
|
|
47718
|
+
* shape, so nothing here treats a readback value as a removal.
|
|
47619
47719
|
*/
|
|
47620
47720
|
async update(logicalId, physicalId, resourceType, properties, previousProperties, context) {
|
|
47621
47721
|
this.logger.debug(`Updating Cognito User Pool ${logicalId}: ${physicalId}`);
|
|
47622
|
-
const
|
|
47722
|
+
const stateBorneDesired = context?.replayingState === true || context?.desiredFromAwsReadback === true;
|
|
47723
|
+
let mfaConfiguration;
|
|
47724
|
+
try {
|
|
47725
|
+
mfaConfiguration = readDeclaredMfaConfiguration(properties["MfaConfiguration"], stateBorneDesired ? { onUnusable: (message) => this.logger.warn(message) } : {});
|
|
47726
|
+
} catch (error) {
|
|
47727
|
+
throw new ProvisioningError(`${error instanceof Error ? error.message : String(error)}. Nothing was applied to user pool ${physicalId}`, resourceType, logicalId, physicalId, error instanceof Error ? error : void 0);
|
|
47728
|
+
}
|
|
47623
47729
|
this.warnOnBlankMfaConfiguration(properties["MfaConfiguration"]);
|
|
47624
47730
|
const liveFirstAuthFactors = mfaPreflightNeedsLiveSignInPolicy(properties, mfaConfiguration) ? await this.readLiveAllowedFirstAuthFactors(physicalId) : void 0;
|
|
47625
47731
|
this.assertMfaCombinationApplicable(logicalId, resourceType, physicalId, properties, mfaConfiguration, liveFirstAuthFactors);
|
|
@@ -51473,6 +51579,163 @@ function resolveTableIdentity(input) {
|
|
|
51473
51579
|
};
|
|
51474
51580
|
}
|
|
51475
51581
|
/**
|
|
51582
|
+
* Describe an unresolved name by SHAPE only. Its leaves can be resolved
|
|
51583
|
+
* secrets, and the engine's masker matches a secret's full plaintext, which a
|
|
51584
|
+
* JSON rendering (escaping) or a cut (a fragment) would defeat.
|
|
51585
|
+
*/
|
|
51586
|
+
function describeUnresolvedName(value) {
|
|
51587
|
+
if (Array.isArray(value)) return "an array";
|
|
51588
|
+
if (typeof value === "object" && value !== null) {
|
|
51589
|
+
const keys = Object.keys(value).slice(0, 5);
|
|
51590
|
+
return keys.length === 0 ? "an empty object" : `an object with keys [${keys.join(", ")}]`;
|
|
51591
|
+
}
|
|
51592
|
+
if (typeof value === "number") return "a number that is not a safe integer";
|
|
51593
|
+
return `a ${typeof value}`;
|
|
51594
|
+
}
|
|
51595
|
+
/**
|
|
51596
|
+
* Refuse an UPDATE whose nested `Name` renames the recorded Glue entity
|
|
51597
|
+
* (issue #3724).
|
|
51598
|
+
*
|
|
51599
|
+
* CDK emits the NESTED name (`TableInput.Name`, `DatabaseInput.Name`,
|
|
51600
|
+
* `ConnectionInput.Name`), and none of the registry schemas marks it
|
|
51601
|
+
* createOnly (Table marks its top-level `Name`, Database its `DatabaseName`,
|
|
51602
|
+
* Connection only `CatalogId`), so a rename diffs as an in-place UPDATE. For
|
|
51603
|
+
* a table that update is a wrong-target write: `UpdateTable` addresses the
|
|
51604
|
+
* table BY `TableInput.Name`, so it would rewrite whichever table holds the new
|
|
51605
|
+
* name — possibly one cdkd does not manage — while the state record kept the
|
|
51606
|
+
* old id. `UpdateDatabase` / `UpdateConnection` address the recorded name, but
|
|
51607
|
+
* whatever AWS does with a different name inside the definition, cdkd keeps
|
|
51608
|
+
* recording the old one. No arm is licensed to downgrade this on a replay: the
|
|
51609
|
+
* alternative is a write to a resource the record does not name.
|
|
51610
|
+
*
|
|
51611
|
+
* `ResourceUpdateNotSupportedError` is what the deploy engine's `--replace`
|
|
51612
|
+
* fallback reacts to, so the remedy it names is a real path. An ABSENT name
|
|
51613
|
+
* passes: the builders then send the recorded one. Any other non-string value
|
|
51614
|
+
* still reaches the wire uncoerced, so a safe integer is compared by its string
|
|
51615
|
+
* form (the one spelling JS and Glue cannot disagree on) and anything else is
|
|
51616
|
+
* refused with an untyped error, since a `--replace` CREATE would carry the
|
|
51617
|
+
* same value — cdkd cannot tell which entity it addresses.
|
|
51618
|
+
* `foldCase` is set for tables and databases, whose names Glue folds to
|
|
51619
|
+
* lowercase: a case-only difference addresses the same entity, and a
|
|
51620
|
+
* `drift --revert` bag read back from AWS carries the folded spelling. Only
|
|
51621
|
+
* ASCII is folded, so a guess wrong about Glue's folding over-refuses rather
|
|
51622
|
+
* than letting a different entity through.
|
|
51623
|
+
*/
|
|
51624
|
+
function refuseNestedRename(args) {
|
|
51625
|
+
const { desiredName: raw, recordedName } = args;
|
|
51626
|
+
if (raw == null) return;
|
|
51627
|
+
if (!(typeof raw === "string" || typeof raw === "number" && Number.isSafeInteger(raw))) throw markNonRetryable(new ProvisioningError(`${args.field} is not a resolved name (${describeUnresolvedName(raw)}), so cdkd cannot tell which Glue ${args.noun} the update of ${args.logicalId} would address and will not send it. Declare ${args.field} as a string ('${recordedName}' keeps the recorded ${args.noun})`, args.resourceType, args.logicalId));
|
|
51628
|
+
const desiredName = String(raw);
|
|
51629
|
+
const fold = (name) => args.foldCase ? name.replace(/[A-Z]/g, (c) => c.toLowerCase()) : name;
|
|
51630
|
+
if (fold(desiredName) === fold(recordedName)) return;
|
|
51631
|
+
const remedyFlags = args.stateful ? "--replace --force-stateful-recreation" : "--replace";
|
|
51632
|
+
throw new ResourceUpdateNotSupportedError(args.resourceType, args.logicalId, `${args.field} changed from '${recordedName}' to '${desiredName}', and cdkd cannot rename a Glue ${args.noun} in place — ${args.consequence(desiredName)}. To rename it, re-deploy with ${remedyFlags}, which DELETEs the ${args.noun} '${recordedName}' and then CREATEs '${desiredName}' (under UpdateReplacePolicy: Retain the old one is kept instead); the CREATE fails if a ${args.noun} named '${desiredName}' already exists, after the DELETE. If the template did not change this name, the state record was left by an earlier deploy that wrote to '${desiredName}' (issue #3724): check that ${args.noun} before re-deploying. Otherwise keep the name '${recordedName}'`);
|
|
51633
|
+
}
|
|
51634
|
+
/**
|
|
51635
|
+
* The recorded `CatalogId` a `readCurrentState` snapshot carries back, so a
|
|
51636
|
+
* `drift --revert` built from that snapshot addresses the catalog the entity
|
|
51637
|
+
* was READ from (issue #3756). `GetDatabase` / `GetTable` / `GetConnection` do
|
|
51638
|
+
* not echo it, and a snapshot without it made the revert's update target this
|
|
51639
|
+
* account's DEFAULT catalog. Echoed only when usable: the raw value keeps drift
|
|
51640
|
+
* comparing like with like, and an unusable one (the account-id pseudo
|
|
51641
|
+
* parameter, another intrinsic) stays absent, which is what the reads
|
|
51642
|
+
* addressed for it.
|
|
51643
|
+
*/
|
|
51644
|
+
function withRecordedCatalogId(snapshot, properties) {
|
|
51645
|
+
const raw = properties?.["CatalogId"];
|
|
51646
|
+
return catalogIdForApi(raw) === void 0 ? snapshot : {
|
|
51647
|
+
...snapshot,
|
|
51648
|
+
CatalogId: raw
|
|
51649
|
+
};
|
|
51650
|
+
}
|
|
51651
|
+
/**
|
|
51652
|
+
* The `CatalogId` an UPDATE sends. A finite number (a YAML-numeric account id,
|
|
51653
|
+
* which {@link withRecordedCatalogId} can now carry into a `drift --revert`
|
|
51654
|
+
* bag) is stringified the way the readers and deletes do; anything else keeps
|
|
51655
|
+
* the pre-existing cast, so an unresolved intrinsic still reaches AWS and is
|
|
51656
|
+
* rejected there rather than silently defaulting to this account's catalog.
|
|
51657
|
+
*/
|
|
51658
|
+
function updateCatalogId(value) {
|
|
51659
|
+
return typeof value === "number" && Number.isFinite(value) ? String(value) : value;
|
|
51660
|
+
}
|
|
51661
|
+
/**
|
|
51662
|
+
* Classify a `CatalogId`. Absent and the account-id pseudo parameter both mean
|
|
51663
|
+
* the caller's own catalog ({@link isAccountIdPseudoParameter}); a usable
|
|
51664
|
+
* literal is itself; anything else (another intrinsic, a malformed value)
|
|
51665
|
+
* cannot be placed.
|
|
51666
|
+
*/
|
|
51667
|
+
function classifyCatalog(value) {
|
|
51668
|
+
if (value == null || isAccountIdPseudoParameter(value)) return { kind: "default" };
|
|
51669
|
+
const id = catalogIdForApi(value);
|
|
51670
|
+
return id === void 0 ? { kind: "unusable" } : {
|
|
51671
|
+
kind: "literal",
|
|
51672
|
+
id
|
|
51673
|
+
};
|
|
51674
|
+
}
|
|
51675
|
+
/**
|
|
51676
|
+
* Refuse an UPDATE whose `CatalogId` moves the entity to another Data Catalog
|
|
51677
|
+
* (issue #3756).
|
|
51678
|
+
*
|
|
51679
|
+
* Every Glue update sends the DESIRED `CatalogId` while the state record names
|
|
51680
|
+
* only the entity, so a changed catalog addresses the same-named entity in
|
|
51681
|
+
* ANOTHER catalog — rewriting it while the recorded one is left alone.
|
|
51682
|
+
* `AWS::Glue::Database` reaches this on every such edit (its registry schema
|
|
51683
|
+
* marks only `DatabaseName` createOnly); Table and Connection mark `CatalogId`
|
|
51684
|
+
* createOnly and reach it only when the createOnly lookup degrades.
|
|
51685
|
+
*
|
|
51686
|
+
* Equivalence is decided, not string-compared: absent and a literal equal to
|
|
51687
|
+
* the caller's own account are the SAME catalog, so the mixed case asks STS
|
|
51688
|
+
* (`callerAccountId`), which a CDK stack's `catalogId: Stack.of(this).account`
|
|
51689
|
+
* hits whenever the recorded side holds the pseudo parameter an import left.
|
|
51690
|
+
* An unusable DESIRED side is left to the wire as before, and an unusable
|
|
51691
|
+
* RECORDED side (an imported raw intrinsic) cannot be placed, so it warns and
|
|
51692
|
+
* proceeds: refusing would wedge every later deploy on a record the user
|
|
51693
|
+
* cannot edit.
|
|
51694
|
+
*/
|
|
51695
|
+
async function refuseCatalogMove(args) {
|
|
51696
|
+
const recorded = classifyCatalog(args.recorded);
|
|
51697
|
+
const desired = classifyCatalog(args.desired);
|
|
51698
|
+
if (desired.kind === "unusable") return;
|
|
51699
|
+
if (recorded.kind === "unusable") {
|
|
51700
|
+
args.warn(`Glue ${args.noun} ${args.logicalId}: the recorded CatalogId is not a usable value (likely an unresolved intrinsic an import recorded), so cdkd cannot confirm the update addresses the Data Catalog the ${args.noun} was deployed to; it proceeds against ${desired.kind === "literal" ? `Data Catalog ${desired.id}` : "this account's default Data Catalog"}.`);
|
|
51701
|
+
return;
|
|
51702
|
+
}
|
|
51703
|
+
if (recorded.kind === "default" && desired.kind === "default") return;
|
|
51704
|
+
if (recorded.kind === "literal" && desired.kind === "literal") {
|
|
51705
|
+
if (recorded.id === desired.id) return;
|
|
51706
|
+
} else {
|
|
51707
|
+
const literal = recorded.kind === "literal" ? recorded.id : desired.id;
|
|
51708
|
+
let callerAccount;
|
|
51709
|
+
try {
|
|
51710
|
+
callerAccount = await args.callerAccountId();
|
|
51711
|
+
} catch (error) {
|
|
51712
|
+
throw new ProvisioningError(`Could not resolve the caller's account id (sts:GetCallerIdentity) to tell whether CatalogId ${literal} is this account's default Data Catalog, so cdkd did not update Glue ${args.noun} ${args.logicalId}: ${error instanceof Error ? error.message : String(error)}`, args.resourceType, args.logicalId, void 0, error instanceof Error ? error : void 0);
|
|
51713
|
+
}
|
|
51714
|
+
if (literal === callerAccount) return;
|
|
51715
|
+
}
|
|
51716
|
+
const describe = (side) => side.kind === "literal" ? `Data Catalog ${side.id}` : "this account's default Data Catalog";
|
|
51717
|
+
const remedyFlags = args.stateful ? "--replace --force-stateful-recreation" : "--replace";
|
|
51718
|
+
throw new ResourceUpdateNotSupportedError(args.resourceType, args.logicalId, `CatalogId moves the ${args.noun} '${args.entityName}' from ${describe(recorded)} to ${describe(desired)}, and an in-place update would address the same-named ${args.noun} in the NEW catalog while the state record kept the old one. To move it, re-deploy with ${remedyFlags}, which DELETEs the ${args.noun} from ${describe(recorded)} and then CREATEs it in ${describe(desired)} (under UpdateReplacePolicy: Retain the old one is kept instead); or keep the recorded CatalogId`);
|
|
51719
|
+
}
|
|
51720
|
+
/**
|
|
51721
|
+
* A memoized "which account am I" for {@link refuseCatalogMove}'s mixed case,
|
|
51722
|
+
* built per provider instance so the STS call happens at most once and only
|
|
51723
|
+
* when a catalog comparison needs it. A failure is not cached.
|
|
51724
|
+
*/
|
|
51725
|
+
function makeCallerAccountResolver(region) {
|
|
51726
|
+
let stsClient;
|
|
51727
|
+
let cached;
|
|
51728
|
+
return async () => {
|
|
51729
|
+
if (cached) return cached;
|
|
51730
|
+
stsClient ??= new STSClient({
|
|
51731
|
+
...ambientClientDefaults(),
|
|
51732
|
+
...region ? { region } : {}
|
|
51733
|
+
});
|
|
51734
|
+
cached = await resolveAccountId(stsClient);
|
|
51735
|
+
return cached;
|
|
51736
|
+
};
|
|
51737
|
+
}
|
|
51738
|
+
/**
|
|
51476
51739
|
* SDK Provider for AWS Glue resources
|
|
51477
51740
|
*
|
|
51478
51741
|
* Supports:
|
|
@@ -51485,6 +51748,7 @@ function resolveTableIdentity(input) {
|
|
|
51485
51748
|
var GlueProvider = class {
|
|
51486
51749
|
client;
|
|
51487
51750
|
providerRegion = ambientRegion();
|
|
51751
|
+
callerAccountId = makeCallerAccountResolver(this.providerRegion);
|
|
51488
51752
|
logger = getLogger().child("GlueProvider");
|
|
51489
51753
|
handledProperties = /* @__PURE__ */ new Map([["AWS::Glue::Database", /* @__PURE__ */ new Set([
|
|
51490
51754
|
"DatabaseInput",
|
|
@@ -51551,7 +51815,29 @@ var GlueProvider = class {
|
|
|
51551
51815
|
this.logger.debug(`Updating Glue Database ${logicalId}: ${physicalId}`);
|
|
51552
51816
|
const databaseInput = properties["DatabaseInput"];
|
|
51553
51817
|
if (!databaseInput) throw new ProvisioningError(`DatabaseInput is required for Glue Database update ${logicalId}`, resourceType, logicalId, physicalId);
|
|
51554
|
-
|
|
51818
|
+
refuseNestedRename({
|
|
51819
|
+
resourceType,
|
|
51820
|
+
logicalId,
|
|
51821
|
+
field: "DatabaseInput.Name",
|
|
51822
|
+
noun: "database",
|
|
51823
|
+
recordedName: physicalId,
|
|
51824
|
+
desiredName: databaseInput["Name"],
|
|
51825
|
+
foldCase: true,
|
|
51826
|
+
consequence: () => `UpdateDatabase would address '${physicalId}' with a different name inside its definition, and the state record would keep '${physicalId}' whatever AWS did with it`,
|
|
51827
|
+
stateful: true
|
|
51828
|
+
});
|
|
51829
|
+
await refuseCatalogMove({
|
|
51830
|
+
resourceType,
|
|
51831
|
+
logicalId,
|
|
51832
|
+
noun: "database",
|
|
51833
|
+
entityName: physicalId,
|
|
51834
|
+
recorded: previousProperties?.["CatalogId"],
|
|
51835
|
+
desired: properties["CatalogId"],
|
|
51836
|
+
stateful: true,
|
|
51837
|
+
callerAccountId: this.callerAccountId,
|
|
51838
|
+
warn: (message) => this.logger.warn(message)
|
|
51839
|
+
});
|
|
51840
|
+
const catalogId = updateCatalogId(properties["CatalogId"]);
|
|
51555
51841
|
const liveParameters = await this.readLiveDatabaseParameters(logicalId, resourceType, physicalId, catalogId);
|
|
51556
51842
|
const previousDatabaseInput = asRecord(previousProperties?.["DatabaseInput"]);
|
|
51557
51843
|
try {
|
|
@@ -51644,7 +51930,29 @@ var GlueProvider = class {
|
|
|
51644
51930
|
const { databaseName, tableName } = decoded;
|
|
51645
51931
|
const tableInput = properties["TableInput"];
|
|
51646
51932
|
if (!tableInput) throw new ProvisioningError(`TableInput is required for Glue Table update ${logicalId}`, resourceType, logicalId, physicalId);
|
|
51647
|
-
|
|
51933
|
+
refuseNestedRename({
|
|
51934
|
+
resourceType,
|
|
51935
|
+
logicalId,
|
|
51936
|
+
field: "TableInput.Name",
|
|
51937
|
+
noun: "table",
|
|
51938
|
+
recordedName: tableName,
|
|
51939
|
+
desiredName: tableInput["Name"],
|
|
51940
|
+
foldCase: true,
|
|
51941
|
+
consequence: (desired) => `UpdateTable addresses the table by TableInput.Name, so it would write to the table named '${desired}' in database '${databaseName}' (possibly one cdkd does not manage) while the state record kept '${tableName}'`,
|
|
51942
|
+
stateful: true
|
|
51943
|
+
});
|
|
51944
|
+
await refuseCatalogMove({
|
|
51945
|
+
resourceType,
|
|
51946
|
+
logicalId,
|
|
51947
|
+
noun: "table",
|
|
51948
|
+
entityName: `${databaseName}.${tableName}`,
|
|
51949
|
+
recorded: previousProperties?.["CatalogId"],
|
|
51950
|
+
desired: properties["CatalogId"],
|
|
51951
|
+
stateful: true,
|
|
51952
|
+
callerAccountId: this.callerAccountId,
|
|
51953
|
+
warn: (message) => this.logger.warn(message)
|
|
51954
|
+
});
|
|
51955
|
+
const catalogId = updateCatalogId(properties["CatalogId"]);
|
|
51648
51956
|
const updateIcebergKey = findIcebergTableInputKey(properties);
|
|
51649
51957
|
if (updateIcebergKey !== void 0) this.logger.warn(icebergTableInputRefusalMessage(logicalId, updateIcebergKey, "update"));
|
|
51650
51958
|
const live = await this.readLiveTableState(logicalId, resourceType, physicalId, databaseName, tableName, catalogId);
|
|
@@ -52155,11 +52463,10 @@ var GlueProvider = class {
|
|
|
52155
52463
|
* `ViewExpandedText`, `TargetTable`). The table physicalId is
|
|
52156
52464
|
* `databaseName|tableName`; we recover both from the split.
|
|
52157
52465
|
*
|
|
52158
|
-
* `CatalogId` is
|
|
52159
|
-
*
|
|
52160
|
-
*
|
|
52161
|
-
*
|
|
52162
|
-
* fire false drift here.
|
|
52466
|
+
* `CatalogId` is not READ — `GetDatabase` / `GetTable` do not echo it —
|
|
52467
|
+
* but the recorded usable value is carried back
|
|
52468
|
+
* ({@link withRecordedCatalogId}), so a `drift --revert` built from this
|
|
52469
|
+
* snapshot addresses the catalog it was read from.
|
|
52163
52470
|
*
|
|
52164
52471
|
* Returns `undefined` when the resource is gone (`EntityNotFoundException`).
|
|
52165
52472
|
* Other Glue resource types (`Job`, `Crawler`, `Connection`, `Trigger`,
|
|
@@ -52170,8 +52477,14 @@ var GlueProvider = class {
|
|
|
52170
52477
|
async readCurrentState(physicalId, _logicalId, resourceType, properties) {
|
|
52171
52478
|
const catalogId = catalogIdForApi(properties?.["CatalogId"]);
|
|
52172
52479
|
switch (resourceType) {
|
|
52173
|
-
case "AWS::Glue::Database":
|
|
52174
|
-
|
|
52480
|
+
case "AWS::Glue::Database": {
|
|
52481
|
+
const snapshot = await this.readDatabase(physicalId, catalogId);
|
|
52482
|
+
return snapshot && withRecordedCatalogId(snapshot, properties);
|
|
52483
|
+
}
|
|
52484
|
+
case "AWS::Glue::Table": {
|
|
52485
|
+
const snapshot = await this.readTable(physicalId, catalogId, properties);
|
|
52486
|
+
return snapshot && withRecordedCatalogId(snapshot, properties);
|
|
52487
|
+
}
|
|
52175
52488
|
default: return;
|
|
52176
52489
|
}
|
|
52177
52490
|
}
|
|
@@ -53605,6 +53918,7 @@ function toCfnCrawlerTargets(targets) {
|
|
|
53605
53918
|
var GlueConnectionProvider = class {
|
|
53606
53919
|
client;
|
|
53607
53920
|
providerRegion = ambientRegion();
|
|
53921
|
+
callerAccountId = makeCallerAccountResolver(this.providerRegion);
|
|
53608
53922
|
logger = getLogger().child("GlueConnectionProvider");
|
|
53609
53923
|
handledProperties = /* @__PURE__ */ new Map([["AWS::Glue::Connection", /* @__PURE__ */ new Set(["ConnectionInput", "CatalogId"])]]);
|
|
53610
53924
|
getClient() {
|
|
@@ -53635,14 +53949,36 @@ var GlueConnectionProvider = class {
|
|
|
53635
53949
|
throw new ProvisioningError(`Failed to create Glue Connection ${logicalId}: ${error instanceof Error ? error.message : String(error)}`, resourceType, logicalId, void 0, cause);
|
|
53636
53950
|
}
|
|
53637
53951
|
}
|
|
53638
|
-
async update(logicalId, physicalId, resourceType, properties,
|
|
53952
|
+
async update(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
53639
53953
|
this.logger.debug(`Updating Glue Connection ${logicalId}: ${physicalId}`);
|
|
53640
53954
|
const connectionInput = properties["ConnectionInput"];
|
|
53641
53955
|
if (!connectionInput) throw new ProvisioningError(`ConnectionInput is required for Glue Connection update ${logicalId}`, resourceType, logicalId, physicalId);
|
|
53642
|
-
|
|
53956
|
+
refuseNestedRename({
|
|
53957
|
+
resourceType,
|
|
53958
|
+
logicalId,
|
|
53959
|
+
field: "ConnectionInput.Name",
|
|
53960
|
+
noun: "connection",
|
|
53961
|
+
recordedName: physicalId,
|
|
53962
|
+
desiredName: connectionInput["Name"],
|
|
53963
|
+
foldCase: false,
|
|
53964
|
+
consequence: () => `UpdateConnection would address '${physicalId}' with a different name inside its definition, and the state record would keep '${physicalId}' whatever AWS did with it`,
|
|
53965
|
+
stateful: false
|
|
53966
|
+
});
|
|
53967
|
+
await refuseCatalogMove({
|
|
53968
|
+
resourceType,
|
|
53969
|
+
logicalId,
|
|
53970
|
+
noun: "connection",
|
|
53971
|
+
entityName: physicalId,
|
|
53972
|
+
recorded: previousProperties?.["CatalogId"],
|
|
53973
|
+
desired: properties["CatalogId"],
|
|
53974
|
+
stateful: false,
|
|
53975
|
+
callerAccountId: this.callerAccountId,
|
|
53976
|
+
warn: (message) => this.logger.warn(message)
|
|
53977
|
+
});
|
|
53978
|
+
const catalogId = updateCatalogId(properties["CatalogId"]);
|
|
53643
53979
|
try {
|
|
53644
53980
|
await this.getClient().send(new UpdateConnectionCommand({
|
|
53645
|
-
...catalogId && { CatalogId: catalogId },
|
|
53981
|
+
...catalogId !== void 0 && { CatalogId: catalogId },
|
|
53646
53982
|
Name: physicalId,
|
|
53647
53983
|
ConnectionInput: buildConnectionInput(connectionInput, physicalId)
|
|
53648
53984
|
}));
|
|
@@ -53691,7 +54027,7 @@ var GlueConnectionProvider = class {
|
|
|
53691
54027
|
throw err;
|
|
53692
54028
|
}
|
|
53693
54029
|
if (!conn) return void 0;
|
|
53694
|
-
return { ConnectionInput: {
|
|
54030
|
+
return withRecordedCatalogId({ ConnectionInput: {
|
|
53695
54031
|
Name: conn.Name ?? physicalId,
|
|
53696
54032
|
ConnectionType: conn.ConnectionType ?? "",
|
|
53697
54033
|
Description: conn.Description ?? "",
|
|
@@ -53701,7 +54037,7 @@ var GlueConnectionProvider = class {
|
|
|
53701
54037
|
AthenaProperties: conn.AthenaProperties ?? {},
|
|
53702
54038
|
PythonProperties: conn.PythonProperties ?? {},
|
|
53703
54039
|
PhysicalConnectionRequirements: conn.PhysicalConnectionRequirements ? pickDefined(conn.PhysicalConnectionRequirements) : {}
|
|
53704
|
-
} };
|
|
54040
|
+
} }, properties);
|
|
53705
54041
|
}
|
|
53706
54042
|
async import(input) {
|
|
53707
54043
|
const explicitName = input.knownPhysicalId ?? input.properties["ConnectionInput"]?.["Name"];
|
|
@@ -64868,14 +65204,24 @@ async function runDestroyForStack(stackName, state, ctx) {
|
|
|
64868
65204
|
* as the other. The ` / ` join that first replaced it was its own defect:
|
|
64869
65205
|
* pasted, it handed the second command to the first as arguments.
|
|
64870
65206
|
*/
|
|
64871
|
-
const
|
|
65207
|
+
const hintCommand = (command, t) => pasteableCommand(command, [{
|
|
64872
65208
|
value: t,
|
|
64873
|
-
hole: "stack"
|
|
65209
|
+
hole: "stack",
|
|
65210
|
+
opts: { plainIdent: true }
|
|
64874
65211
|
}, {
|
|
64875
65212
|
flag: "--stack-region",
|
|
64876
65213
|
value: regionForState,
|
|
64877
|
-
hole: "region"
|
|
64878
|
-
|
|
65214
|
+
hole: "region",
|
|
65215
|
+
opts: { plainIdent: true }
|
|
65216
|
+
}]);
|
|
65217
|
+
const hintFor = (command, targets, label) => [...new Set(targets.map((t) => `\n${label}: ${hintCommand(command, t).command}`))].join("");
|
|
65218
|
+
/**
|
|
65219
|
+
* The ONE sentence explaining `hintFor`'s holes, for the prose BEFORE its
|
|
65220
|
+
* lines (go-to-k/cdkd#3759). `hintFor` prints one command per target, so a
|
|
65221
|
+
* per-hole `withheldTargetClause` would repeat once per line; this states the
|
|
65222
|
+
* rule once, and only when the gate actually withheld a value on some line.
|
|
65223
|
+
*/
|
|
65224
|
+
const hintHolesClause = (targets) => targets.every((t) => hintCommand("cdkd state show", t).withheld.length === 0) ? "" : " A target that is not a plain identifier is printed as a quoted '<stack>' or '<region>' placeholder; list the records as stored with 'cdkd state list --long'.";
|
|
64879
65225
|
const buildDestroySnapshot = () => {
|
|
64880
65226
|
const { imports: _imports, outputReads: _outputReads, ...rest } = state;
|
|
64881
65227
|
return {
|
|
@@ -65163,26 +65509,29 @@ async function runDestroyForStack(stackName, state, ctx) {
|
|
|
65163
65509
|
const skippedSuffix = result.skippedCount > 0 ? `, ${yellow(result.skippedCount)} skipped` : "";
|
|
65164
65510
|
const guardSuffix = result.guardIndeterminateCount > 0 ? `, ${yellow(result.guardIndeterminateCount)} unverified` : "";
|
|
65165
65511
|
if (result.guardIndeterminateCount > 0) {
|
|
65166
|
-
const
|
|
65512
|
+
const eventsCommand = pasteableCommand("cdkd events", [{
|
|
65167
65513
|
value: stackName,
|
|
65168
|
-
hole: "stack"
|
|
65169
|
-
|
|
65170
|
-
|
|
65514
|
+
hole: "stack",
|
|
65515
|
+
opts: { plainIdent: true }
|
|
65516
|
+
}]);
|
|
65517
|
+
const durablePointer = ctx.eventRecorder === void 0 ? "This summary is the only record: this run wrote no deployment events, either because it is a 'cdkd state destroy' (go-to-k/cdkd#2423) or because it is a nested-stack child, neither of which threads an event recorder." : "The RESOURCE_GUARD_INDETERMINATE entries name the check and the reason and survive the run." + withheldTargetClause(eventsCommand, "stack", "cdkd events", "This stack's name") + `\nRead them with: ${eventsCommand.command}`;
|
|
65518
|
+
logger.warn(`\n${yellow("⚠")} ${result.guardIndeterminateCount} pre-flight safety check(s) could NOT be completed during this destroy and cdkd proceeded anyway: ${[...guardIndeterminateTargets].map((t) => plainOrDescribed(t, "logical id")).join(", ")}. A check can be suppressed by DENYING the permission it needs, so treat this as unconfirmed rather than benign. ${durablePointer}`);
|
|
65171
65519
|
}
|
|
65172
|
-
if (!preserveState) logger.info(`\n${green("✓")} ${bold(`Stack ${stackName} destroyed`)} (${green(result.deletedCount)} deleted${retainedSuffix}${guardSuffix}, ${result.errorCount} errors)`);
|
|
65173
|
-
else if (result.interrupted && result.errorCount === 0) logger.warn(`\n${yellow("⚠")} ${bold(`Stack ${stackName} destroy interrupted`)} (${green(result.deletedCount)} deleted${retainedSuffix}${skippedSuffix}${guardSuffix}, ${result.errorCount} errors). State preserved — re-run 'cdkd destroy' / 'cdkd state destroy' to finish.`);
|
|
65520
|
+
if (!preserveState) logger.info(`\n${green("✓")} ${bold(`Stack ${plainOrDescribed(stackName, "stack name")} destroyed`)} (${green(result.deletedCount)} deleted${retainedSuffix}${guardSuffix}, ${result.errorCount} errors)`);
|
|
65521
|
+
else if (result.interrupted && result.errorCount === 0) logger.warn(`\n${yellow("⚠")} ${bold(`Stack ${plainOrDescribed(stackName, "stack name")} destroy interrupted`)} (${green(result.deletedCount)} deleted${retainedSuffix}${skippedSuffix}${guardSuffix}, ${result.errorCount} errors). State preserved — re-run 'cdkd destroy' / 'cdkd state destroy' to finish.`);
|
|
65174
65522
|
else if (result.errorCount === 0) {
|
|
65175
65523
|
const targets = [...skippedStateTargets];
|
|
65176
65524
|
const showHint = hintFor("cdkd state show", targets, "Inspect it with");
|
|
65177
65525
|
const orphanHint = hintFor("cdkd state orphan", targets, "Drop the record with");
|
|
65178
|
-
logger.warn(`\n${yellow("⚠")} ${bold(`Stack ${stackName} partially destroyed`)} (${green(result.deletedCount)} deleted${retainedSuffix}${skippedSuffix}${guardSuffix}, ${result.errorCount} errors). cdkd could not address the skipped resource(s), so they may still exist in AWS. Fix the physicalId in state.json and re-run, or delete them by hand and drop the records.` + showHint + orphanHint);
|
|
65526
|
+
logger.warn(`\n${yellow("⚠")} ${bold(`Stack ${plainOrDescribed(stackName, "stack name")} partially destroyed`)} (${green(result.deletedCount)} deleted${retainedSuffix}${skippedSuffix}${guardSuffix}, ${result.errorCount} errors). cdkd could not address the skipped resource(s), so they may still exist in AWS. Fix the physicalId in state.json and re-run, or delete them by hand and drop the records.` + hintHolesClause(targets) + showHint + orphanHint);
|
|
65179
65527
|
} else {
|
|
65180
|
-
const
|
|
65528
|
+
const failedTargets = failedStateTargets.size > 0 ? [...failedStateTargets] : [stackName];
|
|
65529
|
+
const orphanHint = hintFor("cdkd state orphan", failedTargets, "Drop the record with");
|
|
65181
65530
|
const skippedTargets = [...skippedStateTargets];
|
|
65182
65531
|
const skippedClause = skippedTargets.length > 0 ? ` Separately, ${result.skippedCount} resource(s) were SKIPPED — cdkd could not address them, so no delete was issued and they may still exist in AWS. Fix the physicalId in state.json and re-run, or delete them by hand and drop their records.` : "";
|
|
65183
65532
|
const skippedCommands = hintFor("cdkd state show", skippedTargets, "Inspect it with") + hintFor("cdkd state orphan", skippedTargets, "Drop the record with");
|
|
65184
65533
|
const dedupedCommands = (lines) => [...new Set(lines.split("\n").filter((l) => l !== ""))].map((l) => `\n${l}`).join("");
|
|
65185
|
-
logger.warn(`\n${yellow("⚠")} ${bold(`Stack ${stackName} partially destroyed`)} (${green(result.deletedCount)} deleted${retainedSuffix}${skippedSuffix}${guardSuffix}, ${red(result.errorCount)} errors). State preserved — re-run 'cdkd destroy' / 'cdkd state destroy' to clean up. If the same resource keeps failing, dropping the state record is the last resort: it removes the record without deleting AWS resources.` + skippedClause + dedupedCommands(orphanHint + skippedCommands));
|
|
65534
|
+
logger.warn(`\n${yellow("⚠")} ${bold(`Stack ${plainOrDescribed(stackName, "stack name")} partially destroyed`)} (${green(result.deletedCount)} deleted${retainedSuffix}${skippedSuffix}${guardSuffix}, ${red(result.errorCount)} errors). State preserved — re-run 'cdkd destroy' / 'cdkd state destroy' to clean up. If the same resource keeps failing, dropping the state record is the last resort: it removes the record without deleting AWS resources.` + skippedClause + hintHolesClause([...failedTargets, ...skippedTargets]) + dedupedCommands(orphanHint + skippedCommands));
|
|
65186
65535
|
}
|
|
65187
65536
|
} finally {
|
|
65188
65537
|
try {
|
|
@@ -65297,16 +65646,18 @@ function getCurrentNestedStackContext() {
|
|
|
65297
65646
|
* prevent. `tests/unit/provisioning/nested-stack-provider.test.ts` pins that
|
|
65298
65647
|
* property against the union of both phrase sets.
|
|
65299
65648
|
*
|
|
65300
|
-
* @param childStackName the child's `<parent>~<childLogicalId>` state key
|
|
65649
|
+
* @param childStackName the child's `<parent>~<childLogicalId>` state key as
|
|
65650
|
+
* the PROSE may print it — the caller passes it through `plainOrDescribed`,
|
|
65651
|
+
* since this leaf cannot import it (go-to-k/cdkd#3759)
|
|
65301
65652
|
* @param errorCount resources in the child that failed to delete
|
|
65302
65653
|
* @param alsoSkippedCount resources the child SKIPPED (no AWS call issued)
|
|
65303
65654
|
* @param alsoInterrupted whether the child's destroy was also interrupted
|
|
65304
65655
|
*/
|
|
65305
|
-
function nestedStackChildFailureMessage(childStackName, errorCount, alsoSkippedCount, alsoInterrupted, inspectCommand) {
|
|
65656
|
+
function nestedStackChildFailureMessage(childStackName, errorCount, alsoSkippedCount, alsoInterrupted, inspectCommand, holeNote = "") {
|
|
65306
65657
|
const extra = [];
|
|
65307
65658
|
if (alsoSkippedCount > 0) extra.push(`${alsoSkippedCount} resource(s) were also skipped`);
|
|
65308
65659
|
if (alsoInterrupted) extra.push("the child destroy was also interrupted");
|
|
65309
|
-
return `Nested stack ${childStackName} failed to destroy: ${errorCount} resource(s) failed to delete` + (extra.length > 0 ? ` (${extra.join("; ")})` : "") +
|
|
65660
|
+
return `Nested stack ${childStackName} failed to destroy: ${errorCount} resource(s) failed to delete` + (extra.length > 0 ? ` (${extra.join("; ")})` : "") + ". The child's state is PRESERVED and still lists them — inspect it, resolve the failure, and re-run the destroy. The parent's record of this nested stack is kept so the child stays reachable." + holeNote + `\nInspect it with: ${inspectCommand}`;
|
|
65310
65661
|
}
|
|
65311
65662
|
|
|
65312
65663
|
//#endregion
|
|
@@ -65483,10 +65834,12 @@ var NestedStackProvider = class {
|
|
|
65483
65834
|
...ctx.destroyOptions?.resourceTimeoutByType && { resourceTimeoutByType: ctx.destroyOptions.resourceTimeoutByType }
|
|
65484
65835
|
}));
|
|
65485
65836
|
if (childResult.errorCount > 0) {
|
|
65486
|
-
const
|
|
65837
|
+
const inspect = pasteableCommand("cdkd state show", [{
|
|
65487
65838
|
value: childStackName,
|
|
65488
|
-
hole: "stack"
|
|
65489
|
-
|
|
65839
|
+
hole: "stack",
|
|
65840
|
+
opts: { plainIdent: true }
|
|
65841
|
+
}]);
|
|
65842
|
+
const failure = new Error(nestedStackChildFailureMessage(plainOrDescribed(childStackName, "stack name"), childResult.errorCount, childResult.skippedCount, childResult.interrupted, inspect.command, withheldTargetClause(inspect, "stack", "cdkd state show", "The child stack's name")));
|
|
65490
65843
|
throw childResult.interrupted ? markNonRetryable(failure) : failure;
|
|
65491
65844
|
}
|
|
65492
65845
|
if (childResult.skippedCount > 0 || childResult.interrupted) {
|
|
@@ -68983,17 +69336,38 @@ async function resolveChildStackParameters(parentStackRow, parentTemplate, paren
|
|
|
68983
69336
|
* and the user should re-synth, exactly as `NestedStackProvider` would
|
|
68984
69337
|
* fail at deploy time.
|
|
68985
69338
|
*/
|
|
69339
|
+
/**
|
|
69340
|
+
* The template's `Resources` entries whose logical id the state already
|
|
69341
|
+
* records — the only rows that can diff as an UPDATE. Own keys only, and
|
|
69342
|
+
* tolerant of a malformed section, since it feeds a prefetch that must never
|
|
69343
|
+
* throw.
|
|
69344
|
+
*/
|
|
69345
|
+
function recordedTemplateResources(template, state) {
|
|
69346
|
+
const recorded = nullPrototypeRecord();
|
|
69347
|
+
const resources = template.Resources;
|
|
69348
|
+
const stateResources = state.resources;
|
|
69349
|
+
if (resources === null || typeof resources !== "object" || stateResources === null || typeof stateResources !== "object") return recorded;
|
|
69350
|
+
for (const [logicalId, resource] of Object.entries(resources)) if (Object.prototype.hasOwnProperty.call(stateResources, logicalId)) recorded[logicalId] = resource;
|
|
69351
|
+
return recorded;
|
|
69352
|
+
}
|
|
68986
69353
|
async function buildDiffTree(args) {
|
|
68987
69354
|
const { stackName, displayName, region, template, nestedTemplates, recursive, stateBackend, diffCalculator, parentHasSecretReference, parameters, canonicalizeProperties, assetRedirect, cfnFallback, previewOrphanAdoption, ancestorTemplatePaths, isNestedChild } = args;
|
|
68988
69355
|
const { state, unreadable, deployRefusals } = await loadStateOrEmpty(stackName, region, stateBackend);
|
|
69356
|
+
const createOnlyPrefetch = prefetchCreateOnlyPropertyPaths(templateResourceTypes(recordedTemplateResources(template, state)));
|
|
68989
69357
|
const secretBearingAbove = parentHasSecretReference === true || templateHasSecretDynamicReference(template);
|
|
68990
|
-
|
|
68991
|
-
|
|
68992
|
-
|
|
68993
|
-
|
|
68994
|
-
|
|
68995
|
-
|
|
68996
|
-
|
|
69358
|
+
let stackDiff;
|
|
69359
|
+
try {
|
|
69360
|
+
stackDiff = await computeStackDiff(state, template, region, stackName, stateBackend, diffCalculator, {
|
|
69361
|
+
...parameters && { parameters },
|
|
69362
|
+
...canonicalizeProperties && { canonicalizeProperties },
|
|
69363
|
+
...cfnFallback !== void 0 && { cfnFallback },
|
|
69364
|
+
...previewOrphanAdoption && { previewOrphanAdoption },
|
|
69365
|
+
inheritSecretBearingTemplate: false
|
|
69366
|
+
});
|
|
69367
|
+
} finally {
|
|
69368
|
+
createOnlyPrefetch.cancel();
|
|
69369
|
+
}
|
|
69370
|
+
const { changes, outputChanges, adoptedOrphans, adoptedRecords, blocking, unreadableOrphans, deployRefusals: adoptedDeployRefusals } = stackDiff;
|
|
68997
69371
|
const stateAfterAdoption = Object.keys(adoptedRecords).length > 0 ? {
|
|
68998
69372
|
...state,
|
|
68999
69373
|
resources: {
|
|
@@ -77522,14 +77896,16 @@ async function destroyCommand(stackArgs, options) {
|
|
|
77522
77896
|
else stackTargetRegion = onlyRegion;
|
|
77523
77897
|
} else if (synthRegion && refs.some((r) => r.region === synthRegion)) stackTargetRegion = synthRegion;
|
|
77524
77898
|
else {
|
|
77525
|
-
const regions = refs.map((r) => r.region
|
|
77526
|
-
|
|
77899
|
+
const regions = refs.map((r) => r.region === void 0 ? "(legacy)" : plainOrDescribed(r.region, "region")).join(", ");
|
|
77900
|
+
const orphanOne = pasteableCommand("cdkd state orphan", [{
|
|
77527
77901
|
value: stackName,
|
|
77528
|
-
hole: "stack"
|
|
77902
|
+
hole: "stack",
|
|
77903
|
+
opts: { plainIdent: true }
|
|
77529
77904
|
}, {
|
|
77530
77905
|
flag: "--stack-region",
|
|
77531
77906
|
hole: "region"
|
|
77532
|
-
}])
|
|
77907
|
+
}]);
|
|
77908
|
+
throw new Error(`Stack ${quotedOrDescribed(stackName, "stack name")} has state in multiple regions: ${regions}. Remove cdkd's record for ONE region with the command below (fill in the region), or run destroy from a CDK app whose env.region matches one of them.` + withheldTargetClause(orphanOne, "stack", "cdkd state orphan", "This stack's name") + `\nRemove one record with: ${orphanOne.command}`);
|
|
77533
77909
|
}
|
|
77534
77910
|
const stateResult = await stateBackend.getState(stackName, stackTargetRegion);
|
|
77535
77911
|
if (!stateResult) {
|
|
@@ -79152,7 +79528,7 @@ async function resolveIdentifierValue(entry, ctx, deps) {
|
|
|
79152
79528
|
return entry.resolve(ctx);
|
|
79153
79529
|
} catch (stateOnlyError) {
|
|
79154
79530
|
if (entry.backfill && deps) return await entry.backfill(ctx, deps);
|
|
79155
|
-
if (carriesSecretMask(ctx.attributes[entry.field])) throw new
|
|
79531
|
+
if (carriesSecretMask(ctx.attributes[entry.field])) throw new RepairableRefusal(maskedIdentifierAttributeReason(entry.field, ctx.logicalId), importRepairCommand(ctx.logicalId));
|
|
79156
79532
|
throw stateOnlyError;
|
|
79157
79533
|
}
|
|
79158
79534
|
}
|
|
@@ -79167,25 +79543,19 @@ async function resolveIdentifierValue(entry, ctx, deps) {
|
|
|
79167
79543
|
* today and would never stop being blocked by a re-import.
|
|
79168
79544
|
*/
|
|
79169
79545
|
function maskedIdentifierAttributeReason(field, logicalId) {
|
|
79170
|
-
return `cdkd state holds only the redaction mask ('***') at attributes.${field} for ${isPasteableIdent(logicalId) ? logicalId : `this resource (its logical id is not a plain identifier; read it with 'cdkd state show')`}, and that attribute is the value cdkd export reads as this resource type's CloudFormation import identifier (${field}); nothing masked may reach the exported template, since CloudFormation would either refuse it at IMPORT or write it onto the live resource at the next update. The mask is what 'cdkd import' writes for a Cloud Control model key it could not certify as read-only — every key when cloudformation:DescribeType was unavailable. Re-deploying does NOT clear it. Repair the record with the command below, after granting cloudformation:DescribeType, or export the stack without this resource and adopt it into CloudFormation by hand. See https://github.com/go-to-k/cdkd/issues/2932
|
|
79546
|
+
return `cdkd state holds only the redaction mask ('***') at attributes.${field} for ${isPasteableIdent(logicalId) ? logicalId : `this resource (its logical id is not a plain identifier; read it with 'cdkd state show')`}, and that attribute is the value cdkd export reads as this resource type's CloudFormation import identifier (${field}); nothing masked may reach the exported template, since CloudFormation would either refuse it at IMPORT or write it onto the live resource at the next update. The mask is what 'cdkd import' writes for a Cloud Control model key it could not certify as read-only — every key when cloudformation:DescribeType was unavailable. Re-deploying does NOT clear it. Repair the record with the command below, after granting cloudformation:DescribeType, or export the stack without this resource and adopt it into CloudFormation by hand. See https://github.com/go-to-k/cdkd/issues/2932.`;
|
|
79171
79547
|
}
|
|
79172
79548
|
/**
|
|
79173
|
-
* The `cdkd import`
|
|
79174
|
-
*
|
|
79549
|
+
* The `cdkd import` command a redaction-mask refusal carries in
|
|
79550
|
+
* {@link BlockedResource.repair}, which `groupBlockedReasons` prints on the
|
|
79551
|
+
* row's one `Repair with:` line.
|
|
79175
79552
|
*
|
|
79176
|
-
*
|
|
79177
|
-
*
|
|
79178
|
-
*
|
|
79179
|
-
* `'
|
|
79180
|
-
*
|
|
79181
|
-
*
|
|
79182
|
-
* would have.
|
|
79183
|
-
*
|
|
79184
|
-
* That site is NOT routed here, deliberately: `export.ts` is one of the
|
|
79185
|
-
* go-to-k/cdkd#3436 own-copy gates the maintainer asked to land in a follow-up
|
|
79186
|
-
* PR rather than widen go-to-k/cdkd#3613. The fence carries an EXEMPTION naming
|
|
79187
|
-
* it, so this helper gains its second caller in the PR that closes the site —
|
|
79188
|
-
* and the exemption goes stale in the same commit.
|
|
79553
|
+
* Two refusals carry this remedy, and both build it here so there is one
|
|
79554
|
+
* spelling of its gate: `resolveIdentifierValue`'s masked-attribute refusal
|
|
79555
|
+
* (a `RepairableRefusal` beside `maskedIdentifierAttributeReason`'s prose) and
|
|
79556
|
+
* `buildImportPlan`'s resolved-identifier refusal (go-to-k/cdkd#3736). The
|
|
79557
|
+
* second used to spell it independently inside a prose `'...'` span with the
|
|
79558
|
+
* logical id interpolated (go-to-k/cdkd#3363's shape).
|
|
79189
79559
|
*
|
|
79190
79560
|
* The POSITIONAL is a hole on purpose, and the load-bearing half is what it is
|
|
79191
79561
|
* NOT: an earlier cut passed the LOGICAL ID there, producing a command that
|
|
@@ -79193,11 +79563,10 @@ function maskedIdentifierAttributeReason(field, logicalId) {
|
|
|
79193
79563
|
* check can see that — both spellings are equally well-formed to one — and only
|
|
79194
79564
|
* reading the command can.
|
|
79195
79565
|
*
|
|
79196
|
-
* It is a hole rather than a name because
|
|
79197
|
-
*
|
|
79198
|
-
* (`buildImportPlan` does have one,
|
|
79199
|
-
*
|
|
79200
|
-
* reason to grow two spellings here.)
|
|
79566
|
+
* It is a hole rather than a name because one caller,
|
|
79567
|
+
* `resolveIdentifierValue`, has no stack name in scope at all.
|
|
79568
|
+
* (`buildImportPlan` does have one, but filling it is a separate gating
|
|
79569
|
+
* question, and a second spelling here is what this helper exists to avoid.)
|
|
79201
79570
|
*/
|
|
79202
79571
|
function importRepairCommand(logicalId) {
|
|
79203
79572
|
const named = isPasteableIdent(logicalId);
|
|
@@ -79677,6 +80046,19 @@ async function assertCfnStackAbsent(cfnClient, stackName) {
|
|
|
79677
80046
|
}
|
|
79678
80047
|
}
|
|
79679
80048
|
/**
|
|
80049
|
+
* A resolver refusal that carries a repair command, so the `buildImportPlan`
|
|
80050
|
+
* catch can move it into {@link BlockedResource.repair} instead of the
|
|
80051
|
+
* message text.
|
|
80052
|
+
*/
|
|
80053
|
+
var RepairableRefusal = class extends Error {
|
|
80054
|
+
repair;
|
|
80055
|
+
constructor(message, repair) {
|
|
80056
|
+
super(message);
|
|
80057
|
+
this.name = "RepairableRefusal";
|
|
80058
|
+
this.repair = repair;
|
|
80059
|
+
}
|
|
80060
|
+
};
|
|
80061
|
+
/**
|
|
79680
80062
|
* Returns true when a resource type is non-importable BUT can be handled
|
|
79681
80063
|
* by the phase-2 CREATE path. Today this is exactly `Custom::*` and the
|
|
79682
80064
|
* untyped CDK form `AWS::CloudFormation::CustomResource` (both are
|
|
@@ -80183,7 +80565,8 @@ async function buildImportPlan(state, template, cfnClient, parentStackName, opti
|
|
|
80183
80565
|
blocked.push({
|
|
80184
80566
|
logicalId,
|
|
80185
80567
|
resourceType,
|
|
80186
|
-
reason: "could not resolve resource identifier: " + (err instanceof Error ? err.message : String(err))
|
|
80568
|
+
reason: "could not resolve resource identifier: " + (err instanceof Error ? err.message : String(err)),
|
|
80569
|
+
...err instanceof RepairableRefusal ? { repair: err.repair } : {}
|
|
80187
80570
|
});
|
|
80188
80571
|
continue;
|
|
80189
80572
|
}
|
|
@@ -80192,7 +80575,8 @@ async function buildImportPlan(state, template, cfnClient, parentStackName, opti
|
|
|
80192
80575
|
blocked.push({
|
|
80193
80576
|
logicalId,
|
|
80194
80577
|
resourceType,
|
|
80195
|
-
reason:
|
|
80578
|
+
reason: "the CloudFormation import identifier cdkd resolved for this resource is the redaction mask ('***'), so the exported template would declare the mask as the resource's identity — CloudFormation would either refuse it at IMPORT or write it onto the live resource at the next update. cdkd state holds only the mask where the identifier should be (a masked attribute, or a masked physical id). Repair the record with the command below, granting cloudformation:DescribeType first if the import warned that it could not read the schema, or export the stack without this resource and adopt it into CloudFormation by hand. See https://github.com/go-to-k/cdkd/issues/2932.",
|
|
80579
|
+
repair: importRepairCommand(logicalId)
|
|
80196
80580
|
});
|
|
80197
80581
|
continue;
|
|
80198
80582
|
}
|
|
@@ -80241,10 +80625,29 @@ function groupBlockedReasons(blocked) {
|
|
|
80241
80625
|
resourceType: b.resourceType,
|
|
80242
80626
|
reasons: []
|
|
80243
80627
|
};
|
|
80244
|
-
|
|
80628
|
+
const text = displaySafe(b.reason);
|
|
80629
|
+
entry.reasons.push(b.repair === void 0 ? text : `${text}\nRepair with: ${b.repair}`);
|
|
80245
80630
|
byResource.set(b.logicalId, entry);
|
|
80246
80631
|
}
|
|
80247
|
-
return [...byResource].map(([logicalId, { resourceType, reasons }]) =>
|
|
80632
|
+
return [...byResource].map(([logicalId, { resourceType, reasons }]) => {
|
|
80633
|
+
const header = `${blockedRowId(logicalId)} (${blockedRowType(resourceType)})`;
|
|
80634
|
+
return reasons.length === 1 ? ` - ${header}: ${reasons[0]}` : ` - ${header}:\n${reasons.map((r) => ` - ${r}`).join("\n")}`;
|
|
80635
|
+
});
|
|
80636
|
+
}
|
|
80637
|
+
/**
|
|
80638
|
+
* A blocked row's identifiers come from the synthesized template's keys and
|
|
80639
|
+
* print beside reasons that end in a labelled `Repair with:` line, so the row
|
|
80640
|
+
* names them only in a shape that cannot forge that line — by a newline, or by
|
|
80641
|
+
* interior padding that wraps on screen (go-to-k/cdkd#3736). A CloudFormation
|
|
80642
|
+
* logical id is always a plain identifier, and a type always matches
|
|
80643
|
+
* `BLOCKED_ROW_TYPE`, so a real template loses nothing.
|
|
80644
|
+
*/
|
|
80645
|
+
function blockedRowId(logicalId) {
|
|
80646
|
+
return isPasteableIdent(logicalId) ? logicalId : "a resource whose logical id is not a plain identifier";
|
|
80647
|
+
}
|
|
80648
|
+
const BLOCKED_ROW_TYPE = /^[A-Za-z0-9]+(?:::[A-Za-z0-9_@-]+)+$/;
|
|
80649
|
+
function blockedRowType(resourceType) {
|
|
80650
|
+
return BLOCKED_ROW_TYPE.test(resourceType) ? resourceType : "an unrecognized type";
|
|
80248
80651
|
}
|
|
80249
80652
|
/**
|
|
80250
80653
|
* Build the `ResourceIdentifier` map CloudFormation IMPORT expects in
|
|
@@ -99291,4 +99694,4 @@ function buildProgram() {
|
|
|
99291
99694
|
|
|
99292
99695
|
//#endregion
|
|
99293
99696
|
export { buildProgram };
|
|
99294
|
-
//# sourceMappingURL=program-
|
|
99697
|
+
//# sourceMappingURL=program-DP27UiVh.js.map
|