@go-to-k/cdkd 0.296.28 → 0.296.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{asg-provider-B3zcS87C.js → asg-provider-UKRukGI_.js} +3 -3
- package/dist/{asg-provider-B3zcS87C.js.map → asg-provider-UKRukGI_.js.map} +1 -1
- package/dist/cli.js +2 -2
- package/dist/{deploy-engine-D4FdwPCi.js → deploy-engine-Bt-8KvUj.js} +1913 -57
- package/dist/deploy-engine-Bt-8KvUj.js.map +1 -0
- package/dist/{iam-policy-targets-B61e5_Sk.js → iam-policy-targets-Cz2tPxXk.js} +2 -2
- package/dist/{iam-policy-targets-B61e5_Sk.js.map → iam-policy-targets-Cz2tPxXk.js.map} +1 -1
- package/dist/{iam-role-provider-0U4kMuzh.js → iam-role-provider-BBFYFBLx.js} +3 -3
- package/dist/{iam-role-provider-0U4kMuzh.js.map → iam-role-provider-BBFYFBLx.js.map} +1 -1
- package/dist/index.d.ts +121 -55
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/{neptune-provider-DF6Eh4Tl.js → neptune-provider-B9InVgs6.js} +3 -3
- package/dist/{neptune-provider-DF6Eh4Tl.js.map → neptune-provider-B9InVgs6.js.map} +1 -1
- package/dist/{program-v_QNBjtZ.js → program-CN7Dqb3j.js} +513 -30
- package/dist/program-CN7Dqb3j.js.map +1 -0
- package/dist/{provider-classes-wbKBBEol.js → provider-classes-eEgFT-Vt.js} +196 -22
- package/dist/provider-classes-eEgFT-Vt.js.map +1 -0
- package/dist/{rds-provider-BfQsw4hw.js → rds-provider-DgbVxaPP.js} +3 -3
- package/dist/{rds-provider-BfQsw4hw.js.map → rds-provider-DgbVxaPP.js.map} +1 -1
- package/dist/{version-B0JEGOLV.js → version-DyV_xwRX.js} +2 -2
- package/dist/{version-B0JEGOLV.js.map → version-DyV_xwRX.js.map} +1 -1
- package/package.json +1 -1
- package/dist/deploy-engine-D4FdwPCi.js.map +0 -1
- package/dist/program-v_QNBjtZ.js.map +0 -1
- package/dist/provider-classes-wbKBBEol.js.map +0 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { a as runWithStackAwsClients, i as resetAwsClients, o as setAwsClients, t as AwsClients } from "./aws-clients-CnmtbrxD.js";
|
|
2
2
|
import { A as UNRENDERABLE, B as stringifyJsonPayload, D as SAFE_MSG_ALTERED_CHAR, F as displayStackName, I as isPasteableIdent, M as displayAwsMessage, N as displayIdent, O as SECRET_REF_MAX_CODE_POINTS, P as displaySafe, R as plainIdentOr, T as withStackName, V as truncateCodePoints, _ as derivesPatternBName, a as getLogger, f as getLiveRenderer, h as PATTERN_B_RESOURCE_TYPES, j as cutMarker, k as STACK_REF_MAX_CODE_POINTS, l as runStackBuffered, m as PATTERN_B_NAME_PROPERTIES, o as isStdoutReservedForPayload, p as PATTERN_B_NAME_OPTIONS, r as safeStringify, s as reserveStdoutForPayload, t as describeAwsFailure, v as explicitNamePropertyFor, w as withSkipPrefix, y as generateResourceName, z as safeMsg } from "./aws-failure-text-BaWeCWRz.js";
|
|
3
|
-
import { $
|
|
3
|
+
import { $n as isAmbiguousOutcomeError, $t as credentialFingerprint, Bn as withheldTargetClause, D as VALUE_NOT_SHOWN, Dn as TIMEOUT_FLAG_RESOURCE_TYPE, E as assertRegionMatch, En as withErrorHandling, Ft as buildLockContentionMessage, G as runDeleteAttempt, Hn as setPasteableVerbFlags, Ht as CUSTOM_RESOURCE_RESPONSE_PREFIX, In as plainOrDescribed, It as forceQuitRecoveryClause, Jt as setPasteableAwsProfile, Kt as producerCoordinateKey, Ln as quotedOrDescribed, Lt as formatLockExpiry, Nn as isInertUnquoted, Nt as UNREPRODUCIBLE_LOCK_CLAUSE, P as remedyLogicalId, Pn as pasteableCommand, Pt as buildForceUnlockCommand, Qt as clientDefaultsFor, Rn as shellBoundedDisplay, Rt as formatLockOperation, Sn as SynthesisError, T as RESOURCE_NOT_FOUND, Tn as normalizeAwsError, Ut as DEFAULT_STATE_PREFIX, Vn as setPasteableRunFlags, Wt as injectiveKey, Xt as ambientClientDefaults, Yt as withPasteableAwsProfile, Z as isAwsCliLiteral, Zt as ambientCredentialConfig, _n as ResourceTimeoutError, ar as isMarkedNonRetryable, bn as StackTerminationProtectionError, cn as IntrinsicResolutionRefusalError, en as AccountIdUnavailableError, ft as logicalIdShown, gn as ProvisioningError, hn as PartialFailureError, in as CrossAccountSecretRefusalError, it as isInterruptedWaitError, jn as commandHole, kn as SHELL_ACTIVE_WHY, ln as LocalInvokeBuildError$1, mn as NestedStackChildDirectDestroyError, mt as resourceTypeShown, n as RESOLVED_PREVIOUS_PRINCIPAL_KEYS, nn as CdkdError, nr as isTransientServerError, nt as endCommandInterruptScope, on as DeployCancelledError, or as isThrottlingError, pn as MalformedProducerRecordRefusalError, qt as producerRecordKey, rr as retryClassificationText, rt as interruptWatchListenerCount, s as readRecordedPrincipals, sn as DynamicReferenceRegionAmbiguousError, sr as markNonRetryable, t as IAM_PRINCIPAL_NAME, tr as isRetryableTransientError, tt as beginCommandInterruptScope, un as LocalStartServiceError, vn as ResourceUpdateNotSupportedError, yn as StackHasActiveImportsError, zn as shellQuote, zt as formatLockOwner } from "./iam-policy-targets-Cz2tPxXk.js";
|
|
4
4
|
import { n as awsClientDefaults, r as getAssumedRoleCredentials, u as formatAuthority } from "./aws-client-defaults-D0q0z4dG.js";
|
|
5
|
-
import { $ as gray, $a as prefetchCreateOnlyPropertyPaths, $i as refuseMalformedOutputs, $o as wholeStringLeavesOf, $r as getAccountInfo, $s as partitionSensitiveEnv, A as perType, Aa as NO_CC_HANDLERS_REASON, Ac as decodeListingKey, Ai as malformedLocalResourceEntriesWarning, An as buildFinalSnapshotIdentifier, Ao as shareLogOnlyValues, Ar as poisonRenderedSpellingsCollidingIn, As as rewriteTemplateAssetReferences, Bc as hasPlainPrototype, Bi as malformedResourceEntriesWarning, Bn as formatDestructiveChange, Bo as isUncertifiedBaselineMaskPosition, Br as AWS_CREDENTIAL_ENV_KEYS, Bs as validateContainerRepoName, Bt as planRollback, C as noEchoComparisonForTemplate, Ca as unreadableOrphanRecords, Cc as ssmResolvedValueType, Ci as hasReadableResources, Cn as maskEventTextWithBoundBags, Co as createUnionSecretMasker, Cs as AssetPublisher, Ct as isHandledOrphan, D as recordedProtectionNote, Dc as findLargeInlineResources, Di as malformedExportNamesWarning, Dn as extractDeploymentEventError, Do as printingCorpusOf, Dr as DiffCalculator, Ds as buildAssetRedirectMap, Dt as sameJournaledOrphans, E as recordedProtectionEvidence, Ea as findActionableSilentDrops, Ec as MIGRATE_TMP_PREFIX, Ei as malformedDriftResourcePropertiesWarning, En as stateSecretNameNeedles, Eo as logOnlyValueCount, Es as WorkGraph, Et as makeForeignHolderScan, Fa as isStatefulRecreateTargetForReplace, Fc as AssemblyReader, Fi as malformedOrphansRefusalMessage, Fn as refusesFinalSnapshot, Fo as markSameGenerationBag, Fr as assertFlagRoleArn, Fs as getBootstrapMarkerKey, Ft as recordAfterRollbackUpdate, Gc as displayAssemblyPath, Gi as previewableOrphanRecords, Gn as withCreateTokenLedger, Gs as describeDockerExecFailure, Gt as seedsDeleteFirstGuard, Hc as ownValue, Hi as malformedResourcesWarning, Ho as identityKeyFor, Hr as callerEnvCredentials, Hs as buildDockerImage, Ht as recordUnderIdIsNotOwn, Ia as isStatefulRecreateTargetSync, Ic as StageLoadError, Ii as malformedOrphansWarning, In as unsupportedFinalSnapshotError, Io as redactSecretsForState, Ir as assertSendableRoleArn, Is as isCrossRegionRedirect, It as demoteSupersededOrphans, Ji as refuseMalformedOrphanRecords, Jo as recordMaskOnlyValue, Js as finchSecretArgvRefusal, Kc as renderAssemblyPathEscape, Ki as refuseDivergentRecordRegionForDestroy, Ko as carriesSecretMask, Ks as describeDockerFailure, Kt as orphanDeleteNeedsIdentity, La as renderStatefulReason, Lc as processStackMessages, Li as malformedOutputsRefusalMessage, Ln as maskingRetryLogger, Lo as scrubResourceRecord, Lr as explicitRoleArnOrThrow, Ls as parseBootstrapMarker, Lt as isJournaledOrphan, Ma as findReplacedReadersOfRecreateTargets, Mc as PARTITION_TABLE, Mi as malformedOrphanRecordsRefusalMessage, Mn as createPreDeleteFinalSnapshot, Mo as errorCauseChain, Mr as producerRegionsFromState, Ms as BOOTSTRAP_MARKER_PREFIX, Na as shownType, Nc as canonicalizeRegion, Ni as malformedOrphanRecordsWarning, Nn as effectiveDeletionPolicy, No as maskSecretsInError, Nr as regionLessSecretName, Ns as assertAssetBucketRegion, Nt as withStackRecords, O as PROTECTION_PROPERTY_BY_TYPE, Oa as unwrittenCreateOnlyReplacement, Oc as uploadCfnTemplate, Oi as malformedExportSourceWarning, On as ATOMIC_FINAL_SNAPSHOT_TYPES, Oo as recordLogOnlyParameterValue, Or as INTRINSIC_KEYS, Os as createAssetRedirectResolver, Ot as replayFailedOperations, Pa as MULTI_REGION_RECREATE_BLOCKED_TYPES, Pc as derivePartitionAndUrlSuffix, Pi as malformedOrphanRowsKeptWarning, Pn as isFinalSnapshotError, Po as maskSecretsInText, Pr as applyRoleArnIfSet, Ps as ensureAssetStorage, Pt as removeProtectionTypeList, Q as cyan, Qi as refuseMalformedOrphansForOrphan, Qo as recordProvenPublicExpression, Qr as parameterTypeMayLoseSecretIdentity, Qs as isMalformedEnvKey, Rc as defineOwnKey, Ri as malformedOutputsWarning, Rn as constructPathOf, Ro as DYNAMIC_REFERENCE_TOKEN_SCAN, Rr as isIamRoleArn, Rs as readBootstrapMarkerBody, Rt as isReplacementOrphan, S as noEchoAttributeNamesOf, Sa as unpreviewableOrphanRecords, Sc as warnDeprecatedNoPrefixCliFlag, Si as hasReadableOutputs, Sn as journaledOrphanPrintingBag, So as carryLogOnlyValues, Ss as shouldRetainResource, St as dropFailedHint, T as noEchoParameterNamesOf, Ta as withheldAccountClause, Tc as CFN_TEMPLATE_URL_LIMIT, Ti as isReadableResourceEntry, Tn as secretNamePrintingBag, To as literalSplitDelimitersOf, Ts as stringifyValue, Tt as loadJournaledOrphans, Uc as absoluteAssemblyPathEscape, Ui as malformedScrubResourceEntriesRefusalMessage, Un as ledgerForStack, Uo as inheritNestedStackParameterAssociations, Ur as envCredentialsAreAssumedRole, Us as resolveDockerContextDirectory, Ut as replacementNeverSwapped, Vc as nullPrototypeRecord, Vi as malformedResourcePropertiesWarning, Vn as RollbackInlinePolicyWriters, Vo as pathCrossesDottedKey, Vr as applyCallerIdentityCredentials, Vs as buildDenyExternalAccessPolicy, Vt as recheckFailedPlan, Wc as describeFileReadFailure, Wi as malformedStateRefusalMessage, Wo as recordNestedStackParameterExpressions, Ws as describeDockerCapturedOutput, Wt as resolveReplacementOldType, X as createReadOnlyAttributeHealerFactory, Xi as refuseMalformedOrphans, Xo as recordNoEchoAttributeValues, Xr as coerceParameterTypedValue, Xs as getDockerCmd, Y as formatResourceLine, Yc as resolveBucketRegion, Yi as refuseMalformedOrphanRecordsForDestroy, Yo as recordMaskOnlyValuesIn, Ys as formatDockerLoginError, Yt as inheritProducerRegions, Z as bold, Zi as refuseMalformedOrphansForDestroy, Zo as recordNoEchoParameterFreshValue, Zr as isUnboundTemplateParameter, Zs as isDockerClientEnvKey, _ as makeCanonicalizePropertiesFn, _a as repairMalformedOrphansForReadOnly, _c as resolveSkipPrefix, _i as UNREADABLE_RESOURCES_MAP_ROW, _n as isExportAliasCollision, _r as deleteSkipReason, _s as importableOutputKeys, _t as revertedNestedRowIds, a as findNestedTemplateTreeDefect, aa as refuseMalformedResourceEntriesForImport, ac as escapeRegExp, ai as AWS_NO_VALUE, an as displayTextOrWithheld, ar as isCustomResource, as as isSingleDynamicReferenceToken, at as reachableDivergentParameters, b as serviceTokenBlockingReason, ba as repairMalformedResourcePropertiesForReadOnly, bc as resolveUseCdkBootstrapAssets, bi as displayLogicalId, bn as DEFAULT_RESOURCE_WARN_AFTER_MS, bo as valueAtCoordinate, bs as orphansAfterRollback, bt as withNestedStackContext, c as renderNestedTemplateTreeDefect, ca as refuseMalformedResourcePropertiesForDestroy, cc as getDockerImageBySourceHash, ci as refStateLookupFromResource, cn as secretBearingStateKeyWarning, co as canonicalCoordinates, cr as readsNoEchoDeleteValues, cs as S3StateBackend, ct as planOrphanAdoption, d as conditionInputsFrom, da as refuseMalformedResourcePropertiesForOrphan, dc as getDefaultStateBucketName, di as parameterInputsFor, dn as exportNameNoEchoParameters, do as maskReadbackAtCoordinates, dr as withPrintingSecrets, ds as acceptedCreateOnlyDropsOf, dt as displacedPhysicalIdShown, ea as refuseMalformedOutputsForDestroy, ec as redactDockerArgvValues, ei as isImpossibleEmptyStoredAttribute, en as updatePartialMessage, eo as templateResourceTypes, es as STATE_SOURCED_BASELINE_RULES, et as green, f as parentSuppliedValues, fa as refuseMalformedResourcesForDeploy, fc as getLegacyStateBucketName, fn as exportNameSecretExposure, fo as maskWholeValue, fr as CloudControlProvider, fs as describeRegionValueKind, ft as dropSettledNestedJournals, g as mergeNoChangeOutputs, ga as repairMalformedOrphanRecordsForReadOnly, gc as resolveCaptureObservedState, gi as UNREADABLE_ORPHANS_CONTAINER_ROW, gn as collectPublishedOutputNames, go as noEchoOutputsComparison, gr as deleteIndeterminateGuards, gs as hasUnverifiableParameterRefusal, h as keptWholeReasonText, ha as refuseMalformedState, hc as resolveAutoAssetStorage, hi as STATE_RESOURCES_MALFORMED, hn as collectDeclaredOutputNames, ho as noEchoLeavesOf, hr as UNSPECIFIED_SKIP_REASON, hs as hasReasonlessBaselineRefusal, ht as recordDisplacedSkips, i as childTemplateLoader, ia as refuseMalformedResourceEntriesForDestroy, ic as warnFinchArgvExposure, ii as keepsSecretReferenceToken, in as WITHHELD_NAME_DISPLAY, ir as ccBrokenReason, is as WHOLE_DYNAMIC_REFERENCE_PATTERN, it as namesAnyDeclaredParameter, j as readProtection, ja as hasNoCloudControlHandlers, jc as expectedOwnerParam, ji as malformedLocalResourcesWarning, jn as ccRoutedFinalSnapshotError, jo as createSecretMasker, jr as classifyReplaySecretRegion, js as AssetModeResolver, jt as destroyStackRecordsView, k as isProtectionValueActive, kc as CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION, ki as malformedLocalOutputsWarning, kn as PRE_DELETE_SNAPSHOT_TYPES, ko as recordLogOnlyValue, kr as IntrinsicFunctionResolver, ks as loadPublishableAssetManifest, kt as replayRollback, l as templateIdentity, la as refuseMalformedResourcePropertiesForDrift, lc as Synthesizer, ln as secretSafeKeyDisplay, lo as isMarkedCoordinate, lr as isCustomResourceType$1, ls as rebuildClientForBucketRegion, lt as NESTED_PENDING_PARENT_REASON, m as isSecretBearingReferenceString, ma as refuseMalformedResourcesForExport, mc as resolveApp, mi as STATE_REGION_DIVERGED, mn as noEchoParameterValueSeed, mo as noEchoCoordinatesOf, ms as hasReadableExportSet, mt as nestedChildStackName$1, n as IMPLICIT_DELETE_DEPENDENCIES, na as refuseMalformedResourceEntries, nc as runDockerForeground, ni as carriesFetchableDynamicReference, nn as DeploymentEventsReader, no as withRetry, nr as CC_BROKEN_REASON, ns as STATE_SOURCED_READBACK_RULES, nt as yellow, o as isAbsoluteAssetPath, oa as refuseMalformedResourceEntriesForImportSave, oc as stripControlChars, oi as cfnRefValueFromPhysicalId, on as exportAliasCollisionScrubWarning, oo as DagBuilder, or as wouldReturnToSdkProvider, os as LockManager, ot as resourcesNamingDeclaredParameter, p as readRecordedConditionVerdicts, pa as refuseMalformedResourcesForDestroy, pc as loadCdkJson, pi as JSON_LISTING_HOLE_VALUE, pn as isWholeDynamicReferenceValue, po as maskedLeafCoordinatesOf, pr as slowCcOperationTimeoutMs, ps as exportNamesCarriedFrom, qc as resolveAssemblyPath, qo as provenPublicValue, qs as dockerSpawnEnvWithSensitive, qt as findNestedStackTypeChanges, r as computeImplicitDeleteEdges, ra as refuseMalformedResourceEntriesForDeploy, rc as runDockerStreaming, ri as isNamelessDynamicReferenceError, rn as DeploymentEventsStore, rr as ProviderRegistry, rs as TEMPLATE_SOURCED_RULES, rt as computeParameterTaint, s as listNestedTemplateRows, sa as refuseMalformedResourceEntriesForOrphan, sc as AssetManifestLoader, si as isStalePlaceholderArnAttribute, sn as secretBearing, so as TemplateParser, sr as TemplateNoEchoReresolver, ss as isLockInfoExpired, st as makeSiblingClaimReader, t as DeployEngine, ta as refuseMalformedResourceAttributesForOrphan, tc as redactedDockerCause, ti as carriesDynamicReference, tn as updatePartialReason, to as describeTypeWithThrottleRetry, ts as STATE_SOURCED_CROSS_GENERATION_RULES, tt as red, u as conditionFingerprint, ua as refuseMalformedResourcePropertiesForExport, uc as synthesisStatusMessage, ui as withSharedDrainBudget, un as carriedExportAliasExposure, uo as maskAtCoordinates, us as splitImportedOps, ut as displacedOpClause, v as deferredServiceTokenWarning, va as repairMalformedOutputsForReadOnly, vc as resolveStateBucketWithDefault, vi as accountArgs, vn as bindingSkippedOutputs, vo as readbackPathFor, vs as importableOutputs, vt as withNestedRevertRun, w as noEchoExactEchoLeavesOf, wa as unreadableResourceEntries, wc as CFN_TEMPLATE_BODY_LIMIT, wi as isReadableOrphanRecord, wn as orphanRecordsPrintingBag, wo as hasMaskableValues, ws as isSensitiveAttributeName, wt as journaledOrphanLines, x as withResourceDeadline, xa as repairMalformedResourcesForReadOnly, xc as stateBucketExistenceConfirmed, xi as hasReadableOrphans, xn as completedReplayEntries, xo as liveMatchesUnresolvedTokenFrame, xs as orphansCarriedFrom, xt as deleteJournaledOrphans, y as findServiceTokenRefusals, ya as repairMalformedResourceEntriesForReadOnly, yc as resolveStateBucketWithDefaultAndSource, yi as deployRefusesOrphanRowsReason, yn as DEFAULT_RESOURCE_TIMEOUT_MS, yo as readsNoEchoSource, yr as isWaitAbandonedError, ys as isReadableBag, zc as hasOwnKey, zi as malformedRenderedContainersWarning, zn as findDestructiveChanges, zo as dynamicReferenceTokens, zr as sendableAssumeRoleCommand, zs as validateAssetBucketName, zt as planFailedOps } from "./deploy-engine-D4FdwPCi.js";
|
|
6
|
-
import { t as getCdkdVersion } from "./version-
|
|
5
|
+
import { $c as nullPrototypeRecord, $o as provenPublicValue, $s as buildDenyExternalAccessPolicy, $t as findNestedStackTypeChanges, A as noEchoExactEchoLeavesOf, Aa as unreadableResourceEntries, Ac as resolveStateBucketWithDefault, Ai as isReadableOrphanRecord, An as orphanRecordsPrintingBag, Ao as hasMaskableValues, As as importableOutputs, At as journaledOrphanLines, Ba as MULTI_REGION_RECREATE_BLOCKED_TYPES, Bc as uploadCfnTemplate, Bi as malformedOrphanRowsKeptWarning, Bn as isFinalSnapshotError, Bo as maskSecretsInText, Br as applyRoleArnIfSet, Bs as createAssetRedirectResolver, Bt as removeProtectionTypeList, C as recordRetainedForReadoption, Ca as repairMalformedOrphansForReadOnly, Cc as getDefaultStateBucketName, Ci as UNREADABLE_RESOURCES_MAP_ROW, Cn as isExportAliasCollision, Cr as deleteSkipReason, Cs as acceptedCreateOnlyDropsOf, Ct as revertedNestedRowIds, D as withResourceDeadline, Da as repairMalformedResourcesForReadOnly, Dc as resolveAutoAssetStorage, Di as hasReadableOrphans, Dn as completedReplayEntries, Do as liveMatchesUnresolvedTokenFrame, Ds as hasReasonlessBaselineRefusal, Dt as deleteJournaledOrphans, E as serviceTokenBlockingReason, Ea as repairMalformedResourcePropertiesForReadOnly, Ec as resolveApp, Ei as displayLogicalId, En as DEFAULT_RESOURCE_WARN_AFTER_MS, Eo as valueAtCoordinate, Es as hasReadableExportSet, Et as withNestedStackContext, F as isProtectionValueActive, Fc as ssmResolvedValueType, Fi as malformedLocalOutputsWarning, Fn as PRE_DELETE_SNAPSHOT_TYPES, Fo as recordLogOnlyValue, Fr as IntrinsicFunctionResolver, Fs as AssetPublisher, Ft as replayRollback, Gc as canonicalizeRegion, Gi as malformedRenderedContainersWarning, Gn as findDestructiveChanges, Go as dynamicReferenceTokens, Gr as sendableAssumeRoleCommand, Gs as assertAssetBucketRegion, Gt as planFailedOps, Ha as isStatefulRecreateTargetSync, Hc as decodeListingKey, Hi as malformedOrphansWarning, Hn as unsupportedFinalSnapshotError, Ho as redactSecretsForState, Hr as assertSendableRoleArn, Hs as rewriteTemplateAssetReferences, Ht as demoteSupersededOrphans, I as perType, Ia as NO_CC_HANDLERS_REASON, Ic as CFN_TEMPLATE_BODY_LIMIT, Ii as malformedLocalResourceEntriesWarning, In as buildFinalSnapshotIdentifier, Io as shareLogOnlyValues, Ir as poisonRenderedSpellingsCollidingIn, Is as isSensitiveAttributeName, Jc as StageLoadError, Ji as malformedResourcesWarning, Jo as identityKeyFor, Jr as callerEnvCredentials, Js as isCrossRegionRedirect, Jt as recordUnderIdIsNotOwn, Kc as derivePartitionAndUrlSuffix, Ki as malformedResourceEntriesWarning, Kn as formatDestructiveChange, Ko as isUncertifiedBaselineMaskPosition, Kr as AWS_CREDENTIAL_ENV_KEYS, Ks as ensureAssetStorage, Kt as planRollback, L as readProtection, La as hasNoCloudControlHandlers, Lc as CFN_TEMPLATE_URL_LIMIT, Li as malformedLocalResourcesWarning, Ln as ccRoutedFinalSnapshotError, Lo as createSecretMasker, Lr as classifyReplaySecretRegion, Ls as stringifyValue, Lt as destroyStackRecordsView, M as recordedProtectionEvidence, Ma as findActionableSilentDrops, Mc as resolveUseCdkBootstrapAssets, Mi as malformedDriftResourcePropertiesWarning, Mn as stateSecretNameNeedles, Mo as logOnlyValueCount, Ms as orphansAfterRollback, Mt as makeForeignHolderScan, N as recordedProtectionNote, Nc as stateBucketExistenceConfirmed, Ni as malformedExportNamesWarning, Nn as extractDeploymentEventError, No as printingCorpusOf, Nr as DiffCalculator, Ns as orphansCarriedFrom, Nt as sameJournaledOrphans, O as noEchoAttributeNamesOf, Oa as unpreviewableOrphanRecords, Oc as resolveCaptureObservedState, Oi as hasReadableOutputs, On as journaledOrphanPrintingBag, Oo as carryLogOnlyValues, Os as hasUnverifiableParameterRefusal, Ot as dropFailedHint, P as PROTECTION_PROPERTY_BY_TYPE, Pa as unwrittenCreateOnlyReplacement, Pc as warnDeprecatedNoPrefixCliFlag, Pi as malformedExportSourceWarning, Pn as ATOMIC_FINAL_SNAPSHOT_TYPES, Po as recordLogOnlyParameterValue, Pr as INTRINSIC_KEYS, Ps as shouldRetainResource, Pt as replayFailedOperations, Qc as hasPlainPrototype, Qi as refuseDivergentRecordRegionForDestroy, Qo as carriesSecretMask, Qs as validateContainerRepoName, Qt as orphanDeleteNeedsIdentity, Ra as findReplacedReadersOfRecreateTargets, Rc as MIGRATE_TMP_PREFIX, Ri as malformedOrphanRecordsRefusalMessage, Rn as createPreDeleteFinalSnapshot, Ro as errorCauseChain, Rr as producerRegionsFromState, Rs as WorkGraph, S as keptForReadoption, Sa as repairMalformedOrphanRecordsForReadOnly, Sc as synthesisStatusMessage, Si as UNREADABLE_ORPHANS_CONTAINER_ROW, Sn as collectPublishedOutputNames, So as noEchoOutputsComparison, Sr as deleteIndeterminateGuards, Ss as splitImportedOps, T as findServiceTokenRefusals, Ta as repairMalformedResourceEntriesForReadOnly, Tc as loadCdkJson, Ti as deployRefusesOrphanRowsReason, Tn as DEFAULT_RESOURCE_TIMEOUT_MS, To as readsNoEchoSource, Tr as isWaitAbandonedError, Ts as exportNamesCarriedFrom, Ua as renderStatefulReason, Uc as expectedOwnerParam, Ui as malformedOutputsRefusalMessage, Un as maskingRetryLogger, Uo as scrubResourceRecord, Ur as explicitRoleArnOrThrow, Us as AssetModeResolver, Ut as isJournaledOrphan, Va as isStatefulRecreateTargetForReplace, Vc as CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION, Vi as malformedOrphansRefusalMessage, Vn as refusesFinalSnapshot, Vo as markSameGenerationBag, Vr as assertFlagRoleArn, Vs as loadPublishableAssetManifest, Vt as recordAfterRollbackUpdate, Wc as PARTITION_TABLE, Wi as malformedOutputsWarning, Wn as constructPathOf, Wo as DYNAMIC_REFERENCE_TOKEN_SCAN, Wr as isIamRoleArn, Ws as BOOTSTRAP_MARKER_PREFIX, Wt as isReplacementOrphan, Xc as defineOwnKey, Xi as malformedStateRefusalMessage, Xo as recordNestedStackParameterExpressions, Xs as readBootstrapMarkerBody, Xt as resolveReplacementOldType, Yc as processStackMessages, Yi as malformedScrubResourceEntriesRefusalMessage, Yn as ledgerForStack, Yo as inheritNestedStackParameterAssociations, Yr as envCredentialsAreAssumedRole, Ys as parseBootstrapMarker, Yt as replacementNeverSwapped, Zc as hasOwnKey, Zi as previewableOrphanRecords, Zn as withCreateTokenLedger, Zs as validateAssetBucketName, Zt as seedsDeleteFirstGuard, _ as makeCanonicalizePropertiesFn, _a as refuseMalformedResourcePropertiesForOrphan, _c as escapeRegExp, _i as parameterInputsFor, _n as exportNameNoEchoParameters, _o as maskReadbackAtCoordinates, _r as withPrintingSecrets, _s as CrossPrefixScanCache, _t as displacedPhysicalIdShown, a as findNestedTemplateTreeDefect, aa as refuseMalformedOutputs, ac as dockerSpawnEnvWithSensitive, ai as getAccountInfo, al as resolveAssemblyPath, ao as prefetchCreateOnlyPropertyPaths, as as wholeStringLeavesOf, at as gray, ba as refuseMalformedResourcesForExport, bc as getDockerImageBySourceHash, bi as STATE_REGION_DIVERGED, bn as noEchoParameterValueSeed, bo as noEchoCoordinatesOf, bs as isAccessDenied, bt as nestedChildStackName$1, c as renderNestedTemplateTreeDefect, ca as refuseMalformedResourceEntries, cc as getDockerCmd, ci as carriesFetchableDynamicReference, cn as DeploymentEventsReader, co as withRetry, cr as CC_BROKEN_REASON, cs as STATE_SOURCED_READBACK_RULES, ct as yellow, d as conditionInputsFrom, da as refuseMalformedResourceEntriesForImport, dc as partitionSensitiveEnv, di as AWS_NO_VALUE, dn as displayTextOrWithheld, dr as isCustomResource, ds as isSingleDynamicReferenceToken, dt as reachableDivergentParameters, ea as refuseMalformedOrphanRecords, ec as buildDockerImage, el as ownValue, es as recordMaskOnlyValue, f as parentSuppliedValues, fa as refuseMalformedResourceEntriesForImportSave, fc as redactDockerArgvValues, fi as cfnRefValueFromPhysicalId, fn as exportAliasCollisionScrubWarning, fo as DagBuilder, fr as wouldReturnToSdkProvider, fs as LockManager, ft as resourcesNamingDeclaredParameter, g as mergeNoChangeOutputs, ga as refuseMalformedResourcePropertiesForExport, gc as warnFinchArgvExposure, gi as withSharedDrainBudget, gn as carriedExportAliasExposure, go as maskAtCoordinates, gs as CrossPrefixReadError, gt as displacedOpClause, h as keptWholeReasonText, ha as refuseMalformedResourcePropertiesForDrift, hc as runDockerStreaming, hn as secretSafeKeyDisplay, ho as isMarkedCoordinate, hr as isCustomResourceType$1, hs as rebuildClientForBucketRegion, ht as NESTED_PENDING_PARENT_REASON, i as childTemplateLoader, ia as refuseMalformedOrphansForOrphan, ic as describeDockerFailure, ii as parameterTypeMayLoseSecretIdentity, il as renderAssemblyPathEscape, is as recordProvenPublicExpression, it as cyan, j as noEchoParameterNamesOf, ja as withheldAccountClause, jc as resolveStateBucketWithDefaultAndSource, ji as isReadableResourceEntry, jn as secretNamePrintingBag, jo as literalSplitDelimitersOf, js as isReadableBag, jt as loadJournaledOrphans, k as noEchoComparisonForTemplate, ka as unreadableOrphanRecords, kc as resolveSkipPrefix, ki as hasReadableResources, kn as maskEventTextWithBoundBags, ko as createUnionSecretMasker, ks as importableOutputKeys, kt as isHandledOrphan, l as templateIdentity, la as refuseMalformedResourceEntriesForDeploy, lc as isDockerClientEnvKey, li as isNamelessDynamicReferenceError, ln as DeploymentEventsStore, lr as ProviderRegistry, ls as TEMPLATE_SOURCED_RULES, lt as computeParameterTaint, m as isSecretBearingReferenceString, ma as refuseMalformedResourcePropertiesForDestroy, mc as runDockerForeground, mi as refStateLookupFromResource, mn as secretBearingStateKeyWarning, mo as canonicalCoordinates, mr as readsNoEchoDeleteValues, ms as S3StateBackend, mt as planOrphanAdoption, n as IMPLICIT_DELETE_DEPENDENCIES, na as refuseMalformedOrphans, nc as describeDockerCapturedOutput, ni as coerceParameterTypedValue, nl as describeFileReadFailure, ns as recordNoEchoAttributeValues, nt as createReadOnlyAttributeHealerFactory, o as isAbsoluteAssetPath, oa as refuseMalformedOutputsForDestroy, oc as finchSecretArgvRefusal, oi as isImpossibleEmptyStoredAttribute, on as updatePartialMessage, oo as templateResourceTypes, os as STATE_SOURCED_BASELINE_RULES, ot as green, p as readRecordedConditionVerdicts, pa as refuseMalformedResourceEntriesForOrphan, pc as redactedDockerCause, pi as isStalePlaceholderArnAttribute, pn as secretBearing, po as TemplateParser, pr as TemplateNoEchoReresolver, ps as isLockInfoExpired, pt as makeSiblingClaimReader, qc as AssemblyReader, qi as malformedResourcePropertiesWarning, qn as RollbackInlinePolicyWriters, qo as pathCrossesDottedKey, qr as applyCallerIdentityCredentials, qs as getBootstrapMarkerKey, qt as recheckFailedPlan, r as computeImplicitDeleteEdges, ra as refuseMalformedOrphansForDestroy, rc as describeDockerExecFailure, ri as isUnboundTemplateParameter, rl as displayAssemblyPath, rs as recordNoEchoParameterFreshValue, rt as bold, s as listNestedTemplateRows, sa as refuseMalformedResourceAttributesForOrphan, sc as formatDockerLoginError, si as carriesDynamicReference, sl as resolveBucketRegion, sn as updatePartialReason, so as describeTypeWithThrottleRetry, ss as STATE_SOURCED_CROSS_GENERATION_RULES, st as red, t as DeployEngine, ta as refuseMalformedOrphanRecordsForDestroy, tc as resolveDockerContextDirectory, tl as absoluteAssemblyPathEscape, tn as inheritProducerRegions, ts as recordMaskOnlyValuesIn, tt as formatResourceLine, u as conditionFingerprint, ua as refuseMalformedResourceEntriesForDestroy, uc as isMalformedEnvKey, ui as keepsSecretReferenceToken, un as WITHHELD_NAME_DISPLAY, ur as ccBrokenReason, us as WHOLE_DYNAMIC_REFERENCE_PATTERN, ut as namesAnyDeclaredParameter, va as refuseMalformedResourcesForDeploy, vc as stripControlChars, vn as exportNameSecretExposure, vo as maskWholeValue, vr as CloudControlProvider, vs as applyCrossPrefixScan, vt as dropSettledNestedJournals, w as deferredServiceTokenWarning, wa as repairMalformedOutputsForReadOnly, wc as getLegacyStateBucketName, wi as accountArgs, wn as bindingSkippedOutputs, wo as readbackPathFor, ws as describeRegionValueKind, wt as withNestedRevertRun, xa as refuseMalformedState, xc as Synthesizer, xi as STATE_RESOURCES_MALFORMED, xn as collectDeclaredOutputNames, xo as noEchoLeavesOf, xr as UNSPECIFIED_SKIP_REASON, xs as isNotImplemented, xt as recordDisplacedSkips, ya as refuseMalformedResourcesForDestroy, yc as AssetManifestLoader, yi as JSON_LISTING_HOLE_VALUE, yn as isWholeDynamicReferenceValue, yo as maskedLeafCoordinatesOf, yr as slowCcOperationTimeoutMs, ys as crossPrefixDeniedWarning, za as shownType, zc as findLargeInlineResources, zi as malformedOrphanRecordsWarning, zn as effectiveDeletionPolicy, zo as maskSecretsInError, zr as regionLessSecretName, zs as buildAssetRedirectMap, zt as withStackRecords } from "./deploy-engine-Bt-8KvUj.js";
|
|
6
|
+
import { t as getCdkdVersion } from "./version-DyV_xwRX.js";
|
|
7
7
|
import { randomBytes, randomUUID } from "node:crypto";
|
|
8
8
|
import { CopyObjectCommand, CreateBucketCommand, DeleteBucketCommand, DeleteObjectsCommand, GetBucketLocationCommand, GetObjectCommand, HeadBucketCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchBucket, NotFound, PutBucketEncryptionCommand, PutBucketPolicyCommand, PutBucketVersioningCommand, PutObjectCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
|
|
9
9
|
import { GetRoleCommand, GetUserCommand } from "@aws-sdk/client-iam";
|
|
@@ -1306,6 +1306,14 @@ function createListCommand() {
|
|
|
1306
1306
|
|
|
1307
1307
|
//#endregion
|
|
1308
1308
|
//#region src/utils/interrupt-signals.ts
|
|
1309
|
+
const postCleanupListeners = /* @__PURE__ */ new WeakSet();
|
|
1310
|
+
function prependPostCleanupSigintListener(listener) {
|
|
1311
|
+
postCleanupListeners.add(listener);
|
|
1312
|
+
process.prependListener("SIGINT", listener);
|
|
1313
|
+
return () => {
|
|
1314
|
+
process.removeListener("SIGINT", listener);
|
|
1315
|
+
};
|
|
1316
|
+
}
|
|
1309
1317
|
function forwardSigtermToSigint() {
|
|
1310
1318
|
beginCommandInterruptScope();
|
|
1311
1319
|
try {
|
|
@@ -1333,7 +1341,7 @@ function watchCommandInterrupt(opts) {
|
|
|
1333
1341
|
}
|
|
1334
1342
|
let stacksInFlight = 0;
|
|
1335
1343
|
function gracefulOwnerArmed() {
|
|
1336
|
-
return process.listeners("SIGINT").filter((l) => l !== handler).length - interruptWatchListenerCount() > 0;
|
|
1344
|
+
return process.listeners("SIGINT").filter((l) => l !== handler && !postCleanupListeners.has(l)).length - interruptWatchListenerCount() > 0;
|
|
1337
1345
|
}
|
|
1338
1346
|
const handler = () => {
|
|
1339
1347
|
if (stacksInFlight > 0 && gracefulOwnerArmed()) {
|
|
@@ -1923,8 +1931,8 @@ function resolveRequireApproval(cliValue, logger, cdkJson = loadCdkJson()) {
|
|
|
1923
1931
|
throw new CdkdError(`cdk.json "requireApproval" must be one of ${REQUIRE_APPROVAL_VALUES.join(", ")}, got: ${displayIdent(typeof configured === "string" ? configured : JSON.stringify(configured))}`, "INVALID_REQUIRE_APPROVAL");
|
|
1924
1932
|
}
|
|
1925
1933
|
function createApprovalPrompter(options) {
|
|
1934
|
+
if (options.yes) return Object.assign(() => Promise.resolve(true), { autoApproves: true });
|
|
1926
1935
|
return (request) => {
|
|
1927
|
-
if (options.yes) return Promise.resolve(true);
|
|
1928
1936
|
return serializePrompt(() => getLiveRenderer().suspendWhile(async () => {
|
|
1929
1937
|
process.stdout.write(renderApprovalRequest(request));
|
|
1930
1938
|
return confirmOrRefuse("Do you wish to deploy these changes?", {
|
|
@@ -2396,7 +2404,7 @@ function collectCrossStackRefs(node, onRef) {
|
|
|
2396
2404
|
//#region src/provisioning/register-providers.ts
|
|
2397
2405
|
let providerClasses;
|
|
2398
2406
|
function loadProviderClasses() {
|
|
2399
|
-
providerClasses ??= import("./provider-classes-
|
|
2407
|
+
providerClasses ??= import("./provider-classes-eEgFT-Vt.js");
|
|
2400
2408
|
return providerClasses;
|
|
2401
2409
|
}
|
|
2402
2410
|
function registerAllProviders(registry, classes) {
|
|
@@ -2637,6 +2645,262 @@ function createPrefixMigrationGate(opts) {
|
|
|
2637
2645
|
};
|
|
2638
2646
|
}
|
|
2639
2647
|
|
|
2648
|
+
//#endregion
|
|
2649
|
+
//#region src/cli/commands/registry-release.ts
|
|
2650
|
+
async function releaseRegistryMarkerQuietly(backend, stackName, region, logger, known) {
|
|
2651
|
+
if (stackName.includes("~")) return;
|
|
2652
|
+
try {
|
|
2653
|
+
const released = known === void 0 ? await backend.releaseRegistryMarker(stackName, region) : await backend.releaseRegistryMarker(stackName, region, known);
|
|
2654
|
+
logger.debug(safeMsg`Stack registry marker: ${released}`);
|
|
2655
|
+
} catch (error) {
|
|
2656
|
+
logger.warn(safeMsg`Could not delete the stack registry marker of ${displayStackName(stackName)} ` + safeMsg`(${describeAwsFailure(error).summary}). It names this state prefix, which no longer ` + `records the stack, so a deploy under another prefix treats it as stale.`);
|
|
2657
|
+
}
|
|
2658
|
+
}
|
|
2659
|
+
|
|
2660
|
+
//#endregion
|
|
2661
|
+
//#region src/cli/commands/cross-prefix-gate.ts
|
|
2662
|
+
function deployStackRegion(stack, baseRegion) {
|
|
2663
|
+
return stack.region || baseRegion;
|
|
2664
|
+
}
|
|
2665
|
+
function createCrossPrefixDeployGate(opts) {
|
|
2666
|
+
return async (gateStackName, state) => {
|
|
2667
|
+
if (gateStackName !== opts.stackName) return;
|
|
2668
|
+
if (state !== void 0) return;
|
|
2669
|
+
const result = await opts.guard.firstDeploy(opts.stackName, opts.region);
|
|
2670
|
+
applyCrossPrefixScan(result, {
|
|
2671
|
+
stackName: opts.stackName,
|
|
2672
|
+
region: opts.region,
|
|
2673
|
+
bucket: opts.bucket,
|
|
2674
|
+
recovery: opts.recovery
|
|
2675
|
+
}, "deploy", ...reportOnce(result));
|
|
2676
|
+
};
|
|
2677
|
+
}
|
|
2678
|
+
const reported = /* @__PURE__ */ new WeakSet();
|
|
2679
|
+
function reportOnce(result) {
|
|
2680
|
+
const first = !reported.has(result);
|
|
2681
|
+
reported.add(result);
|
|
2682
|
+
return first ? [(message) => getLogger().warn(message), (message) => getLogger().info(message)] : [() => void 0, () => void 0];
|
|
2683
|
+
}
|
|
2684
|
+
function createCrossPrefixDestructiveGate(opts) {
|
|
2685
|
+
return async (stackName, _destructive, stage) => {
|
|
2686
|
+
const result = await opts.cache.full(stackName, opts.region);
|
|
2687
|
+
applyCrossPrefixScan(result, {
|
|
2688
|
+
stackName,
|
|
2689
|
+
region: opts.region,
|
|
2690
|
+
bucket: opts.bucket,
|
|
2691
|
+
recovery: opts.recovery
|
|
2692
|
+
}, stage === "late" ? "deploy-late-replace" : "deploy-destructive", ...reportOnce(result));
|
|
2693
|
+
};
|
|
2694
|
+
}
|
|
2695
|
+
function createCrossPrefixHolder(opts) {
|
|
2696
|
+
return async (stackName) => {
|
|
2697
|
+
const result = await opts.cache.full(stackName, opts.region);
|
|
2698
|
+
switch (result.kind) {
|
|
2699
|
+
case "found": return {
|
|
2700
|
+
kind: "unreadable",
|
|
2701
|
+
what: safeMsg`bucket ${opts.bucket} also records this stack under another state prefix (${displayIdent(result.prefixes[0])}), whose record may hold it`
|
|
2702
|
+
};
|
|
2703
|
+
case "in-progress": return {
|
|
2704
|
+
kind: "unreadable",
|
|
2705
|
+
what: safeMsg`bucket ${opts.bucket} assigns this stack to another state prefix (${displayIdent(result.prefix)}), where a deploy may be in progress`
|
|
2706
|
+
};
|
|
2707
|
+
case "failed": return {
|
|
2708
|
+
kind: "unreadable",
|
|
2709
|
+
what: safeMsg`the other state prefixes of bucket ${opts.bucket} could not be checked`,
|
|
2710
|
+
retryable: true
|
|
2711
|
+
};
|
|
2712
|
+
case "denied":
|
|
2713
|
+
reportOnce(result)[0](crossPrefixDeniedWarning({
|
|
2714
|
+
stackName,
|
|
2715
|
+
region: opts.region,
|
|
2716
|
+
bucket: opts.bucket
|
|
2717
|
+
}, result.error, result.stage));
|
|
2718
|
+
return;
|
|
2719
|
+
default: return;
|
|
2720
|
+
}
|
|
2721
|
+
};
|
|
2722
|
+
}
|
|
2723
|
+
function crossPrefixEngineOptions(opts) {
|
|
2724
|
+
const backend = opts.backend;
|
|
2725
|
+
return {
|
|
2726
|
+
...backend !== void 0 && { onFirstDeployLeftNoRecord: async (stackName) => {
|
|
2727
|
+
if (stackName !== opts.stackName) return;
|
|
2728
|
+
const known = await opts.guard.knownMarker?.(stackName, opts.region);
|
|
2729
|
+
await releaseRegistryMarkerQuietly(backend, stackName, opts.region, getLogger(), known);
|
|
2730
|
+
} },
|
|
2731
|
+
firstDeployGate: createCrossPrefixDeployGate({
|
|
2732
|
+
stackName: opts.stackName,
|
|
2733
|
+
region: opts.region,
|
|
2734
|
+
bucket: opts.bucket,
|
|
2735
|
+
recovery: opts.recovery,
|
|
2736
|
+
guard: opts.guard
|
|
2737
|
+
}),
|
|
2738
|
+
onDestructivePlan: createCrossPrefixDestructiveGate({
|
|
2739
|
+
region: opts.region,
|
|
2740
|
+
bucket: opts.bucket,
|
|
2741
|
+
recovery: opts.recovery,
|
|
2742
|
+
cache: opts.guard
|
|
2743
|
+
}),
|
|
2744
|
+
crossPrefixHolder: createCrossPrefixHolder({
|
|
2745
|
+
region: opts.region,
|
|
2746
|
+
bucket: opts.bucket,
|
|
2747
|
+
cache: opts.guard
|
|
2748
|
+
})
|
|
2749
|
+
};
|
|
2750
|
+
}
|
|
2751
|
+
function composeStateLoadedGates(crossPrefix, migration) {
|
|
2752
|
+
return async (stackName, state) => {
|
|
2753
|
+
await crossPrefix(stackName, state);
|
|
2754
|
+
if (migration) await migration(stackName, state);
|
|
2755
|
+
};
|
|
2756
|
+
}
|
|
2757
|
+
|
|
2758
|
+
//#endregion
|
|
2759
|
+
//#region src/state/stack-registry.ts
|
|
2760
|
+
function unwrapReadError(error) {
|
|
2761
|
+
return error instanceof CrossPrefixReadError ? error.cause : error;
|
|
2762
|
+
}
|
|
2763
|
+
function topLevelStackName(stackName) {
|
|
2764
|
+
return stackName.split("~")[0];
|
|
2765
|
+
}
|
|
2766
|
+
var CrossPrefixGuard = class {
|
|
2767
|
+
scan;
|
|
2768
|
+
backend;
|
|
2769
|
+
readOnly;
|
|
2770
|
+
markers = /* @__PURE__ */ new Map();
|
|
2771
|
+
answers = /* @__PURE__ */ new Map();
|
|
2772
|
+
constructor(backend, opts = {}) {
|
|
2773
|
+
this.backend = backend;
|
|
2774
|
+
this.readOnly = opts.readOnly === true;
|
|
2775
|
+
this.scan = opts.scan ?? new CrossPrefixScanCache(backend);
|
|
2776
|
+
}
|
|
2777
|
+
get target() {
|
|
2778
|
+
return this.scan.target;
|
|
2779
|
+
}
|
|
2780
|
+
full(stackName, region, when = "now") {
|
|
2781
|
+
const key = JSON.stringify([stackName, region]);
|
|
2782
|
+
let answer = this.answers.get(key);
|
|
2783
|
+
if (answer === void 0) {
|
|
2784
|
+
answer = this.evaluate(stackName, region, false, when);
|
|
2785
|
+
this.answers.set(key, answer);
|
|
2786
|
+
} else if (when === "now") this.scan.target.rank(stackName, region, "now");
|
|
2787
|
+
return answer;
|
|
2788
|
+
}
|
|
2789
|
+
firstDeploy(stackName, region) {
|
|
2790
|
+
const key = JSON.stringify([stackName, region]);
|
|
2791
|
+
const answer = this.evaluate(stackName, region, true, "now");
|
|
2792
|
+
this.answers.set(key, answer);
|
|
2793
|
+
return answer;
|
|
2794
|
+
}
|
|
2795
|
+
async knownMarker(stackName, region) {
|
|
2796
|
+
const read = this.markers.get(JSON.stringify([topLevelStackName(stackName), region]));
|
|
2797
|
+
if (read === void 0) return void 0;
|
|
2798
|
+
return read.catch(() => void 0);
|
|
2799
|
+
}
|
|
2800
|
+
marker(top, region, fresh = false) {
|
|
2801
|
+
const key = JSON.stringify([top, region]);
|
|
2802
|
+
let read = fresh ? void 0 : this.markers.get(key);
|
|
2803
|
+
if (read === void 0) {
|
|
2804
|
+
read = this.backend.getRegistryMarker(top, region);
|
|
2805
|
+
this.markers.set(key, read);
|
|
2806
|
+
}
|
|
2807
|
+
return read;
|
|
2808
|
+
}
|
|
2809
|
+
async evaluate(stackName, region, firstDeploy, when) {
|
|
2810
|
+
const top = topLevelStackName(stackName);
|
|
2811
|
+
const claimable = top === stackName && !this.readOnly;
|
|
2812
|
+
if (firstDeploy && claimable && !this.markers.has(JSON.stringify([top, region]))) {
|
|
2813
|
+
if (await this.claim(top, region) === "claimed") return { kind: "clear" };
|
|
2814
|
+
}
|
|
2815
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
2816
|
+
let marker;
|
|
2817
|
+
try {
|
|
2818
|
+
marker = await this.marker(top, region, attempt > 0);
|
|
2819
|
+
} catch (error) {
|
|
2820
|
+
return this.fallback(stackName, region, when, error);
|
|
2821
|
+
}
|
|
2822
|
+
if (marker === null) {
|
|
2823
|
+
if (firstDeploy) {
|
|
2824
|
+
if (!claimable) return { kind: "clear" };
|
|
2825
|
+
const claimed = await this.claim(top, region);
|
|
2826
|
+
if (claimed === "conflict") continue;
|
|
2827
|
+
if (claimed !== "claimed") return this.fallback(stackName, region, when, claimed.error);
|
|
2828
|
+
return { kind: "clear" };
|
|
2829
|
+
}
|
|
2830
|
+
const scanned = await this.scan.full(stackName, region, when);
|
|
2831
|
+
if (scanned.kind === "clear" && claimable) {
|
|
2832
|
+
if (await this.claim(top, region) === "conflict") continue;
|
|
2833
|
+
}
|
|
2834
|
+
return scanned;
|
|
2835
|
+
}
|
|
2836
|
+
if (marker.prefix === this.backend.prefix) return { kind: "clear" };
|
|
2837
|
+
let held;
|
|
2838
|
+
let locked;
|
|
2839
|
+
try {
|
|
2840
|
+
held = await this.backend.recordUnderPrefix(marker.prefix, stackName, region);
|
|
2841
|
+
locked = held === "holder" ? false : await this.backend.lockUnderPrefix(marker.prefix, top, region);
|
|
2842
|
+
} catch (error) {
|
|
2843
|
+
return isAccessDenied(error) ? {
|
|
2844
|
+
kind: "denied",
|
|
2845
|
+
error,
|
|
2846
|
+
stage: "probe"
|
|
2847
|
+
} : {
|
|
2848
|
+
kind: "failed",
|
|
2849
|
+
error
|
|
2850
|
+
};
|
|
2851
|
+
}
|
|
2852
|
+
if (held === "holder") return {
|
|
2853
|
+
kind: "found",
|
|
2854
|
+
prefixes: [marker.prefix]
|
|
2855
|
+
};
|
|
2856
|
+
if (locked) return {
|
|
2857
|
+
kind: "in-progress",
|
|
2858
|
+
prefix: marker.prefix
|
|
2859
|
+
};
|
|
2860
|
+
const stale = held === "empty" ? [marker.prefix] : [];
|
|
2861
|
+
const scanned = await this.scan.full(stackName, region, when);
|
|
2862
|
+
if (scanned.kind !== "clear") return scanned;
|
|
2863
|
+
const allStale = [.../* @__PURE__ */ new Set([...stale, ...scanned.stale ?? []])];
|
|
2864
|
+
const answer = {
|
|
2865
|
+
kind: "clear",
|
|
2866
|
+
...allStale.length > 0 && { stale: allStale }
|
|
2867
|
+
};
|
|
2868
|
+
if (!claimable) return answer;
|
|
2869
|
+
if (await this.claim(top, region, marker.etag) === "conflict") continue;
|
|
2870
|
+
return answer;
|
|
2871
|
+
}
|
|
2872
|
+
return {
|
|
2873
|
+
kind: "failed",
|
|
2874
|
+
error: new CrossPrefixReadError(`_cdkd-registry/${region}/${top}.json`, Object.assign(/* @__PURE__ */ new Error("the marker changed twice while cdkd was claiming it"), { name: "ConcurrentClaim" }))
|
|
2875
|
+
};
|
|
2876
|
+
}
|
|
2877
|
+
async claim(top, region, ifMatch) {
|
|
2878
|
+
try {
|
|
2879
|
+
const result = await this.backend.claimRegistryMarker(top, region, ifMatch);
|
|
2880
|
+
if (result === "claimed") this.markers.set(JSON.stringify([top, region]), Promise.resolve({
|
|
2881
|
+
prefix: this.backend.prefix,
|
|
2882
|
+
etag: ""
|
|
2883
|
+
}));
|
|
2884
|
+
return result;
|
|
2885
|
+
} catch (error) {
|
|
2886
|
+
return { error };
|
|
2887
|
+
}
|
|
2888
|
+
}
|
|
2889
|
+
async fallback(stackName, region, when, error) {
|
|
2890
|
+
if (!isAccessDenied(error) && !isNotImplemented(unwrapReadError(error))) return {
|
|
2891
|
+
kind: "failed",
|
|
2892
|
+
error
|
|
2893
|
+
};
|
|
2894
|
+
const scanned = await this.scan.full(stackName, region, when);
|
|
2895
|
+
return scanned.kind === "clear" ? {
|
|
2896
|
+
kind: "denied",
|
|
2897
|
+
error,
|
|
2898
|
+
stage: "registry",
|
|
2899
|
+
...scanned.stale && { stale: scanned.stale }
|
|
2900
|
+
} : scanned;
|
|
2901
|
+
}
|
|
2902
|
+
};
|
|
2903
|
+
|
|
2640
2904
|
//#endregion
|
|
2641
2905
|
//#region src/cli/commands/deploy.ts
|
|
2642
2906
|
async function deployCommand(stacks, options) {
|
|
@@ -2706,6 +2970,7 @@ Force-quit: stack locks may not be released. If the next run reports a lock, run
|
|
|
2706
2970
|
};
|
|
2707
2971
|
process.on("SIGINT", topLevelSigintHandler);
|
|
2708
2972
|
const unforwardSigterm = forwardSigtermToSigint();
|
|
2973
|
+
let preflightBackendForCleanup;
|
|
2709
2974
|
try {
|
|
2710
2975
|
logger.info(cyan(synthesisStatusMessage(app, "Synthesizing CDK app...")));
|
|
2711
2976
|
const synthesizer = new Synthesizer();
|
|
@@ -2721,6 +2986,7 @@ Force-quit: stack locks may not be released. If the next run reports a lock, run
|
|
|
2721
2986
|
};
|
|
2722
2987
|
const [result, statePrep] = await Promise.all([synthesizer.synthesize(synthOptions), statePrepPromise]);
|
|
2723
2988
|
const { stateBucket, preflightStateBackend, exportIndexStore } = statePrep;
|
|
2989
|
+
preflightBackendForCleanup = preflightStateBackend;
|
|
2724
2990
|
synthOptions.stateBucket = stateBucket;
|
|
2725
2991
|
const refusalRecovery = {
|
|
2726
2992
|
profile: options.profile,
|
|
@@ -2787,6 +3053,8 @@ Force-quit: stack locks may not be released. If the next run reports a lock, run
|
|
|
2787
3053
|
ignoreErrors: options.ignoreErrors === true
|
|
2788
3054
|
});
|
|
2789
3055
|
refuseMalformedNestedTemplateTrees(targetStacks);
|
|
3056
|
+
const baseRegion = namedCliRegion(options.region) ?? "us-east-1";
|
|
3057
|
+
const crossPrefixGuard = new CrossPrefixGuard(preflightStateBackend, { readOnly: options.dryRun === true });
|
|
2790
3058
|
await synthesizer.expandMacrosForStacks(targetStacks, synthOptions);
|
|
2791
3059
|
const { STSClient, GetCallerIdentityCommand } = await import("@aws-sdk/client-sts");
|
|
2792
3060
|
const stsClient = new STSClient({
|
|
@@ -2816,7 +3084,6 @@ Force-quit: stack locks may not be released. If the next run reports a lock, run
|
|
|
2816
3084
|
};
|
|
2817
3085
|
const dagBuilder = new DagBuilder({ relaxCdkVpcDefensiveDeps: !!options.aggressiveVpcParallel });
|
|
2818
3086
|
const diffCalculator = new DiffCalculator();
|
|
2819
|
-
const baseRegion = namedCliRegion(options.region) ?? "us-east-1";
|
|
2820
3087
|
const workGraph = new WorkGraph();
|
|
2821
3088
|
const stackMap = new Map(targetStacks.map((s) => [s.stackName, s]));
|
|
2822
3089
|
const stackRedirects = /* @__PURE__ */ new Map();
|
|
@@ -2864,13 +3131,14 @@ Force-quit: stack locks may not be released. If the next run reports a lock, run
|
|
|
2864
3131
|
logger.debug(`Work graph: ${summary["asset-publish"]} asset(s), ${summary["stack"]} stack(s)`);
|
|
2865
3132
|
const bufferStackOutput = targetStacks.length > 1;
|
|
2866
3133
|
let totalUnaddressed = 0;
|
|
3134
|
+
let totalCrossPrefixKept = 0;
|
|
2867
3135
|
let cancelledStacks = 0;
|
|
2868
3136
|
const runStack = async (stackInfo) => {
|
|
2869
3137
|
return withSkipPrefix(skipPrefix, () => runStackInner(stackInfo));
|
|
2870
3138
|
};
|
|
2871
3139
|
const runStackInner = async (stackInfo) => {
|
|
2872
3140
|
if (deployInterrupted) throw new DeployCancelledError(`Deploy interrupted before stack '${stackInfo.stackName}' started — not starting it.`);
|
|
2873
|
-
const stackRegion = stackInfo
|
|
3141
|
+
const stackRegion = deployStackRegion(stackInfo, baseRegion);
|
|
2874
3142
|
logger.info(`\n${cyan("Deploying stack:")} ${bold(cyan(stackInfo.stackName))}${stackRegion !== baseRegion ? gray(` (region: ${stackRegion})`) : ""}`);
|
|
2875
3143
|
const stackAwsClients = new AwsClients({
|
|
2876
3144
|
region: stackRegion,
|
|
@@ -2908,6 +3176,14 @@ Force-quit: stack locks may not be released. If the next run reports a lock, run
|
|
|
2908
3176
|
skipPrefix,
|
|
2909
3177
|
yes: options.yes
|
|
2910
3178
|
});
|
|
3179
|
+
const crossPrefix = crossPrefixEngineOptions({
|
|
3180
|
+
stackName: stackInfo.stackName,
|
|
3181
|
+
region: stackRegion,
|
|
3182
|
+
bucket: stateBucket,
|
|
3183
|
+
recovery: refusalRecovery,
|
|
3184
|
+
guard: crossPrefixGuard,
|
|
3185
|
+
backend: preflightStateBackend
|
|
3186
|
+
});
|
|
2911
3187
|
let recreateTargets;
|
|
2912
3188
|
if (options.recreateViaCcApi?.length || options.recreateViaSdkProvider?.length) {
|
|
2913
3189
|
const stateForRecreateCheck = await stackStateBackend.getState(stackInfo.stackName, stackRegion);
|
|
@@ -2987,7 +3263,10 @@ Force-quit: stack locks may not be released. If the next run reports a lock, run
|
|
|
2987
3263
|
refusalRecovery,
|
|
2988
3264
|
...assetRedirect && { assetRedirect },
|
|
2989
3265
|
...eventRecorder && { eventRecorder },
|
|
2990
|
-
|
|
3266
|
+
onCurrentStateLoaded: composeStateLoadedGates(crossPrefix.firstDeployGate, migrationGate),
|
|
3267
|
+
...crossPrefix.onFirstDeployLeftNoRecord && { onFirstDeployLeftNoRecord: crossPrefix.onFirstDeployLeftNoRecord },
|
|
3268
|
+
onDestructivePlan: crossPrefix.onDestructivePlan,
|
|
3269
|
+
crossPrefixHolder: crossPrefix.crossPrefixHolder,
|
|
2991
3270
|
...options.pinCcApi?.length && { pinCcApi: {
|
|
2992
3271
|
stackName: stackInfo.stackName,
|
|
2993
3272
|
logicalIds: new Set(options.pinCcApi)
|
|
@@ -3038,10 +3317,15 @@ Force-quit: stack locks may not be released. If the next run reports a lock, run
|
|
|
3038
3317
|
logger.info(` Updated: ${updatedTotal > 0 ? yellow(updatedTotal) : gray(updatedTotal)}`);
|
|
3039
3318
|
logger.info(` Deleted: ${deployResult.deleted > 0 ? red(deployResult.deleted) : gray(deployResult.deleted)}`);
|
|
3040
3319
|
if (deployResult.deleteSkipped > 0) logger.info(` Skipped (not deleted): ${yellow(deployResult.deleteSkipped)}`);
|
|
3320
|
+
const crossPrefixKept = deployResult.crossPrefixKept ?? 0;
|
|
3321
|
+
if (crossPrefixKept > 0) logger.info(` Kept (replacement refused: another state prefix records the stack, or the check could not run): ${yellow(crossPrefixKept)}`);
|
|
3041
3322
|
if (ownUpdatePartial > 0) logger.info(safeMsg` of which left an orphaned predecessor: ${yellow(ownUpdatePartial)}`);
|
|
3042
3323
|
if (nestedUpdatePartial > 0) logger.info(safeMsg` Left an orphaned predecessor in a nested stack: ${yellow(nestedUpdatePartial)}`);
|
|
3043
|
-
const stackUnaddressed = deployResult.deleteSkipped + deployResult.updatePartial;
|
|
3044
|
-
if (!options.dryRun)
|
|
3324
|
+
const stackUnaddressed = deployResult.deleteSkipped + deployResult.updatePartial + crossPrefixKept;
|
|
3325
|
+
if (!options.dryRun) {
|
|
3326
|
+
totalUnaddressed += stackUnaddressed;
|
|
3327
|
+
totalCrossPrefixKept += crossPrefixKept;
|
|
3328
|
+
}
|
|
3045
3329
|
logger.info(` Unchanged: ${gray(deployResult.unchanged)}`);
|
|
3046
3330
|
logger.info(` Duration: ${cyan((deployResult.durationMs / 1e3).toFixed(2) + "s")}`);
|
|
3047
3331
|
if (deployResult.attributeFallbackCount > 0) logger.warn(`${deployResult.attributeFallbackCount} attribute resolution(s) fell back to the physical ID (potentially wrong values); re-run with --strict-getatt to fail on these`);
|
|
@@ -3057,7 +3341,7 @@ Force-quit: stack locks may not be released. If the next run reports a lock, run
|
|
|
3057
3341
|
created: deployResult.created,
|
|
3058
3342
|
updated: updatedTotal,
|
|
3059
3343
|
deleted: deployResult.deleted,
|
|
3060
|
-
...
|
|
3344
|
+
...stackUnaddressed > 0 && { skipped: stackUnaddressed }
|
|
3061
3345
|
}, deployResult.durationMs);
|
|
3062
3346
|
} catch (deployError) {
|
|
3063
3347
|
if (deployError instanceof DeployCancelledError) {
|
|
@@ -3102,11 +3386,12 @@ Force-quit: stack locks may not be released. If the next run reports a lock, run
|
|
|
3102
3386
|
if (!outcome.ok) throw outcome.error;
|
|
3103
3387
|
}
|
|
3104
3388
|
});
|
|
3105
|
-
if (totalUnaddressed > 0 && !options.allowUnaddressed) throw new PartialFailureError(`Deploy left ${totalUnaddressed} resource(s) unaddressed, so they may still exist in AWS. The two cases differ in what happens next: a DELETE the provider could not issue KEEPS its state record, so the next 'cdkd deploy' re-attempts it, while a replacement's surviving predecessor is NOT tracked and will never be retried — delete it by hand. The per-stack summaries above give the breakdown, and each resource's own warning names its cause and remedy.
|
|
3389
|
+
if (totalUnaddressed > 0 && !options.allowUnaddressed) throw new PartialFailureError(`Deploy left ${totalUnaddressed} resource(s) unaddressed, so they may still exist in AWS. The two cases differ in what happens next: a DELETE the provider could not issue KEEPS its state record, so the next 'cdkd deploy' re-attempts it, while a replacement's surviving predecessor is NOT tracked and will never be retried — delete it by hand. ` + (totalCrossPrefixKept > 0 ? "A replacement kept because another state prefix records the stack, or the check could not run, keeps its old resource and applies no new value — resolve the pair, or let the check run, and re-deploy. " : "") + "The per-stack summaries above give the breakdown, and each resource's own warning names its cause and remedy. " + (cancelledStacks > 0 ? `Note ${cancelledStacks} stack(s) were also cancelled and never deployed, so the template is not fully applied beyond the resources named above. ` : "") + `Pass --allow-unaddressed to exit 0 instead.`);
|
|
3106
3390
|
} finally {
|
|
3107
3391
|
unforwardSigterm();
|
|
3108
3392
|
process.removeListener("SIGINT", topLevelSigintHandler);
|
|
3109
3393
|
awsClients.destroy();
|
|
3394
|
+
preflightBackendForCleanup?.destroyClient();
|
|
3110
3395
|
}
|
|
3111
3396
|
}
|
|
3112
3397
|
function createDeployCommand() {
|
|
@@ -10744,19 +11029,40 @@ async function acquireStackLock(opts) {
|
|
|
10744
11029
|
get interrupted() {
|
|
10745
11030
|
return interrupted;
|
|
10746
11031
|
},
|
|
10747
|
-
async release({ failureMessage, beforeRelease }) {
|
|
11032
|
+
async release({ failureMessage, beforeRelease, holdUntil }) {
|
|
10748
11033
|
if (released) return;
|
|
10749
11034
|
released = true;
|
|
10750
|
-
|
|
10751
|
-
await beforeRelease?.();
|
|
11035
|
+
const releaseNow = async () => {
|
|
10752
11036
|
try {
|
|
10753
11037
|
await lockManager.releaseLock(stackName, region);
|
|
10754
11038
|
lockHeld = false;
|
|
10755
11039
|
} catch (releaseErr) {
|
|
10756
11040
|
getLogger().warn(safeMsg`${failureMessage}: ${describeAwsFailure(releaseErr).detail}`);
|
|
10757
11041
|
}
|
|
11042
|
+
};
|
|
11043
|
+
let deferred = false;
|
|
11044
|
+
try {
|
|
11045
|
+
await beforeRelease?.();
|
|
11046
|
+
if (holdUntil !== void 0) {
|
|
11047
|
+
process.removeListener("SIGINT", sigintHandler);
|
|
11048
|
+
let forced = false;
|
|
11049
|
+
const removeDeferred = prependPostCleanupSigintListener(() => {
|
|
11050
|
+
if (!interrupted) {
|
|
11051
|
+
interrupted = true;
|
|
11052
|
+
return;
|
|
11053
|
+
}
|
|
11054
|
+
if (forced || !lockHeld) return;
|
|
11055
|
+
forced = true;
|
|
11056
|
+
lockManager.releaseLock(stackName, region).catch(() => {});
|
|
11057
|
+
process.stderr.write(`\nForce-quit (post-destroy cleanup): stack lock may not be released.${forceQuitRecoveryClause(stackName, region, recovery)}\n`);
|
|
11058
|
+
});
|
|
11059
|
+
holdUntil.defer(holdUntil.work.then(() => void 0, () => void 0).then(releaseNow).finally(removeDeferred));
|
|
11060
|
+
deferred = true;
|
|
11061
|
+
return;
|
|
11062
|
+
}
|
|
11063
|
+
await releaseNow();
|
|
10758
11064
|
} finally {
|
|
10759
|
-
process.removeListener("SIGINT", sigintHandler);
|
|
11065
|
+
if (!deferred) process.removeListener("SIGINT", sigintHandler);
|
|
10760
11066
|
}
|
|
10761
11067
|
}
|
|
10762
11068
|
};
|
|
@@ -10864,6 +11170,16 @@ function countProtectedJournaledOrphans(orphans, region) {
|
|
|
10864
11170
|
}
|
|
10865
11171
|
return count;
|
|
10866
11172
|
}
|
|
11173
|
+
async function releaseRegistryMarkerAfterDestroy(ctx, stackName, region, logger) {
|
|
11174
|
+
if (ctx.crossPrefixCheck === void 0) return;
|
|
11175
|
+
try {
|
|
11176
|
+
const known = await ctx.crossPrefixCheck.cache.knownMarker?.(stackName, region);
|
|
11177
|
+
const released = await ctx.stateBackend.releaseRegistryMarker(stackName, region, known);
|
|
11178
|
+
logger.debug(safeMsg`Stack registry marker: ${released}`);
|
|
11179
|
+
} catch (error) {
|
|
11180
|
+
logger.warn(safeMsg`Could not delete the stack registry marker of ${displayStackName(stackName)} ` + safeMsg`(${describeAwsFailure(error).summary}). It names this state prefix, which no longer ` + `records the stack, so a deploy under another prefix treats it as stale.`);
|
|
11181
|
+
}
|
|
11182
|
+
}
|
|
10867
11183
|
async function runDestroyForStack(stackName, state, ctx) {
|
|
10868
11184
|
const providerClasses = await loadProviderClasses();
|
|
10869
11185
|
const logger = getLogger();
|
|
@@ -10878,8 +11194,11 @@ async function runDestroyForStack(stackName, state, ctx) {
|
|
|
10878
11194
|
errorCount: 0,
|
|
10879
11195
|
interrupted: false
|
|
10880
11196
|
};
|
|
11197
|
+
const retainedForReadoption = [];
|
|
11198
|
+
let retainedEarlier;
|
|
10881
11199
|
const guardIndeterminateTargets = /* @__PURE__ */ new Set();
|
|
10882
11200
|
const regionForState = state.region ?? ctx.baseRegion;
|
|
11201
|
+
const crossPrefixScan = ctx.crossPrefixCheck?.cache.full(stackName, regionForState);
|
|
10883
11202
|
const refusalRecovery = {
|
|
10884
11203
|
profile: ctx.profile,
|
|
10885
11204
|
stateBucket: ctx.stateBucket,
|
|
@@ -10902,6 +11221,15 @@ async function runDestroyForStack(stackName, state, ctx) {
|
|
|
10902
11221
|
const resourceCount = Object.keys(state.resources).length;
|
|
10903
11222
|
const orphanCount = (state.orphans ?? []).length;
|
|
10904
11223
|
refuseMalformedOutputsForDestroy(state, stackName, regionForState, refusalRecovery);
|
|
11224
|
+
if (crossPrefixScan) applyCrossPrefixScan(await crossPrefixScan, {
|
|
11225
|
+
stackName,
|
|
11226
|
+
region: regionForState,
|
|
11227
|
+
bucket: ctx.stateBucket,
|
|
11228
|
+
recovery: {
|
|
11229
|
+
profile: ctx.profile,
|
|
11230
|
+
stateBucket: ctx.stateBucket
|
|
11231
|
+
}
|
|
11232
|
+
}, "destroy", (message) => logger.warn(message), (message) => logger.info(message));
|
|
10905
11233
|
if (resourceCount === 0 && orphanCount === 0 && journaledOrphans.count === 0) {
|
|
10906
11234
|
logger.info(`Stack ${displayStackName(stackName)} has no resources, cleaning up state...`);
|
|
10907
11235
|
const emptyLock = await acquireStackLock({
|
|
@@ -10925,6 +11253,7 @@ async function runDestroyForStack(stackName, state, ctx) {
|
|
|
10925
11253
|
if (!(!recheck || recheckResources === 0 && recheckOrphans === 0)) throw new Error(`Stack ${displayStackName(stackName)} (${displaySafe(regionForState, { asciiOnly: true })}) was empty when this run started but now has ${recheckResources} resource(s) and ${recheckOrphans} rollback-orphaned resource(s) — another cdkd process wrote to it. Re-run the destroy to act on the current state.`);
|
|
10926
11254
|
await ctx.stateBackend.deleteState(stackName, regionForState);
|
|
10927
11255
|
logger.info(`${green("✓")} State deleted`);
|
|
11256
|
+
await Promise.all([recordRetainedForReadoption(ctx.stateBackend, stackName, regionForState, [], logger), releaseRegistryMarkerAfterDestroy(ctx, stackName, regionForState, logger)]);
|
|
10928
11257
|
} finally {
|
|
10929
11258
|
await emptyLock.release({ failureMessage: "Failed to release lock after empty-state cleanup" });
|
|
10930
11259
|
}
|
|
@@ -11012,11 +11341,14 @@ async function runDestroyForStack(stackName, state, ctx) {
|
|
|
11012
11341
|
}
|
|
11013
11342
|
const renderer = getLiveRenderer();
|
|
11014
11343
|
let statePreserved = false;
|
|
11344
|
+
let heldTail;
|
|
11345
|
+
let stackFinished = false;
|
|
11015
11346
|
let journaledOrphanFailures = 0;
|
|
11016
11347
|
let journaledOrphanSkips = 0;
|
|
11017
11348
|
const lock = await acquireStackLock({
|
|
11018
11349
|
...stackLockBase,
|
|
11019
11350
|
onFirstSignal: () => {
|
|
11351
|
+
if (stackFinished) return;
|
|
11020
11352
|
renderer.printAbove(() => {
|
|
11021
11353
|
process.stderr.write("\nInterrupted — finishing in-flight deletes, then flushing state and releasing the lock (press Ctrl-C again to force-quit)...\n");
|
|
11022
11354
|
});
|
|
@@ -11190,6 +11522,17 @@ async function runDestroyForStack(stackName, state, ctx) {
|
|
|
11190
11522
|
if (shouldRetainResource(resource.deletionPolicy)) {
|
|
11191
11523
|
logger.info(` ⊘ ${displaySafe(logicalId)} (${displaySafe(resource.resourceType)}) retained — DeletionPolicy: ${displaySafe(resource.deletionPolicy)}`);
|
|
11192
11524
|
result.retainedCount++;
|
|
11525
|
+
if (keptForReadoption(resource)) {
|
|
11526
|
+
retainedForReadoption.push({
|
|
11527
|
+
logicalId,
|
|
11528
|
+
resourceType: resource.resourceType,
|
|
11529
|
+
physicalId: resource.physicalId
|
|
11530
|
+
});
|
|
11531
|
+
if (retainedEarlier === void 0) {
|
|
11532
|
+
retainedEarlier = Promise.resolve().then(() => ctx.stateBackend.loadRetainedRecord(stackName, regionForState));
|
|
11533
|
+
retainedEarlier.catch(() => void 0);
|
|
11534
|
+
}
|
|
11535
|
+
}
|
|
11193
11536
|
recordDestroyEvent(ctx.eventRecorder, {
|
|
11194
11537
|
eventType: "RESOURCE_RETAINED",
|
|
11195
11538
|
stackName,
|
|
@@ -11401,7 +11744,16 @@ async function runDestroyForStack(stackName, state, ctx) {
|
|
|
11401
11744
|
if (!preserveState) {
|
|
11402
11745
|
await ctx.stateBackend.deleteState(stackName, regionForState);
|
|
11403
11746
|
logger.debug("State deleted");
|
|
11404
|
-
|
|
11747
|
+
const writeKept = () => recordRetainedForReadoption(ctx.stateBackend, stackName, regionForState, retainedForReadoption, logger, retainedEarlier);
|
|
11748
|
+
const releaseMarker = () => releaseRegistryMarkerAfterDestroy(ctx, stackName, regionForState, logger);
|
|
11749
|
+
if (ctx.deferRegistryTail !== void 0) {
|
|
11750
|
+
heldTail = writeKept().then(releaseMarker);
|
|
11751
|
+
await ctx.exportIndexStore?.removeStack(stackName, regionForState);
|
|
11752
|
+
} else await Promise.all([
|
|
11753
|
+
writeKept(),
|
|
11754
|
+
releaseMarker(),
|
|
11755
|
+
ctx.exportIndexStore?.removeStack(stackName, regionForState)
|
|
11756
|
+
]);
|
|
11405
11757
|
} else {
|
|
11406
11758
|
try {
|
|
11407
11759
|
await ctx.stateBackend.saveState(stackName, regionForState, buildDestroySnapshot());
|
|
@@ -11448,6 +11800,10 @@ async function runDestroyForStack(stackName, state, ctx) {
|
|
|
11448
11800
|
try {
|
|
11449
11801
|
await lock.release({
|
|
11450
11802
|
failureMessage: `Failed to release lock for stack ${displayStackName(stackName)}`,
|
|
11803
|
+
...heldTail !== void 0 && ctx.deferRegistryTail !== void 0 && { holdUntil: {
|
|
11804
|
+
work: heldTail,
|
|
11805
|
+
defer: ctx.deferRegistryTail
|
|
11806
|
+
} },
|
|
11451
11807
|
beforeRelease: async () => {
|
|
11452
11808
|
try {
|
|
11453
11809
|
renderer.stop();
|
|
@@ -11458,6 +11814,7 @@ async function runDestroyForStack(stackName, state, ctx) {
|
|
|
11458
11814
|
logger.debug("Releasing lock...");
|
|
11459
11815
|
}
|
|
11460
11816
|
});
|
|
11817
|
+
stackFinished = true;
|
|
11461
11818
|
} finally {
|
|
11462
11819
|
restoreBaseRegionAndClients();
|
|
11463
11820
|
}
|
|
@@ -11508,6 +11865,10 @@ function orderConsumersBeforeProducers(stackNames, consumerToProducers) {
|
|
|
11508
11865
|
}
|
|
11509
11866
|
return ordered;
|
|
11510
11867
|
}
|
|
11868
|
+
function plannedDestroyRegion(refs, synthRegion, cliRegion) {
|
|
11869
|
+
if (refs.length === 1) return refs[0]?.region || cliRegion;
|
|
11870
|
+
if (refs.length > 1 && synthRegion && refs.some((r) => r.region === synthRegion)) return synthRegion;
|
|
11871
|
+
}
|
|
11511
11872
|
async function purgeEventsAfterDestroy(reader, stackName, region, opts, logger) {
|
|
11512
11873
|
if (opts.purgeEvents !== true || opts.runResult !== "SUCCEEDED" || opts.interrupted) return null;
|
|
11513
11874
|
try {
|
|
@@ -11565,6 +11926,9 @@ async function destroyCommand(stackArgs, options) {
|
|
|
11565
11926
|
interruptWatch.dispose();
|
|
11566
11927
|
throw error;
|
|
11567
11928
|
}
|
|
11929
|
+
let stateBackendForCleanup;
|
|
11930
|
+
const deferredTails = [];
|
|
11931
|
+
let deferRegistryTail;
|
|
11568
11932
|
try {
|
|
11569
11933
|
const stateConfig = {
|
|
11570
11934
|
bucket: stateBucket,
|
|
@@ -11574,6 +11938,7 @@ async function destroyCommand(stackArgs, options) {
|
|
|
11574
11938
|
...options.region && { region: options.region },
|
|
11575
11939
|
...options.profile && { profile: options.profile }
|
|
11576
11940
|
});
|
|
11941
|
+
stateBackendForCleanup = stateBackend;
|
|
11577
11942
|
await stateBackend.verifyBucketExists();
|
|
11578
11943
|
const lockManager = new LockManager(awsClients.s3, stateConfig);
|
|
11579
11944
|
const exportIndexStore = new ExportIndexStore(awsClients.s3, stateBucket, options.statePrefix, region, stateBackend, { profile: options.profile });
|
|
@@ -11716,6 +12081,14 @@ async function destroyCommand(stackArgs, options) {
|
|
|
11716
12081
|
arr.push(ref);
|
|
11717
12082
|
stateRefsByName.set(ref.stackName, arr);
|
|
11718
12083
|
}
|
|
12084
|
+
const crossPrefixCheck = { cache: new CrossPrefixGuard(stateBackend) };
|
|
12085
|
+
if (stackNames.length > 1) deferRegistryTail = (released) => deferredTails.push(released);
|
|
12086
|
+
for (const name of stackNames) {
|
|
12087
|
+
const synth = appStacks.find((s) => s.stackName === name);
|
|
12088
|
+
if (synth?.terminationProtection === true && !options.removeProtection) continue;
|
|
12089
|
+
const planned = plannedDestroyRegion(stateRefsByName.get(name) ?? [], synth?.region, region);
|
|
12090
|
+
if (planned !== void 0) crossPrefixCheck.cache.full(name, planned, "prestart");
|
|
12091
|
+
}
|
|
11719
12092
|
for (const [stackIndex, stackName] of stackNames.entries()) {
|
|
11720
12093
|
logger.info(`\nPreparing to destroy stack: ${displaySafe(stackName)}`);
|
|
11721
12094
|
const refs = stateRefsByName.get(stackName) ?? [];
|
|
@@ -11733,15 +12106,12 @@ async function destroyCommand(stackArgs, options) {
|
|
|
11733
12106
|
continue;
|
|
11734
12107
|
}
|
|
11735
12108
|
}
|
|
12109
|
+
const plannedRegion = plannedDestroyRegion(refs, synthRegion, region);
|
|
11736
12110
|
let stackTargetRegion;
|
|
11737
12111
|
if (refs.length === 0) {
|
|
11738
12112
|
logger.warn(`No state found for stack ${displaySafe(stackName)}, skipping`);
|
|
11739
12113
|
continue;
|
|
11740
|
-
} else if (
|
|
11741
|
-
const onlyRegion = refs[0]?.region;
|
|
11742
|
-
if (!onlyRegion) stackTargetRegion = region;
|
|
11743
|
-
else stackTargetRegion = onlyRegion;
|
|
11744
|
-
} else if (synthRegion && refs.some((r) => r.region === synthRegion)) stackTargetRegion = synthRegion;
|
|
12114
|
+
} else if (plannedRegion !== void 0) stackTargetRegion = plannedRegion;
|
|
11745
12115
|
else {
|
|
11746
12116
|
const regions = refs.map((r) => r.region === void 0 ? "(legacy)" : plainOrDescribed(r.region, "region")).join(", ");
|
|
11747
12117
|
const orphanOneClause = withheldAccountClause(accountRecovery, "the command below prints").trimEnd();
|
|
@@ -11819,6 +12189,8 @@ async function destroyCommand(stackArgs, options) {
|
|
|
11819
12189
|
skipFinalSnapshot: options.skipFinalSnapshot === true,
|
|
11820
12190
|
resolveSecretDerivedPrincipals: {},
|
|
11821
12191
|
stackDestroy: true,
|
|
12192
|
+
crossPrefixCheck,
|
|
12193
|
+
...deferRegistryTail !== void 0 && { deferRegistryTail },
|
|
11822
12194
|
exportIndexStore,
|
|
11823
12195
|
...TemplateNoEchoReresolver.usable(synthStack?.template) && (synthStack.region === void 0 || synthStack.region === stackTargetRegion) && { noEchoReresolver: new TemplateNoEchoReresolver({
|
|
11824
12196
|
template: synthStack.template,
|
|
@@ -11872,9 +12244,11 @@ async function destroyCommand(stackArgs, options) {
|
|
|
11872
12244
|
if (interrupted || interruptWatch.interrupted() && stoppedEarly) throw new PartialFailureError(`Destroy interrupted by Ctrl-C. State preserved — re-run 'cdkd destroy' to finish.`);
|
|
11873
12245
|
if (totalSkipped > 0) throw new PartialFailureError(`Destroy skipped ${totalSkipped} entr${totalSkipped === 1 ? "y" : "ies"} whose delete cdkd did not confirm, so the underlying resources may still exist in AWS. A skipped nested stack counts as ONE entry and may cover several of its own resources — the per-stack summaries above give the exact breakdown. State preserved (the records are kept). The per-resource 'skipped (...)' lines and their warnings name each cause and whether repairing the record in state.json helps: where it does, repair it and re-run 'cdkd destroy'; otherwise (for example a custom-resource Delete handler that reported FAILED), delete the resources by hand and drop the records with 'cdkd state orphan <stack> --stack-region <region>'.`);
|
|
11874
12246
|
} finally {
|
|
12247
|
+
await Promise.allSettled(deferredTails);
|
|
11875
12248
|
unforwardSigterm();
|
|
11876
12249
|
interruptWatch.dispose();
|
|
11877
12250
|
awsClients.destroy();
|
|
12251
|
+
stateBackendForCleanup?.destroyClient();
|
|
11878
12252
|
}
|
|
11879
12253
|
}
|
|
11880
12254
|
function createDestroyCommand() {
|
|
@@ -14022,7 +14396,7 @@ async function exportCommand(stackArg, options) {
|
|
|
14022
14396
|
2. Re-run the phase 2 UPDATE manually with the full synth template:
|
|
14023
14397
|
${phase2RetryCommand(cfnStackName)}\n 3. Once phase 2 succeeds, clean up cdkd's stale state record.${orphan.note}\n Run: ${orphan.command}`);
|
|
14024
14398
|
}
|
|
14025
|
-
await stateBackend
|
|
14399
|
+
await removeExportedStackRecord(stateBackend, resolvedStackName, targetRegion, logger);
|
|
14026
14400
|
logger.info(`cdkd state for ${quotedOrNotShown(resolvedStackName)} (${quotedRegion(targetRegion)}) removed. Manage the stack with 'cdk deploy' or 'aws cloudformation' from here on.`);
|
|
14027
14401
|
printNextSteps({
|
|
14028
14402
|
cfnStackName,
|
|
@@ -15626,6 +16000,11 @@ async function buildResolvedParametersPerStack(args) {
|
|
|
15626
16000
|
intrinsicSkippedByCdkdName
|
|
15627
16001
|
};
|
|
15628
16002
|
}
|
|
16003
|
+
async function removeExportedStackRecord(stateBackend, stackName, region, logger) {
|
|
16004
|
+
await stateBackend.deleteState(stackName, region);
|
|
16005
|
+
await recordRetainedForReadoption(stateBackend, stackName, region, [], logger);
|
|
16006
|
+
await releaseRegistryMarkerQuietly(stateBackend, stackName, region, logger);
|
|
16007
|
+
}
|
|
15629
16008
|
async function runPerStackImportLoop(args) {
|
|
15630
16009
|
const logger = getLogger();
|
|
15631
16010
|
const { rootStackName, rootRegion, rootStackInfoNestedTemplates, rootTemplateFormat, tree, rootTemplate, cfnStackNameOverrides, rootParameters, deps, options } = args;
|
|
@@ -15903,7 +16282,7 @@ async function runPerStackImportLoop(args) {
|
|
|
15903
16282
|
}
|
|
15904
16283
|
const stateDeletionFailures = [];
|
|
15905
16284
|
for (const node of leafFirst) try {
|
|
15906
|
-
await deps.stateBackend
|
|
16285
|
+
await removeExportedStackRecord(deps.stateBackend, node.stackName, node.region, logger);
|
|
15907
16286
|
logger.info(`cdkd state for ${quotedOrNotShown(node.stackName)} (${quotedRegion(node.region)}) removed.`);
|
|
15908
16287
|
} catch (err) {
|
|
15909
16288
|
stateDeletionFailures.push({
|
|
@@ -16129,6 +16508,10 @@ const STATE_READ_REASONS = {
|
|
|
16129
16508
|
"read-failed": STATE_READ_FAILED_REASON,
|
|
16130
16509
|
"resources-malformed": "resources is not a JSON object; run `cdkd state show --json` to see the record"
|
|
16131
16510
|
};
|
|
16511
|
+
function stateDestroyTargets(refs, stackRegion) {
|
|
16512
|
+
if (stackRegion) return refs.filter((r) => r.region === stackRegion || !r.region);
|
|
16513
|
+
return refs.length === 1 ? [...refs] : void 0;
|
|
16514
|
+
}
|
|
16132
16515
|
function resourceCountOrNull(resources) {
|
|
16133
16516
|
if (resources === void 0 || resources === null) return 0;
|
|
16134
16517
|
if (typeof resources !== "object" || Array.isArray(resources)) return null;
|
|
@@ -16249,7 +16632,10 @@ async function setupStateBackend(options) {
|
|
|
16249
16632
|
bucket,
|
|
16250
16633
|
prefix,
|
|
16251
16634
|
exportIndexStore: new ExportIndexStore(awsClients.s3, bucket, prefix, region, stateBackend, { profile: options.profile }),
|
|
16252
|
-
dispose: () =>
|
|
16635
|
+
dispose: () => {
|
|
16636
|
+
awsClients.destroy();
|
|
16637
|
+
stateBackend.destroyClient();
|
|
16638
|
+
}
|
|
16253
16639
|
};
|
|
16254
16640
|
}
|
|
16255
16641
|
function renderRecovery(options, setup) {
|
|
@@ -16690,6 +17076,43 @@ function createStateShowCommand() {
|
|
|
16690
17076
|
cmd.addOption(deprecatedRegionOption);
|
|
16691
17077
|
return cmd;
|
|
16692
17078
|
}
|
|
17079
|
+
async function clearRetainedQuietly(backend, stackName, region, logger) {
|
|
17080
|
+
try {
|
|
17081
|
+
await backend.saveRetainedResources(stackName, region, []);
|
|
17082
|
+
return true;
|
|
17083
|
+
} catch (error) {
|
|
17084
|
+
logger.warn(safeMsg`Could not empty the kept-resource record of ${displayStackName(stackName)} ` + safeMsg`(${describeAwsFailure(error).summary}): a later deploy here may still take a kept ` + `resource back. Re-run 'cdkd state orphan' once it can write.`);
|
|
17085
|
+
return false;
|
|
17086
|
+
}
|
|
17087
|
+
}
|
|
17088
|
+
async function clearRetainedWithoutRecord(backend, stackName, stackRegion, logger) {
|
|
17089
|
+
if (stackName.includes("/")) return {
|
|
17090
|
+
cleared: [],
|
|
17091
|
+
attempted: 0
|
|
17092
|
+
};
|
|
17093
|
+
const base = `${backend.prefix}/${stackName}/`;
|
|
17094
|
+
let regions;
|
|
17095
|
+
try {
|
|
17096
|
+
const keys = (await backend.listRawKeys(base)).map((key) => key.slice(base.length).split("/")).filter((parts) => parts.length >= 2 && parts[0] !== "");
|
|
17097
|
+
const recorded = new Set(keys.filter((parts) => parts.length === 2 && parts[1] === "state.json").map((parts) => parts[0]));
|
|
17098
|
+
regions = [...new Set(keys.map((parts) => parts[0]).filter((region) => stackRegion === void 0 || region === stackRegion).filter((region) => !recorded.has(region)))];
|
|
17099
|
+
} catch (error) {
|
|
17100
|
+
logger.warn(safeMsg`Could not look for a kept-resource record of ${displayStackName(stackName)} ` + safeMsg`(${describeAwsFailure(error).summary}).`);
|
|
17101
|
+
return {
|
|
17102
|
+
cleared: [],
|
|
17103
|
+
attempted: 0
|
|
17104
|
+
};
|
|
17105
|
+
}
|
|
17106
|
+
const cleared = [];
|
|
17107
|
+
for (const region of regions) {
|
|
17108
|
+
if (await clearRetainedQuietly(backend, stackName, region, logger)) cleared.push(region);
|
|
17109
|
+
await releaseRegistryMarkerQuietly(backend, stackName, region, logger);
|
|
17110
|
+
}
|
|
17111
|
+
return {
|
|
17112
|
+
cleared,
|
|
17113
|
+
attempted: regions.length
|
|
17114
|
+
};
|
|
17115
|
+
}
|
|
16693
17116
|
async function stateOrphanCommand(stackArgs, options) {
|
|
16694
17117
|
const logger = getLogger();
|
|
16695
17118
|
if (options.verbose) logger.setLevel("debug");
|
|
@@ -16705,6 +17128,12 @@ async function stateOrphanCommand(stackArgs, options) {
|
|
|
16705
17128
|
for (const stackName of stackArgs) {
|
|
16706
17129
|
const stackRefs = refs.filter((r) => r.stackName === stackName);
|
|
16707
17130
|
if (stackRefs.length === 0) {
|
|
17131
|
+
const { cleared, attempted } = await clearRetainedWithoutRecord(setup.stateBackend, stackName, options.stackRegion, logger);
|
|
17132
|
+
if (attempted > 0 && cleared.length === 0) continue;
|
|
17133
|
+
if (cleared.length > 0) {
|
|
17134
|
+
logger.info(safeMsg`Cleared the kept-resource record of ${plainOrDescribed(stackName, "stack name")} ` + safeMsg`(${cleared.map((r) => displaySafe(r, { asciiOnly: true })).join(", ")}): ` + `a later deploy here no longer takes a kept resource back.`);
|
|
17135
|
+
continue;
|
|
17136
|
+
}
|
|
16708
17137
|
logger.info(safeMsg`No state found for stack: ${plainOrDescribed(stackName, "stack name")}, skipping` + (isPasteableIdent(stackName) ? "" : safeMsg`. ${STATE_LIST_POINTER}`));
|
|
16709
17138
|
continue;
|
|
16710
17139
|
}
|
|
@@ -16748,10 +17177,13 @@ async function stateOrphanCommand(stackArgs, options) {
|
|
|
16748
17177
|
await warnOnLiveForeignLock(setup.lockManager, stackName, target.region, logger);
|
|
16749
17178
|
await setup.stateBackend.deleteState(stackName, target.region);
|
|
16750
17179
|
await setup.lockManager.forceReleaseLock(stackName, target.region);
|
|
17180
|
+
await clearRetainedQuietly(setup.stateBackend, stackName, target.region, logger);
|
|
17181
|
+
await releaseRegistryMarkerQuietly(setup.stateBackend, stackName, target.region, logger);
|
|
16751
17182
|
} else {
|
|
16752
17183
|
await warnOnLiveForeignLock(setup.lockManager, stackName, void 0, logger);
|
|
16753
17184
|
await setup.stateBackend.deleteLegacyState(stackName);
|
|
16754
17185
|
await setup.lockManager.forceReleaseLock(stackName, void 0);
|
|
17186
|
+
await clearRetainedWithoutRecord(setup.stateBackend, stackName, void 0, logger);
|
|
16755
17187
|
}
|
|
16756
17188
|
logger.info(safeMsg`✓ Removed state for stack: ${describedStackRef(target)}` + ((options.yes || options.force) && refIsDescribed(target) ? safeMsg`. ${STATE_LIST_POINTER}` : ""));
|
|
16757
17189
|
}
|
|
@@ -16899,6 +17331,8 @@ async function stateDestroyCommand(stackArgs, options) {
|
|
|
16899
17331
|
interruptWatch.dispose();
|
|
16900
17332
|
throw error;
|
|
16901
17333
|
}
|
|
17334
|
+
const deferredTails = [];
|
|
17335
|
+
let deferRegistryTail;
|
|
16902
17336
|
try {
|
|
16903
17337
|
const stateRefs = await setup.stateBackend.listStacks();
|
|
16904
17338
|
const knownStackNames = new Set(stateRefs.map((r) => r.stackName));
|
|
@@ -16916,16 +17350,23 @@ async function stateDestroyCommand(stackArgs, options) {
|
|
|
16916
17350
|
if (!options.stackRegion) return laterRefs.length > 0;
|
|
16917
17351
|
return laterRefs.some((r) => r.region === options.stackRegion || !r.region);
|
|
16918
17352
|
});
|
|
17353
|
+
const crossPrefixCheck = { cache: new CrossPrefixGuard(setup.stateBackend) };
|
|
17354
|
+
if (stackNames.length > 1) deferRegistryTail = (released) => deferredTails.push(released);
|
|
17355
|
+
for (const name of stackNames) {
|
|
17356
|
+
const refs = stateRefs.filter((r) => r.stackName === name);
|
|
17357
|
+
for (const ref of stateDestroyTargets(refs, options.stackRegion) ?? []) crossPrefixCheck.cache.full(name, ref.region ?? setup.region, "prestart");
|
|
17358
|
+
}
|
|
16919
17359
|
for (const [stackIndex, stackName] of stackNames.entries()) {
|
|
16920
17360
|
const refs = stateRefs.filter((r) => r.stackName === stackName);
|
|
16921
17361
|
let targets;
|
|
17362
|
+
const planned = stateDestroyTargets(refs, options.stackRegion);
|
|
16922
17363
|
if (options.stackRegion) {
|
|
16923
|
-
targets =
|
|
17364
|
+
targets = planned ?? [];
|
|
16924
17365
|
if (targets.length === 0) {
|
|
16925
17366
|
logger.warn(safeMsg`Skipping ${plainOrDescribed(stackName, "stack name")} (no state record matches ` + safeMsg`--stack-region ${displayIdent(options.stackRegion)})`);
|
|
16926
17367
|
continue;
|
|
16927
17368
|
}
|
|
16928
|
-
} else if (
|
|
17369
|
+
} else if (planned !== void 0) targets = planned;
|
|
16929
17370
|
else throw multipleRegionsError(stackName, refs, `Use --stack-region ${commandHole("region")} to pick one.`);
|
|
16930
17371
|
for (const [refIndex, ref] of targets.entries()) {
|
|
16931
17372
|
logger.info(safeMsg`\nPreparing to destroy stack: ${formatStackRefSafe(ref)}`);
|
|
@@ -16982,6 +17423,8 @@ async function stateDestroyCommand(stackArgs, options) {
|
|
|
16982
17423
|
skipFinalSnapshot: options.skipFinalSnapshot === true,
|
|
16983
17424
|
resolveSecretDerivedPrincipals: {},
|
|
16984
17425
|
stackDestroy: true,
|
|
17426
|
+
crossPrefixCheck,
|
|
17427
|
+
...deferRegistryTail !== void 0 && { deferRegistryTail },
|
|
16985
17428
|
exportIndexStore: setup.exportIndexStore,
|
|
16986
17429
|
...options.allowUnsupportedTypes?.length && { allowUnsupportedTypes: options.allowUnsupportedTypes },
|
|
16987
17430
|
...options.resourceWarnAfter?.globalMs !== void 0 && { resourceWarnAfterMs: options.resourceWarnAfter.globalMs },
|
|
@@ -17022,6 +17465,7 @@ async function stateDestroyCommand(stackArgs, options) {
|
|
|
17022
17465
|
if (interrupted || interruptWatch.interrupted() && stoppedEarly) throw new PartialFailureError(`Destroy interrupted by Ctrl-C. State preserved — re-run 'cdkd state destroy' to finish.`);
|
|
17023
17466
|
if (totalSkipped > 0) throw new PartialFailureError(`Destroy skipped ${totalSkipped} entr${totalSkipped === 1 ? "y" : "ies"} whose delete cdkd did not confirm, so the underlying resources may still exist in AWS. A skipped nested stack counts as ONE entry and may cover several of its own resources — the per-stack summaries above give the exact breakdown. State preserved (the records are kept). The per-resource 'skipped (...)' lines and their warnings name each cause and whether repairing the record in state.json helps: where it does, repair it and re-run 'cdkd state destroy'; otherwise (for example a custom-resource Delete handler that reported FAILED), delete the resources by hand and drop the records with 'cdkd state orphan <stack> --stack-region <region>'.`);
|
|
17024
17467
|
} finally {
|
|
17468
|
+
await Promise.allSettled(deferredTails);
|
|
17025
17469
|
unforwardSigterm();
|
|
17026
17470
|
interruptWatch.dispose();
|
|
17027
17471
|
setup.dispose();
|
|
@@ -17684,6 +18128,7 @@ async function rollbackCommand(stackArg, options) {
|
|
|
17684
18128
|
});
|
|
17685
18129
|
return;
|
|
17686
18130
|
}
|
|
18131
|
+
const crossPrefixScan = new CrossPrefixGuard(setup.stateBackend).full(stackName, region);
|
|
17687
18132
|
stackAwsClients = new AwsClients({
|
|
17688
18133
|
region,
|
|
17689
18134
|
...options.profile && { profile: options.profile }
|
|
@@ -17718,6 +18163,15 @@ async function rollbackCommand(stackArg, options) {
|
|
|
17718
18163
|
segments: journal.segments.filter((s) => s.reason !== NESTED_PENDING_PARENT_REASON)
|
|
17719
18164
|
};
|
|
17720
18165
|
if (!journal || journal.segments.length === 0 && orphanedPending === 0) throw new Error(`Nothing to roll back for ${plainOrDescribed(stackName, "stack name")} (${plainOrDescribed(region, "region")}). Run 'cdkd deploy' to (re)deploy, or 'cdkd destroy' to clean up.`);
|
|
18166
|
+
applyCrossPrefixScan(await crossPrefixScan, {
|
|
18167
|
+
stackName,
|
|
18168
|
+
region,
|
|
18169
|
+
bucket: setup.bucket,
|
|
18170
|
+
recovery: {
|
|
18171
|
+
profile: options.profile,
|
|
18172
|
+
stateBucket: setup.bucket
|
|
18173
|
+
}
|
|
18174
|
+
}, "rollback", (message) => logger.warn(message), (message) => logger.info(message));
|
|
17721
18175
|
if (!stateData) throw new Error(`Rollback journal exists for ${safeStack(stackName)} (${safe(region)}) but its state.json is missing (keys: ${safe(setup.prefix)}/${safeStack(stackName)}/${safe(region)}/state.json and .../rollback-journal.json). State appears corrupted — inspect the bucket manually.`);
|
|
17722
18176
|
demoteSupersededOrphans(journal.segments, Array.isArray(stateData.state.orphans) ? stateData.state.orphans : []);
|
|
17723
18177
|
if (!options.revertFailed) for (const segment of journal.segments) {
|
|
@@ -17961,6 +18415,8 @@ async function rollbackCommand(stackArg, options) {
|
|
|
17961
18415
|
const survivingOrphans = orphansAfterRollback(baseState, mintedOrphans).orphans ?? [];
|
|
17962
18416
|
if (journal.segments.length === 0 && oldestInitialDeploy && Object.keys(stateResources).length === 0 && survivingOrphans.length === 0) {
|
|
17963
18417
|
await setup.stateBackend.deleteState(stackName, region);
|
|
18418
|
+
await recordRetainedForReadoption(setup.stateBackend, stackName, region, [], logger);
|
|
18419
|
+
await releaseRegistryMarkerQuietly(setup.stateBackend, stackName, region, logger);
|
|
17964
18420
|
logger.info(`State for ${stackRegionShown(stackName, region)} removed (stack fully rolled back).`);
|
|
17965
18421
|
}
|
|
17966
18422
|
if (declinedDivergentRewrite) throw new PartialFailureError(`Rollback stopped: ${declinedDivergentReason}.` + (totalFailures > 0 ? ` ${totalFailures} operation(s) also failed.` : "") + " Journal preserved (this segment, any older ones, and their failed operations) — re-run the rollback once the record's region field matches its key.");
|
|
@@ -19108,8 +19564,20 @@ async function forceUnlockCommand(stackArgs, options) {
|
|
|
19108
19564
|
const where = r ? `${displayStackName(stackName)} (${displayIdent(r)})` : `${displayStackName(stackName)} (legacy lock key)`;
|
|
19109
19565
|
logger.info(`Force-unlocking stack: ${where}`);
|
|
19110
19566
|
try {
|
|
19111
|
-
|
|
19567
|
+
let ledgerError;
|
|
19568
|
+
let recorded = false;
|
|
19569
|
+
await lockManager.forceReleaseLock(stackName, r, async (horizon) => {
|
|
19570
|
+
if (r === void 0) return;
|
|
19571
|
+
const ledger = ledgerForStack(stateBackend, stackName, r);
|
|
19572
|
+
for (let attempt = 0; attempt < 2 && !recorded; attempt++) try {
|
|
19573
|
+
await ledger.noteAbandoned(horizon);
|
|
19574
|
+
recorded = true;
|
|
19575
|
+
} catch (error) {
|
|
19576
|
+
ledgerError = error;
|
|
19577
|
+
}
|
|
19578
|
+
});
|
|
19112
19579
|
logger.info(`✓ Lock released for stack: ${where}`);
|
|
19580
|
+
if (!recorded && ledgerError !== void 0) logger.warn(safeMsg`Lock released, but the create-token ledger of ${where} could not record when the ` + safeMsg`abandoned run stopped: ${describeAwsFailure(ledgerError).summary}. ` + "A later deploy may take back a resource of those names that another deployment creates.");
|
|
19113
19581
|
} catch (error) {
|
|
19114
19582
|
const message = describeAwsFailure(error).detail;
|
|
19115
19583
|
if (message.includes("No lock found") || message.includes("NoSuchKey")) logger.info(`No lock found for stack: ${where}`);
|
|
@@ -19219,6 +19687,20 @@ var ObservedBaselineRefusals = class extends Set {
|
|
|
19219
19687
|
unverifiableParameter = /* @__PURE__ */ new Set();
|
|
19220
19688
|
hadDeployedParameterSource = false;
|
|
19221
19689
|
};
|
|
19690
|
+
async function claimRegistryMarkerAfterImport(backend, stackName, region, logger) {
|
|
19691
|
+
const answer = await new CrossPrefixGuard(backend).full(stackName, region);
|
|
19692
|
+
const regionShown = displaySafe(region, { asciiOnly: true });
|
|
19693
|
+
switch (answer.kind) {
|
|
19694
|
+
case "clear": return;
|
|
19695
|
+
case "found":
|
|
19696
|
+
logger.warn(safeMsg`The state bucket also records ${displayStackName(stackName)} (${regionShown}) under another state prefix ` + safeMsg`(${answer.prefixes.map((p) => displayIdent(p)).join(", ")}). One stack name per ` + "account and region is supported: drop one of the records with 'cdkd state orphan' before deploying or destroying either.");
|
|
19697
|
+
return;
|
|
19698
|
+
case "in-progress":
|
|
19699
|
+
logger.warn(safeMsg`A deploy of ${displayStackName(stackName)} (${regionShown}) holds a lock under another state prefix ` + safeMsg`(${displayIdent(answer.prefix)}). One stack name per account and region is ` + `supported: keep one of the two before deploying or destroying either.`);
|
|
19700
|
+
return;
|
|
19701
|
+
default: logger.warn(safeMsg`Could not record ${displayStackName(stackName)} (${regionShown}) in the state bucket's stack registry` + (answer.kind === "denied" || answer.kind === "failed" ? safeMsg` (${describeAwsFailure(answer.error).summary})` : "") + `. Its next guarded command records it.`);
|
|
19702
|
+
}
|
|
19703
|
+
}
|
|
19222
19704
|
async function importCommand(stackArg, options) {
|
|
19223
19705
|
const providerClasses = await loadProviderClasses();
|
|
19224
19706
|
const logger = getLogger();
|
|
@@ -19439,6 +19921,7 @@ async function importCommand(stackArg, options) {
|
|
|
19439
19921
|
await recordImportOnRollbackJournal(stateBackend, stackInfo.stackName, targetRegion, importedRows.map((r) => r.logicalId), stackState.resources, logger);
|
|
19440
19922
|
await stateBackend.saveState(stackInfo.stackName, targetRegion, stackState, saveOptions);
|
|
19441
19923
|
logger.info(`✓ State written: ${stackInfo.stackName} (${targetRegion})`);
|
|
19924
|
+
await claimRegistryMarkerAfterImport(stateBackend, stackInfo.stackName, targetRegion, logger);
|
|
19442
19925
|
logger.info(` ${importedRows.length} resource(s) imported. Run 'cdkd diff' to see how the imported state lines up with the template.`);
|
|
19443
19926
|
if (migrationCfnStackName && migrationTree && accountIdForNestedSynth) await importNestedStackChildrenRecursive({
|
|
19444
19927
|
lockRecovery,
|
|
@@ -27766,4 +28249,4 @@ function collectVerbFlags(program) {
|
|
|
27766
28249
|
|
|
27767
28250
|
//#endregion
|
|
27768
28251
|
export { canonicalizeIpProtocolValue as a, buildProgram, resolveSecretDerivedPrincipals as i, runDestroyForStack as n, resolvedResourceTimeoutMs as o, isResolvableSecretPrincipalList as r, canonicalizeIpv4Cidr as t };
|
|
27769
|
-
//# sourceMappingURL=program-
|
|
28252
|
+
//# sourceMappingURL=program-CN7Dqb3j.js.map
|