@go-to-k/cdkd 0.291.26 → 0.291.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{asg-provider-Dbqbr89e.js → asg-provider-CWCv370K.js} +3 -3
- package/dist/{asg-provider-Dbqbr89e.js.map → asg-provider-CWCv370K.js.map} +1 -1
- package/dist/{aws-client-defaults-jISU4PHo.js → aws-client-defaults-qSDe1fA_.js} +44 -4
- package/dist/aws-client-defaults-qSDe1fA_.js.map +1 -0
- package/dist/cli.js +2 -2
- package/dist/{deploy-engine-BZps_IKn.js → deploy-engine-DIZztJy5.js} +145 -39
- package/dist/deploy-engine-DIZztJy5.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/{program-BALgPCWL.js → program-WCBWtvb0.js} +424 -277
- package/dist/{program-BALgPCWL.js.map → program-WCBWtvb0.js.map} +1 -1
- package/dist/{version-BkoR4hMq.js → version-CuKFdkKV.js} +2 -2
- package/dist/{version-BkoR4hMq.js.map → version-CuKFdkKV.js.map} +1 -1
- package/package.json +1 -1
- package/dist/aws-client-defaults-jISU4PHo.js.map +0 -1
- package/dist/deploy-engine-BZps_IKn.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 markRedactedCause, 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 pasteableCommand, Cr as describeTypeWithThrottleRetry, Ct as compositeIdSkipResult, D as PRE_DELETE_SNAPSHOT_TYPES, Da as ambientClientDefaults, Di as parseBootstrapMarker, Dn as deployRefusesOrphanRowsReason, Do as isThrottlingError, 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 isRetryableTransientError, Er as TemplateParser, Et as maskDeep, F as extractDeploymentEventError, Fa as defineOwnKey, Fi as describeDockerExecFailure, Fn as malformedExportSourceWarning, 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 describeAwsFailure, Mr as createSecretMasker, Mt as disableInstanceApiTermination, N as unsupportedFinalSnapshotError, Na as globMatches, Ni as resolveDockerContextDirectory, Nn as isReadableResourceEntry, No as safeStringify, Nr as dynamicReferenceTokens, Nt as isTerminationProtectionPropagationError, O as buildFinalSnapshotIdentifier, Oa as ambientCredentialConfig, Oi as readBootstrapMarkerBody, On as displayLogicalId, Oo as isTransientServerError, Or as STATE_SOURCED_CROSS_GENERATION_RULES, Ot as UNSPECIFIED_SKIP_REASON, P as makeCanonicalizePropertiesFn, Pa as processStackMessages, Pi as describeDockerCapturedOutput, Pn as malformedExportNamesWarning, 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 isMarkedNonRetryable, 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 retryClassificationText, jr as carriesSecretMask, jt as isWaitAbandonedError, k as ccRoutedFinalSnapshotError, ka as clientDefaultsFor, ki as validateAssetBucketName, kn as hasReadableOrphans, ko as markNonRetryable, 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 shellQuote, 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-BZps_IKn.js";
|
|
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";
|
|
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
|
-
import { n as awsClientDefaults, s as ambientRegion } from "./aws-client-defaults-
|
|
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-
|
|
3
|
+
import { n as awsClientDefaults, s as ambientRegion, u as formatAuthority } from "./aws-client-defaults-qSDe1fA_.js";
|
|
4
|
+
import { t as getCdkdVersion } from "./version-CuKFdkKV.js";
|
|
5
|
+
import { a as renderDisableCommand, i as protectedReplacementAdvice, r as UNNAMEABLE_ID_CLAUSE, t as ASGProvider } from "./asg-provider-CWCv370K.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";
|
|
@@ -3445,9 +3445,10 @@ async function findDownstreamConsumers(input) {
|
|
|
3445
3445
|
const got = await input.stateBackend.getState(ref.stackName, region);
|
|
3446
3446
|
if (!got) return null;
|
|
3447
3447
|
const out = [];
|
|
3448
|
+
const producerRegion = canonicalizeRegion(input.producerRegion);
|
|
3448
3449
|
const imports = got.state.imports;
|
|
3449
3450
|
if (imports && imports.length > 0) {
|
|
3450
|
-
for (const entry of imports) if (entry.sourceStack === input.producerStack && entry.sourceRegion ===
|
|
3451
|
+
for (const entry of imports) if (entry.sourceStack === input.producerStack && canonicalizeRegion(entry.sourceRegion) === producerRegion) out.push({
|
|
3451
3452
|
consumerStack: ref.stackName,
|
|
3452
3453
|
consumerRegion: region,
|
|
3453
3454
|
exportName: entry.exportName,
|
|
@@ -3456,7 +3457,7 @@ async function findDownstreamConsumers(input) {
|
|
|
3456
3457
|
}
|
|
3457
3458
|
const outputReads = got.state.outputReads;
|
|
3458
3459
|
if (outputReads && outputReads.length > 0) for (const entry of outputReads) {
|
|
3459
|
-
if (entry.sourceRegion ===
|
|
3460
|
+
if (canonicalizeRegion(entry.sourceRegion) === producerRegion && producerNameIsUnresolved(entry.sourceStack)) {
|
|
3460
3461
|
out.push({
|
|
3461
3462
|
consumerStack: ref.stackName,
|
|
3462
3463
|
consumerRegion: region,
|
|
@@ -3466,7 +3467,7 @@ async function findDownstreamConsumers(input) {
|
|
|
3466
3467
|
});
|
|
3467
3468
|
continue;
|
|
3468
3469
|
}
|
|
3469
|
-
if (entry.sourceStack === input.producerStack && entry.sourceRegion ===
|
|
3470
|
+
if (entry.sourceStack === input.producerStack && canonicalizeRegion(entry.sourceRegion) === producerRegion) out.push({
|
|
3470
3471
|
consumerStack: ref.stackName,
|
|
3471
3472
|
consumerRegion: region,
|
|
3472
3473
|
exportName: entry.outputName,
|
|
@@ -28598,11 +28599,13 @@ var EventBridgeBusProvider = class {
|
|
|
28598
28599
|
*
|
|
28599
28600
|
* AWS rewrites a non-canonical CIDR on `CreateRoute`, so a route id that
|
|
28600
28601
|
* spells the template's CIDR can differ from the destination AWS reports
|
|
28601
|
-
* (issue #1771)
|
|
28602
|
-
*
|
|
28603
|
-
*
|
|
28602
|
+
* (issue #1771): the Cloud Control path records what AWS returned while the
|
|
28603
|
+
* template kept what the user wrote. Returning `undefined` for the shapes this
|
|
28604
|
+
* does not model is load-bearing — `cdkd export`'s route-id splitter reads it
|
|
28605
|
+
* to decide whether a divergence is conclusive or merely unexplained.
|
|
28606
|
+
* `EC2Provider`'s import compares through this too (issue #3661).
|
|
28604
28607
|
*/
|
|
28605
|
-
function canonicalizeIpv4Cidr
|
|
28608
|
+
function canonicalizeIpv4Cidr(value) {
|
|
28606
28609
|
const match = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\/(\d{1,2})$/.exec(value);
|
|
28607
28610
|
if (!match) return void 0;
|
|
28608
28611
|
const octets = [
|
|
@@ -32190,8 +32193,8 @@ var EC2Provider = class {
|
|
|
32190
32193
|
if (rest.length > 0 || !routeTableId || !destination) return null;
|
|
32191
32194
|
if (!/^rtb-[0-9a-f]+$/.test(routeTableId)) return null;
|
|
32192
32195
|
const resp = await this.ec2Client.send(new DescribeRouteTablesCommand({ RouteTableIds: [routeTableId] }));
|
|
32193
|
-
const wanted = canonicalizeIpv4Cidr
|
|
32194
|
-
return resp.RouteTables?.[0]?.Routes?.some((r) => r.DestinationCidrBlock !== void 0 && (canonicalizeIpv4Cidr
|
|
32196
|
+
const wanted = canonicalizeIpv4Cidr(destination) ?? destination;
|
|
32197
|
+
return resp.RouteTables?.[0]?.Routes?.some((r) => r.DestinationCidrBlock !== void 0 && (canonicalizeIpv4Cidr(r.DestinationCidrBlock) ?? r.DestinationCidrBlock) === wanted || r.DestinationIpv6CidrBlock === destination || r.DestinationPrefixListId === destination) ? {
|
|
32195
32198
|
physicalId,
|
|
32196
32199
|
attributes: {}
|
|
32197
32200
|
} : null;
|
|
@@ -64050,7 +64053,7 @@ var S3TablesProvider = class {
|
|
|
64050
64053
|
if (resolvedParts === "unparseable") throw new ProvisioningError(`applyTableTagsDiff: ${compositeIdFormatMessage(S3_TABLES_TABLE_ID_FORMAT, logicalId, physicalId)}. Cannot derive the table ARN for the tag update, and refusing to silently drop it.`, resourceType, logicalId, physicalId);
|
|
64051
64054
|
const { tableBucketARN, namespace, name } = resolvedParts;
|
|
64052
64055
|
const resourceArn = await this.lookupTableArn(tableBucketARN, namespace, name);
|
|
64053
|
-
if (!resourceArn) throw new ProvisioningError(`applyTableTagsDiff: GetTable returned no tableARN for ${physicalId} — table is gone or state is out-of-sync. Refusing to silently drop the tag update
|
|
64056
|
+
if (!resourceArn) throw new ProvisioningError(`applyTableTagsDiff: GetTable returned no tableARN for ${physicalId} — table is gone or state is out-of-sync. Refusing to silently drop the tag update. If the table was deleted out-of-band, drop just this resource's record with the command below, filling in the construct path the CDK app gave this resource — its aws:cdk:path Metadata entry in the synthesized template.\nClean up with: cdkd orphan ${commandHole("constructPath")}`, resourceType, logicalId, physicalId);
|
|
64054
64057
|
if (removedKeys.length > 0) try {
|
|
64055
64058
|
await this.getClient().send(new UntagResourceCommand$24({
|
|
64056
64059
|
resourceArn,
|
|
@@ -65223,7 +65226,7 @@ async function scanActiveConsumers(producerStack, producerRegion, ctx) {
|
|
|
65223
65226
|
try {
|
|
65224
65227
|
const imports = (await ctx.stateBackend.getState(ref.stackName, region))?.state.imports;
|
|
65225
65228
|
if (!imports || imports.length === 0) return null;
|
|
65226
|
-
const matches = imports.filter((entry) => entry.sourceStack === producerStack && entry.sourceRegion === producerRegion);
|
|
65229
|
+
const matches = imports.filter((entry) => entry.sourceStack === producerStack && canonicalizeRegion(entry.sourceRegion) === canonicalizeRegion(producerRegion));
|
|
65227
65230
|
if (matches.length === 0) return null;
|
|
65228
65231
|
return matches.map((entry) => ({
|
|
65229
65232
|
consumerStack: ref.stackName,
|
|
@@ -65552,9 +65555,10 @@ var NestedStackProvider = class {
|
|
|
65552
65555
|
refuseMalformedNestedChildOutputs(childStateData.state, childStackName, childRegion);
|
|
65553
65556
|
const attributes = this.buildOutputsAttributes(childStateData.state.outputs ?? {});
|
|
65554
65557
|
const noEchoAttributeNames = [];
|
|
65558
|
+
const identity = credentialFingerprint(ambientCredentialConfig());
|
|
65555
65559
|
for (const [outputKey, persisted] of Object.entries(childStateData.state.outputs ?? {})) {
|
|
65556
65560
|
if (!carriesSecretMask(persisted)) continue;
|
|
65557
|
-
const recovered = recoverMaskedOutput(childStackName, childRegion, outputKey);
|
|
65561
|
+
const recovered = recoverMaskedOutput(identity, childStackName, childRegion, outputKey);
|
|
65558
65562
|
if (recovered === void 0) continue;
|
|
65559
65563
|
const attributeName = this.outputAttributeName(outputKey);
|
|
65560
65564
|
attributes[attributeName] = recovered;
|
|
@@ -66681,7 +66685,8 @@ async function deployCommand(stacks, options) {
|
|
|
66681
66685
|
let deployInterrupted = false;
|
|
66682
66686
|
const topLevelSigintHandler = () => {
|
|
66683
66687
|
if (deployInterrupted) {
|
|
66684
|
-
process.stderr.write(
|
|
66688
|
+
process.stderr.write(`
|
|
66689
|
+
Force-quit: stack locks may not be released. If the next run reports a lock, run this for EACH stack it names, in the region-qualified form — see the message that run prints.\nRelease with: cdkd force-unlock ${commandHole("stackName")} --stack-region ${commandHole("region")}\n`);
|
|
66685
66690
|
process.exit(130);
|
|
66686
66691
|
}
|
|
66687
66692
|
process.stderr.write("\nInterrupted — waiting for in-progress operations to complete...\n");
|
|
@@ -69964,10 +69969,11 @@ async function repairExportIndexForStack(store, stackName, producerRegion, outpu
|
|
|
69964
69969
|
*
|
|
69965
69970
|
* ORDERING: scrub matches the CURRENT resolved secret value against what state
|
|
69966
69971
|
* holds, so run it BEFORE rotating. Once the secret is rotated, the value in
|
|
69967
|
-
* state no longer matches the current one and scrub cannot
|
|
69968
|
-
*
|
|
69969
|
-
*
|
|
69970
|
-
*
|
|
69972
|
+
* state no longer matches the current one and scrub cannot rewrite it. Only a
|
|
69973
|
+
* cross-stack read NAME left that way is REPORTED (go-to-k/cdkd#3382,
|
|
69974
|
+
* `findUnrepairedCrossStackReadNames`); elsewhere a rotated-away value is
|
|
69975
|
+
* invisible to scrub. To remove it, redeploy the stack (which rewrites the
|
|
69976
|
+
* record with the expression).
|
|
69971
69977
|
*/
|
|
69972
69978
|
async function scrubCommand(stacks, options) {
|
|
69973
69979
|
const logger = getLogger();
|
|
@@ -70026,6 +70032,7 @@ async function scrubCommand(stacks, options) {
|
|
|
70026
70032
|
let totalStacksWithUnscrubbableKeys = 0;
|
|
70027
70033
|
let totalStacksWithUnverifiableReads = 0;
|
|
70028
70034
|
let totalStacksWithUnverifiableLeaves = 0;
|
|
70035
|
+
let totalStacksWithUnrepairedReadNames = 0;
|
|
70029
70036
|
/**
|
|
70030
70037
|
* Stacks this `--dry-run` proceeded over with an UNREADABLE resources map
|
|
70031
70038
|
* (issue go-to-k/cdkd#3018). Tracked exactly like `indexUnreadable`: an
|
|
@@ -70132,7 +70139,7 @@ async function scrubCommand(stacks, options) {
|
|
|
70132
70139
|
if (scrubbed.recordsChanged > 0) {
|
|
70133
70140
|
totalStacksScrubbed++;
|
|
70134
70141
|
logger.info(`${options.dryRun ? "Would scrub" : "Scrubbed"} ${scrubbed.recordsChanged} resource record(s) in ${shownStack}`);
|
|
70135
|
-
} else if (scrubbed.secretBearingKeys === 0 && scrubbed.unverifiableReads === 0 && scrubbed.unverifiableLeaves === 0 && indexConverged === 0) logger.info(`No plaintext secrets found in ${shownStack}`);
|
|
70142
|
+
} else if (scrubbed.secretBearingKeys === 0 && scrubbed.unverifiableReads === 0 && scrubbed.unverifiableLeaves === 0 && scrubbed.unrepairedReadNames === 0 && indexConverged === 0) logger.info(`No plaintext secrets found in ${shownStack}`);
|
|
70136
70143
|
if (scrubbed.malformedResources) malformedRecords.push(stack.stackName);
|
|
70137
70144
|
if (scrubbed.malformedOutputs) malformedOutputRecords.push(stack.stackName);
|
|
70138
70145
|
if (scrubbed.malformedOrphans || scrubbed.malformedOrphanRows) malformedOrphanRecords.push(stack.stackName);
|
|
@@ -70145,6 +70152,10 @@ async function scrubCommand(stacks, options) {
|
|
|
70145
70152
|
totalStacksWithUnverifiableReads++;
|
|
70146
70153
|
logger.warn(`${scrubbed.unverifiableReads} cross-stack read(s) in ${shownStack} could NOT be verified (see the warnings above for which, and why) — so this stack is not reported clean.`);
|
|
70147
70154
|
}
|
|
70155
|
+
if (scrubbed.unrepairedReadNames > 0) {
|
|
70156
|
+
totalStacksWithUnrepairedReadNames++;
|
|
70157
|
+
logger.warn(`${scrubbed.unrepairedReadNames} cross-stack read name(s) in ${shownStack} hold a plaintext scrub could NOT repair (see the warnings above) — so this stack is not reported clean.`);
|
|
70158
|
+
}
|
|
70148
70159
|
if (scrubbed.secretBearingKeys > 0) {
|
|
70149
70160
|
totalStacksWithUnscrubbableKeys++;
|
|
70150
70161
|
logger.warn(`${scrubbed.secretBearingKeys} output KEY(s) in ${shownStack} hold plaintext and CANNOT be scrubbed — rename the Export.Name and redeploy (see the warning above).`);
|
|
@@ -70171,7 +70182,7 @@ async function scrubCommand(stacks, options) {
|
|
|
70171
70182
|
totalIndexEntriesUnexamined += unexamined.length;
|
|
70172
70183
|
logger.info(`Exports index (${displayIdent(indexRegion)}): ${unexamined.length} entr${unexamined.length === 1 ? "y is" : "ies are"} published by a producer this run did not scrub, so nothing here read ${unexamined.length === 1 ? "its" : "their"} value. Coverage composes across the apps sharing this bucket and region — run each app's own cdkd scrub to reach its entries.`);
|
|
70173
70184
|
}
|
|
70174
|
-
if (totalStacksScrubbed === 0 && totalStacksWithUnscrubbableKeys === 0 && totalStacksWithUnverifiableReads === 0 && totalStacksWithUnverifiableLeaves === 0 && totalIndexEntriesConverged === 0 && indexUnwritten.length === 0 && indexUnreadable.length === 0 && malformedRecords.length === 0 && malformedOutputRecords.length === 0 && malformedOrphanRecords.length === 0) {
|
|
70185
|
+
if (totalStacksScrubbed === 0 && totalStacksWithUnscrubbableKeys === 0 && totalStacksWithUnverifiableReads === 0 && totalStacksWithUnverifiableLeaves === 0 && totalStacksWithUnrepairedReadNames === 0 && totalIndexEntriesConverged === 0 && indexUnwritten.length === 0 && indexUnreadable.length === 0 && malformedRecords.length === 0 && malformedOutputRecords.length === 0 && malformedOrphanRecords.length === 0) {
|
|
70175
70186
|
if (failures.length === 0) {
|
|
70176
70187
|
logger.info("\nNo plaintext secrets found in any target stack state. Nothing to scrub.");
|
|
70177
70188
|
return;
|
|
@@ -70183,6 +70194,7 @@ async function scrubCommand(stacks, options) {
|
|
|
70183
70194
|
const keyNote = totalStacksWithUnscrubbableKeys > 0 ? ` ${totalStacksWithUnscrubbableKeys} stack(s) hold plaintext in an output KEY, which cdkd scrub cannot rewrite — rename that output's Export.Name and redeploy.` : "";
|
|
70184
70195
|
const leafNote = totalStacksWithUnverifiableLeaves > 0 ? ` ${totalStacksWithUnverifiableLeaves} stack(s) had a {{resolve:...}} scan ABANDONED mid-value, so part of their state was never examined (see the warnings above).` : "";
|
|
70185
70196
|
const unverifiableNote = totalStacksWithUnverifiableReads > 0 ? ` ${totalStacksWithUnverifiableReads} stack(s) carry a cross-stack read that could NOT be verified, so their imported values were not checked — see the warnings above for which read, why, and what to do about it.` : "";
|
|
70197
|
+
const readNameNote = totalStacksWithUnrepairedReadNames > 0 ? ` ${totalStacksWithUnrepairedReadNames} stack(s) hold a cross-stack read name in plaintext that scrub could NOT repair, most likely a secret's value from before a rotation — see the warnings above.` : "";
|
|
70186
70198
|
const indexNote = (() => {
|
|
70187
70199
|
const parts = [];
|
|
70188
70200
|
if (totalIndexEntriesConverged > 0) parts.push(options.dryRun ? ` ${totalIndexEntriesConverged} exports index entr${totalIndexEntriesConverged === 1 ? "y" : "ies"} differ from the producer's scrubbed state.outputs and would be converged to it (--dry-run, nothing written).` : ` ${totalIndexEntriesConverged} exports index entr${totalIndexEntriesConverged === 1 ? "y" : "ies"} converged to the producer's state.outputs value. exports.json is written with the same PutObject state.json is, so on a VERSIONED bucket the pre-repair body survives as a noncurrent version and stays readable with GetObject and a VersionId.`);
|
|
@@ -70191,8 +70203,8 @@ async function scrubCommand(stacks, options) {
|
|
|
70191
70203
|
return parts.join("");
|
|
70192
70204
|
})();
|
|
70193
70205
|
if (options.dryRun) {
|
|
70194
|
-
if (totalStacksScrubbed > 0) logger.info(`\nPlan: ${totalStacksScrubbed} stack(s) hold plaintext secrets and would be scrubbed (--dry-run, no state written).${keyNote}${unverifiableNote}${leafNote}${indexNote}${failureNote} ROTATE any exposed secret in Secrets Manager.`);
|
|
70195
|
-
else logger.info(`\nPlan: no state record can be rewritten.${keyNote}${unverifiableNote}${leafNote}${indexNote}${failureNote} ROTATE any exposed secret.`);
|
|
70206
|
+
if (totalStacksScrubbed > 0) logger.info(`\nPlan: ${totalStacksScrubbed} stack(s) hold plaintext secrets and would be scrubbed (--dry-run, no state written).${keyNote}${unverifiableNote}${readNameNote}${leafNote}${indexNote}${failureNote} ROTATE any exposed secret in Secrets Manager.`);
|
|
70207
|
+
else logger.info(`\nPlan: no state record can be rewritten.${keyNote}${unverifiableNote}${readNameNote}${leafNote}${indexNote}${failureNote} ROTATE any exposed secret.`);
|
|
70196
70208
|
if (failures.length > 0) throw scrubStacksFailedError(failures);
|
|
70197
70209
|
if (indexUnwritten.length > 0 || indexUnreadable.length > 0) throw exportIndexIncompleteError(indexUnwritten, indexUnreadable, true);
|
|
70198
70210
|
if (malformedRecords.length > 0 || malformedOutputRecords.length > 0 || malformedOrphanRecords.length > 0) throw malformedRecordsAuditedError(malformedRecords, malformedOutputRecords, malformedOrphanRecords);
|
|
@@ -70200,13 +70212,13 @@ async function scrubCommand(stacks, options) {
|
|
|
70200
70212
|
if (options.fail) throw new ScrubNeededError();
|
|
70201
70213
|
return;
|
|
70202
70214
|
}
|
|
70203
|
-
if (totalStacksScrubbed > 0) logger.info(`\nDone: scrubbed ${totalStacksScrubbed} stack(s). The CURRENT state.json no longer holds the plaintext. Where the state bucket is VERSIONED — which cdkd bootstrap enables — the pre-scrub body survives as a noncurrent version, stays readable with GetObject and a VersionId, and scrub does not purge it. So a value that was ever persisted must be treated as compromised — ROTATE it in Secrets Manager (scrub matches the current value, so scrub BEFORE rotating); rotation is what makes any surviving version harmless.${keyNote}${unverifiableNote}${leafNote}${indexNote}${failureNote}`);
|
|
70204
|
-
else logger.info(`\nNo state record was rewritten.${keyNote}${unverifiableNote}${leafNote}${indexNote}${failureNote} ROTATE any exposed secret.`);
|
|
70215
|
+
if (totalStacksScrubbed > 0) logger.info(`\nDone: scrubbed ${totalStacksScrubbed} stack(s). The CURRENT state.json no longer holds the plaintext. Where the state bucket is VERSIONED — which cdkd bootstrap enables — the pre-scrub body survives as a noncurrent version, stays readable with GetObject and a VersionId, and scrub does not purge it. So a value that was ever persisted must be treated as compromised — ROTATE it in Secrets Manager (scrub matches the current value, so scrub BEFORE rotating); rotation is what makes any surviving version harmless.${keyNote}${unverifiableNote}${readNameNote}${leafNote}${indexNote}${failureNote}`);
|
|
70216
|
+
else logger.info(`\nNo state record was rewritten.${keyNote}${unverifiableNote}${readNameNote}${leafNote}${indexNote}${failureNote} ROTATE any exposed secret.`);
|
|
70205
70217
|
if (failures.length > 0) throw scrubStacksFailedError(failures);
|
|
70206
70218
|
if (indexUnwritten.length > 0 || indexUnreadable.length > 0) throw exportIndexIncompleteError(indexUnwritten, indexUnreadable, false);
|
|
70207
70219
|
if (malformedRecords.length > 0 || malformedOutputRecords.length > 0 || malformedOrphanRecords.length > 0) throw malformedRecordsAuditedError(malformedRecords, malformedOutputRecords, malformedOrphanRecords);
|
|
70208
70220
|
if (damagedProducerStacks.length > 0) throw damagedProducerRecordsError(damagedProducerStacks);
|
|
70209
|
-
if (options.fail && (totalStacksWithUnscrubbableKeys > 0 || totalStacksWithUnverifiableReads > 0 || totalStacksWithUnverifiableLeaves > 0)) throw new ScrubNeededError();
|
|
70221
|
+
if (options.fail && (totalStacksWithUnscrubbableKeys > 0 || totalStacksWithUnverifiableReads > 0 || totalStacksWithUnrepairedReadNames > 0 || totalStacksWithUnverifiableLeaves > 0)) throw new ScrubNeededError();
|
|
70210
70222
|
}
|
|
70211
70223
|
/**
|
|
70212
70224
|
* Every secret plaintext this run recorded, from ANY position in the template
|
|
@@ -71441,6 +71453,134 @@ function buildExportOwnerIndex(templates) {
|
|
|
71441
71453
|
return owners;
|
|
71442
71454
|
}
|
|
71443
71455
|
/**
|
|
71456
|
+
* How a stored name relates to the REDACTED spelling of a name today's
|
|
71457
|
+
* template produced, with every `{{resolve:...}}` token standing for a
|
|
71458
|
+
* non-empty run of characters: `wildcard` when the stored name matches and at
|
|
71459
|
+
* least one token position holds TEXT rather than a whole token; `equal` when
|
|
71460
|
+
* it is that spelling exactly; `no` otherwise.
|
|
71461
|
+
*/
|
|
71462
|
+
/** The text between (and around) `tokens`, which are `value`'s own tokens in order. */
|
|
71463
|
+
function literalParts(value, tokens) {
|
|
71464
|
+
const parts = [];
|
|
71465
|
+
let cursor = 0;
|
|
71466
|
+
for (const token of tokens) {
|
|
71467
|
+
const at = value.indexOf(token, cursor);
|
|
71468
|
+
parts.push(value.slice(cursor, at));
|
|
71469
|
+
cursor = at + token.length;
|
|
71470
|
+
}
|
|
71471
|
+
parts.push(value.slice(cursor));
|
|
71472
|
+
return parts;
|
|
71473
|
+
}
|
|
71474
|
+
function crossStackNameFit(stored, currentRedacted) {
|
|
71475
|
+
if (typeof stored !== "string") return "no";
|
|
71476
|
+
const tokens = dynamicReferenceTokens(currentRedacted);
|
|
71477
|
+
if (tokens.length === 0) return stored === currentRedacted ? "equal" : "no";
|
|
71478
|
+
const storedTokens = dynamicReferenceTokens(stored);
|
|
71479
|
+
if (storedTokens.length === tokens.length && literalParts(stored, storedTokens).join("\0") === literalParts(currentRedacted, tokens).join("\0")) return storedTokens.every((t, i) => t === tokens[i]) ? "equal" : "no";
|
|
71480
|
+
let pattern = "^";
|
|
71481
|
+
let cursor = 0;
|
|
71482
|
+
for (const token of tokens) {
|
|
71483
|
+
const at = currentRedacted.indexOf(token, cursor);
|
|
71484
|
+
pattern += `${escapeRegExp(currentRedacted.slice(cursor, at))}([\\s\\S]+)`;
|
|
71485
|
+
cursor = at + token.length;
|
|
71486
|
+
}
|
|
71487
|
+
pattern += `${escapeRegExp(currentRedacted.slice(cursor))}$`;
|
|
71488
|
+
const match = new RegExp(pattern).exec(stored);
|
|
71489
|
+
if (!match) return "no";
|
|
71490
|
+
return match.slice(1).map((f) => f ?? "").some((f) => {
|
|
71491
|
+
const inner = dynamicReferenceTokens(f);
|
|
71492
|
+
return !(inner.length === 1 && inner[0] === f);
|
|
71493
|
+
}) ? "wildcard" : "no";
|
|
71494
|
+
}
|
|
71495
|
+
/**
|
|
71496
|
+
* The stored cross-stack read entries that still hold a plaintext this run
|
|
71497
|
+
* could not repair because the secret behind it has ROTATED (go-to-k/cdkd#3382).
|
|
71498
|
+
*
|
|
71499
|
+
* Scrub's needles are the secret's CURRENT value, so a name stored while the
|
|
71500
|
+
* secret held an earlier value matches none of them and the repair walk leaves
|
|
71501
|
+
* it alone. Nothing in the record says the name was secret-bearing, so the
|
|
71502
|
+
* verdict is taken from today's template instead. An entry is flagged when ALL
|
|
71503
|
+
* of these hold:
|
|
71504
|
+
*
|
|
71505
|
+
* - no read today's template performed REPRODUCES it (same identity key the
|
|
71506
|
+
* deploy's union uses, on the redacted spelling). This is what keeps an
|
|
71507
|
+
* ordinary import green even when it shares a producer — and even a name
|
|
71508
|
+
* shape — with a secret-bearing one: this run re-read it and it matched;
|
|
71509
|
+
* - a read today's template performed from a position that can refuse has a
|
|
71510
|
+
* name that carries a secret (its redacted spelling holds a token), reads
|
|
71511
|
+
* the same producer (`imports[].sourceStack`, which is never redacted) in
|
|
71512
|
+
* the same region;
|
|
71513
|
+
* - the stored entry FITS that read's name: every literal part equal, every
|
|
71514
|
+
* token position filled by a non-empty run, and at least one position
|
|
71515
|
+
* holding text rather than a whole token (a name built from two secrets with
|
|
71516
|
+
* one rotated keeps its old half as text after the walk repairs the other).
|
|
71517
|
+
* Every other field must equal the read's spelling.
|
|
71518
|
+
*
|
|
71519
|
+
* Residual, in the over-reporting direction: a stale entry left by a REMOVED
|
|
71520
|
+
* ordinary reference to the same producer whose name happens to fit a
|
|
71521
|
+
* secret-bearing read's shape is flagged too. Stale entries survive only a
|
|
71522
|
+
* deploy that changed nothing or failed — a deploy that updates the stack
|
|
71523
|
+
* replaces both lists — so that needs a removed read, no successful change
|
|
71524
|
+
* since, and a coincident shape. Reads made while evaluating `Conditions`
|
|
71525
|
+
* count as reproducing (the deploy records them too) but are never flagged
|
|
71526
|
+
* against, since the pre-pass does not walk conditions.
|
|
71527
|
+
*
|
|
71528
|
+
* `stored` is the POST-repair list, so an entry this run just rewrote carries
|
|
71529
|
+
* its token and is never flagged. `redact` is the same function the repair
|
|
71530
|
+
* walk used, so a performed read's spelling and a repaired stored one agree.
|
|
71531
|
+
*/
|
|
71532
|
+
function findUnrepairedCrossStackReadNames(stored, performed, redact) {
|
|
71533
|
+
const found = [];
|
|
71534
|
+
const region = (r) => canonicalizeRegion(String(r));
|
|
71535
|
+
const currentImports = performed.imports.map(({ entry, canRefuse }) => ({
|
|
71536
|
+
sourceStack: entry.sourceStack,
|
|
71537
|
+
sourceRegion: region(entry.sourceRegion),
|
|
71538
|
+
exportName: redact(entry.exportName),
|
|
71539
|
+
canRefuse
|
|
71540
|
+
}));
|
|
71541
|
+
const importKey = (e) => JSON.stringify([
|
|
71542
|
+
e.sourceStack,
|
|
71543
|
+
region(e.sourceRegion),
|
|
71544
|
+
e.exportName
|
|
71545
|
+
]);
|
|
71546
|
+
const reproducedImports = new Set(currentImports.map(importKey));
|
|
71547
|
+
const secretImports = currentImports.filter((c) => c.canRefuse && dynamicReferenceTokens(c.exportName).length > 0);
|
|
71548
|
+
(stored.imports ?? []).forEach((entry, index) => {
|
|
71549
|
+
if (reproducedImports.has(importKey(entry))) return;
|
|
71550
|
+
if (secretImports.some((c) => c.sourceStack === entry.sourceStack && c.sourceRegion === region(entry.sourceRegion) && crossStackNameFit(entry.exportName, c.exportName) === "wildcard")) found.push({
|
|
71551
|
+
list: "imports",
|
|
71552
|
+
index,
|
|
71553
|
+
entry
|
|
71554
|
+
});
|
|
71555
|
+
});
|
|
71556
|
+
const currentOutputReads = performed.outputReads.map(({ entry, canRefuse }) => ({
|
|
71557
|
+
sourceStack: redact(entry.sourceStack),
|
|
71558
|
+
sourceRegion: region(entry.sourceRegion),
|
|
71559
|
+
outputName: redact(entry.outputName),
|
|
71560
|
+
canRefuse
|
|
71561
|
+
}));
|
|
71562
|
+
const outputReadKey = (e) => JSON.stringify([
|
|
71563
|
+
e.sourceStack,
|
|
71564
|
+
region(e.sourceRegion),
|
|
71565
|
+
e.outputName
|
|
71566
|
+
]);
|
|
71567
|
+
const reproducedOutputReads = new Set(currentOutputReads.map(outputReadKey));
|
|
71568
|
+
const secretOutputReads = currentOutputReads.filter((c) => c.canRefuse && (dynamicReferenceTokens(c.sourceStack).length > 0 || dynamicReferenceTokens(c.outputName).length > 0));
|
|
71569
|
+
(stored.outputReads ?? []).forEach((entry, index) => {
|
|
71570
|
+
if (reproducedOutputReads.has(outputReadKey(entry))) return;
|
|
71571
|
+
if (secretOutputReads.some((c) => {
|
|
71572
|
+
if (c.sourceRegion !== region(entry.sourceRegion)) return false;
|
|
71573
|
+
const fits = [crossStackNameFit(entry.sourceStack, c.sourceStack), crossStackNameFit(entry.outputName, c.outputName)];
|
|
71574
|
+
return !fits.includes("no") && fits.includes("wildcard");
|
|
71575
|
+
})) found.push({
|
|
71576
|
+
list: "outputReads",
|
|
71577
|
+
index,
|
|
71578
|
+
entry
|
|
71579
|
+
});
|
|
71580
|
+
});
|
|
71581
|
+
return found;
|
|
71582
|
+
}
|
|
71583
|
+
/**
|
|
71444
71584
|
* Is this the issue #2134 refusal -- a `{{resolve:...}}` reference whose region
|
|
71445
71585
|
* cdkd cannot establish?
|
|
71446
71586
|
*
|
|
@@ -72163,6 +72303,14 @@ function makeCrossStackPrePass(deps) {
|
|
|
72163
72303
|
}
|
|
72164
72304
|
throw unresolvableCrossStackReadError(origin, stackName, key, path, err, secrets);
|
|
72165
72305
|
}
|
|
72306
|
+
for (const entry of probe.recordedImports ?? []) findings.performedReads.imports.push({
|
|
72307
|
+
entry,
|
|
72308
|
+
canRefuse: nodeCanRefuse
|
|
72309
|
+
});
|
|
72310
|
+
for (const entry of probe.recordedOutputReads ?? []) findings.performedReads.outputReads.push({
|
|
72311
|
+
entry,
|
|
72312
|
+
canRefuse: nodeCanRefuse
|
|
72313
|
+
});
|
|
72166
72314
|
const producer = recordedProducer(key, probe);
|
|
72167
72315
|
if (!producer) {
|
|
72168
72316
|
logger.debug(`Scrub of ${shownStackName}: ${where} resolved, but the resolver recorded no cdkd cross-stack read for it — the value came from a CloudFormation fallback or a cross-account arm that records nothing, so scrub cannot name a producer to classify. Not classified as a plaintext producer.`);
|
|
@@ -72278,7 +72426,11 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
72278
72426
|
const orphanSecrets = /* @__PURE__ */ new Map();
|
|
72279
72427
|
const prePassFindings = {
|
|
72280
72428
|
unverifiable: [],
|
|
72281
|
-
damagedProducerRecords: []
|
|
72429
|
+
damagedProducerRecords: [],
|
|
72430
|
+
performedReads: {
|
|
72431
|
+
imports: [],
|
|
72432
|
+
outputReads: []
|
|
72433
|
+
}
|
|
72282
72434
|
};
|
|
72283
72435
|
/**
|
|
72284
72436
|
* Leaves whose dynamic-reference scan was ABANDONED mid-token (issue
|
|
@@ -72344,6 +72496,7 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
72344
72496
|
unverifiableReads: 0,
|
|
72345
72497
|
unverifiableProducerRecords: 0,
|
|
72346
72498
|
unverifiableLeaves: 0,
|
|
72499
|
+
unrepairedReadNames: 0,
|
|
72347
72500
|
exportNameDisplay: (name) => secretSafeKeyDisplay(name, outputSecrets)
|
|
72348
72501
|
};
|
|
72349
72502
|
}
|
|
@@ -72411,7 +72564,23 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
72411
72564
|
logger
|
|
72412
72565
|
});
|
|
72413
72566
|
try {
|
|
72414
|
-
|
|
72567
|
+
const conditionContext = {
|
|
72568
|
+
...resolverContext(outputSecrets),
|
|
72569
|
+
recordedImports: [],
|
|
72570
|
+
recordedOutputReads: []
|
|
72571
|
+
};
|
|
72572
|
+
try {
|
|
72573
|
+
conditions = await resolver.evaluateConditions(conditionContext);
|
|
72574
|
+
} finally {
|
|
72575
|
+
for (const entry of conditionContext.recordedImports ?? []) prePassFindings.performedReads.imports.push({
|
|
72576
|
+
entry,
|
|
72577
|
+
canRefuse: false
|
|
72578
|
+
});
|
|
72579
|
+
for (const entry of conditionContext.recordedOutputReads ?? []) prePassFindings.performedReads.outputReads.push({
|
|
72580
|
+
entry,
|
|
72581
|
+
canRefuse: false
|
|
72582
|
+
});
|
|
72583
|
+
}
|
|
72415
72584
|
} catch (err) {
|
|
72416
72585
|
logger.debug(`Condition evaluation skipped for ${shownStack}: ${maskSecretsInText(err instanceof Error ? err.message : String(err), outputSecrets)}`);
|
|
72417
72586
|
}
|
|
@@ -72593,6 +72762,7 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
72593
72762
|
unverifiableReads: prePassFindings.unverifiable.length,
|
|
72594
72763
|
unverifiableProducerRecords: prePassFindings.damagedProducerRecords.length,
|
|
72595
72764
|
unverifiableLeaves,
|
|
72765
|
+
unrepairedReadNames: 0,
|
|
72596
72766
|
...malformedResources ? { malformedResources } : {},
|
|
72597
72767
|
...malformedOutputs ? { malformedOutputs } : {},
|
|
72598
72768
|
...malformedOrphans ? { malformedOrphans } : {},
|
|
@@ -72650,6 +72820,14 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
72650
72820
|
outputName
|
|
72651
72821
|
};
|
|
72652
72822
|
});
|
|
72823
|
+
const unrepairedReadNames = findUnrepairedCrossStackReadNames({
|
|
72824
|
+
imports: newImports,
|
|
72825
|
+
outputReads: newOutputReads
|
|
72826
|
+
}, prePassFindings.performedReads, redactCrossStackName);
|
|
72827
|
+
for (const { list, index, entry } of unrepairedReadNames) {
|
|
72828
|
+
const producer = list === "imports" ? `producer ${displayStackName(maskSecretsInText(entry.sourceStack, crossStackNeedles))}, ` : "";
|
|
72829
|
+
logger.warn(`Scrub of ${shownStack}: state.${list}[${index}] (${producer}${displayIdent(String(entry.sourceRegion))}) holds a cross-stack read name in plaintext that has the shape of a secret-bearing read in today's template but not the secret's current value — most likely a value from before the secret was ROTATED. Scrub cannot repair it (it matches only the current value) and does not print it; treat that earlier value as exposed. A deploy that updates ${shownStack} rewrites this list from the reads it performs.`);
|
|
72830
|
+
}
|
|
72653
72831
|
const newOutputs = redactUnaccountedOutputs(outputSecrets.size > 0 ? redactSecretsForState(state.outputs, outputSecrets, outputsSourceUntrusted ? void 0 : outputsTemplateSource, TEMPLATE_SOURCED_RULES) : state.outputs, state.outputs, accountedOutputKeys, allRecordedSecrets(outputSecrets, perResourceSecrets, orphanSecrets));
|
|
72654
72832
|
emitAbandonedScanNotes();
|
|
72655
72833
|
if (JSON.stringify(newOutputs) !== JSON.stringify(state.outputs)) recordsChanged++;
|
|
@@ -72673,6 +72851,7 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
72673
72851
|
unverifiableReads: prePassFindings.unverifiable.length,
|
|
72674
72852
|
unverifiableProducerRecords: prePassFindings.damagedProducerRecords.length,
|
|
72675
72853
|
unverifiableLeaves,
|
|
72854
|
+
unrepairedReadNames: unrepairedReadNames.length,
|
|
72676
72855
|
...malformedResources ? { malformedResources } : {},
|
|
72677
72856
|
...malformedOutputs ? { malformedOutputs } : {},
|
|
72678
72857
|
...malformedOrphans ? { malformedOrphans } : {},
|
|
@@ -74152,9 +74331,17 @@ async function driftCommand(stacks, options) {
|
|
|
74152
74331
|
const reports = [];
|
|
74153
74332
|
for (const ref of targetRefs) {
|
|
74154
74333
|
if (!ref.region) {
|
|
74155
|
-
const migrate =
|
|
74334
|
+
const migrate = pasteableCommand("cdkd deploy", [{
|
|
74335
|
+
value: ref.stackName,
|
|
74336
|
+
hole: "stack",
|
|
74337
|
+
opts: {
|
|
74338
|
+
patternMatched: true,
|
|
74339
|
+
plainIdent: true
|
|
74340
|
+
}
|
|
74341
|
+
}]);
|
|
74156
74342
|
const identity = stackIdentityLine(ref.stackName);
|
|
74157
|
-
|
|
74343
|
+
const clause = withheldTargetClause(migrate, "stack", "cdkd deploy");
|
|
74344
|
+
throw new Error(`A state record for this stack is a legacy one with no region, which drift cannot read. A cdkd write migrates it to the region-scoped layout; re-run drift detection after it.\n${identity ?? clause.trimStart()}\nMigrate with: ${migrate.command}`);
|
|
74158
74345
|
}
|
|
74159
74346
|
const report = await runDriftForStack(ref.stackName, ref.region, stateBackend, providerRegistry, ccApiFallback, resolvePrincipalUniqueId, options.accept || options.revert ? "refuse" : "repair");
|
|
74160
74347
|
reports.push(report);
|
|
@@ -75307,7 +75494,8 @@ async function runAccept(reports, stateBackend, stateConfig, awsClients, options
|
|
|
75307
75494
|
for (const change of outcome.changes) {
|
|
75308
75495
|
const refusal = acceptRefusalReason(change, outcome.maskedPaths);
|
|
75309
75496
|
if (refusal !== void 0) {
|
|
75310
|
-
|
|
75497
|
+
const revert = revertCommandLine(report.stackName, report.region);
|
|
75498
|
+
logger.warn(` ! ${report.stackName}/${outcome.logicalId} (${outcome.resourceType}): not accepting '${change.path}' — ${refusal}, so cdkd will not write it to ` + (revert === void 0 ? "state. Run 'cdkd drift --revert' for this stack to push the referenced value back to AWS, or re-deploy if the reference changed." : `state. Push the referenced value back to AWS with the command below, or re-deploy if the reference changed.\nRevert with: ${revert}`));
|
|
75311
75499
|
continue;
|
|
75312
75500
|
}
|
|
75313
75501
|
setAtPath(newBaseline, change.path, change.awsValue);
|
|
@@ -76706,7 +76894,8 @@ async function runRevert(reports, providerRegistry, stateBackend, stateConfig, a
|
|
|
76706
76894
|
await stateBackend.saveState(report.stackName, report.region, newState, saveOptions);
|
|
76707
76895
|
logger.info(`✓ State updated for ${report.stackName} (${report.region}): recorded the value the provider actually applied on ${recordedCount} resource(s).`);
|
|
76708
76896
|
} catch (err) {
|
|
76709
|
-
|
|
76897
|
+
const revertAgain = revertCommandLine(report.stackName, report.region);
|
|
76898
|
+
logger.warn(`Reverted ${report.stackName} (${report.region}), but could not record the value the provider actually applied: ${err instanceof Error ? err.message : String(err)}. The next 'cdkd drift' will report the same difference — ` + (revertAgain === void 0 ? `re-run 'cdkd drift --revert' for this stack once the state write can succeed.` : `re-run the command below once the state write can succeed.\nRevert with: ${revertAgain}`));
|
|
76710
76899
|
}
|
|
76711
76900
|
}
|
|
76712
76901
|
} finally {
|
|
@@ -76721,7 +76910,7 @@ async function runRevert(reports, providerRegistry, stateBackend, stateConfig, a
|
|
|
76721
76910
|
if (totalFailed > 0) summaryParts.push(`${totalFailed} failed`);
|
|
76722
76911
|
logger.info(`\nRevert summary: ${summaryParts.join(", ")}.`);
|
|
76723
76912
|
if (totalUnsupported > 0) logger.warn(`${totalUnsupported} resource(s) cannot be reverted in place — re-deploy the stack with cdkd deploy --replace, or destroy + redeploy to push the cdkd-state values back into AWS.`);
|
|
76724
|
-
if (totalFailed > 0 || totalUnsupported > 0 || totalUnresolvable > 0) throw new PartialFailureError(`Revert completed with ${totalFailed + totalUnsupported + totalUnresolvable} resource error(s) (${totalFailed} AWS update failure(s), ${totalUnsupported} update-not-supported, ${totalUnresolvable} refused or unresolvable — those never reached provider.update; each per-resource message above names its cause and remedy, e.g. missing secretsmanager:GetSecretValue / ssm:GetParameter grants for an unresolvable reference). Re-run
|
|
76913
|
+
if (totalFailed > 0 || totalUnsupported > 0 || totalUnresolvable > 0) throw new PartialFailureError(`Revert completed with ${totalFailed + totalUnsupported + totalUnresolvable} resource error(s) (${totalFailed} AWS update failure(s), ${totalUnsupported} update-not-supported, ${totalUnresolvable} refused or unresolvable — those never reached provider.update; each per-resource message above names its cause and remedy, e.g. missing secretsmanager:GetSecretValue / ssm:GetParameter grants for an unresolvable reference). Re-run cdkd drift ${commandHole("stacks...")} to see the remaining drift, then cdkd drift ${commandHole("stacks...")} --revert to retry.`);
|
|
76725
76914
|
}
|
|
76726
76915
|
function humanTextSink(json) {
|
|
76727
76916
|
return json ? {
|
|
@@ -76775,6 +76964,53 @@ function printAcceptPlan(reports, out) {
|
|
|
76775
76964
|
}
|
|
76776
76965
|
}
|
|
76777
76966
|
/**
|
|
76967
|
+
* The gated `cdkd drift ... --revert` line for a block that also carries
|
|
76968
|
+
* untrusted values, or `undefined` when either identifier cannot be named.
|
|
76969
|
+
*
|
|
76970
|
+
* go-to-k/cdkd#3307's remedy for its sites 2 and 3, closed through
|
|
76971
|
+
* go-to-k/cdkd#3436's fold-in and on exactly the derivation site 4 uses.
|
|
76972
|
+
*
|
|
76973
|
+
* The corrected go-to-k/cdkd#3486 criterion says a rendered block carrying
|
|
76974
|
+
* untrusted values carries no pasteable command, and both of these blocks do —
|
|
76975
|
+
* a property path and a resource type at one, a state-write error message at
|
|
76976
|
+
* the other. What makes the command printable anyway is the rule `main` has
|
|
76977
|
+
* for naming a target BESIDE such a block
|
|
76978
|
+
* (`.claude/rules/state-malformed-containers.md`, go-to-k/cdkd#3328):
|
|
76979
|
+
* exactness keeps a space and a `:`, so an identifier can spell one of the
|
|
76980
|
+
* block's own labels and forge it once the terminal wraps, and the answer is
|
|
76981
|
+
* `isPasteableIdent` in CONJUNCTION with the command gate, on BOTH
|
|
76982
|
+
* identifiers.
|
|
76983
|
+
*
|
|
76984
|
+
* Withheld means NOT PRINTED rather than printed with a hole: both blocks
|
|
76985
|
+
* already display the stack name, so a hole beside it invites the operator to
|
|
76986
|
+
* fill it from a name the block shows — the misdirection the criterion
|
|
76987
|
+
* forbids. The prose keeps its own `for this stack` wording in that case,
|
|
76988
|
+
* which names no command to paste.
|
|
76989
|
+
*
|
|
76990
|
+
* `exact` is not consulted: `isPasteableIdent` is strictly stronger on every
|
|
76991
|
+
* arm of the gate — it starts at an alphanumeric so is never option-shaped,
|
|
76992
|
+
* admits no `*` or `/`, cannot be empty, and its `displayIdent` compare
|
|
76993
|
+
* carries both the alteration test and the cap.
|
|
76994
|
+
*/
|
|
76995
|
+
function mayNameTarget(stackName, region) {
|
|
76996
|
+
return isPasteableIdent(stackName) && isPasteableIdent(region);
|
|
76997
|
+
}
|
|
76998
|
+
/**
|
|
76999
|
+
* The gated `cdkd drift ... --revert` line, or `undefined` when
|
|
77000
|
+
* {@link mayNameTarget} refuses either identifier.
|
|
77001
|
+
*/
|
|
77002
|
+
function revertCommandLine(stackName, region) {
|
|
77003
|
+
if (!mayNameTarget(stackName, region)) return void 0;
|
|
77004
|
+
return `${pasteableCommand("cdkd drift", [{
|
|
77005
|
+
value: stackName,
|
|
77006
|
+
hole: "stack"
|
|
77007
|
+
}, {
|
|
77008
|
+
flag: "--stack-region",
|
|
77009
|
+
value: region,
|
|
77010
|
+
hole: "region"
|
|
77011
|
+
}]).command} --revert`;
|
|
77012
|
+
}
|
|
77013
|
+
/**
|
|
76778
77014
|
* Print the planned `provider.update` calls for `--revert` (no AWS calls).
|
|
76779
77015
|
* One line per resource summarising how many property paths will be
|
|
76780
77016
|
* overwritten on the AWS side.
|
|
@@ -76817,7 +77053,16 @@ function printRevertPlan(reports, out) {
|
|
|
76817
77053
|
const word = unbaselined.length === 1 ? "value" : "values";
|
|
76818
77054
|
out.write(` ! this resource has no observed-capture baseline, so the revert pushes the raw TEMPLATE and LEAVES ${unbaselined.length} AWS-authored ${word} untouched:\n`);
|
|
76819
77055
|
for (const path of unbaselined) out.write(` ${maskSecretsInText(path, o.secrets)}\n`);
|
|
76820
|
-
|
|
77056
|
+
const refresh = mayNameTarget(report.stackName, report.region) ? pasteableCommand("cdkd state refresh-observed", [{
|
|
77057
|
+
value: report.stackName,
|
|
77058
|
+
hole: "stack"
|
|
77059
|
+
}, {
|
|
77060
|
+
flag: "--stack-region",
|
|
77061
|
+
value: report.region,
|
|
77062
|
+
hole: "region"
|
|
77063
|
+
}]) : void 0;
|
|
77064
|
+
out.write(" The template does not declare these, so cdkd cannot tell an AWS-authored value from an out-of-band change and will not reset either (issue #1626). " + (refresh === void 0 ? "Re-deploy if you want them reverted too; this record's identity cannot be named safely in a command, so none is offered.\n" : "Populate observedProperties with the command below, or re-deploy, if you want them reverted too.\n"));
|
|
77065
|
+
if (refresh !== void 0) out.write(` Populate with: ${refresh.command}\n`);
|
|
76821
77066
|
}
|
|
76822
77067
|
}
|
|
76823
77068
|
}
|
|
@@ -76991,132 +77236,36 @@ function formatScalar(value) {
|
|
|
76991
77236
|
return JSON.stringify(value);
|
|
76992
77237
|
}
|
|
76993
77238
|
/**
|
|
76994
|
-
* Why a command is not printed, phrased as the RULE rather than as a claim
|
|
76995
|
-
* about the name (m19 of the go-to-k/cdkd#3486 review). This SUPERSEDES the
|
|
76996
|
-
* m4 / m10 wording, which said the constant should name every reason the gate
|
|
76997
|
-
* has "since naming one tells the operator something false about the others" —
|
|
76998
|
-
* the enumeration is what round 4 measured as the defect.
|
|
76999
|
-
*
|
|
77000
|
-
* The earlier wording was a four-way disjunction — "does not render exactly, is
|
|
77001
|
-
* empty, is too long, or ... an option or a pattern" — which is true, but three
|
|
77002
|
-
* of the four disjuncts are visibly FALSE of a name printed on the `Stack:`
|
|
77003
|
-
* line right above it: `--all` renders exactly, is non-empty and is short. A
|
|
77004
|
-
* reader checking the sentence against what they can see concludes the tool is
|
|
77005
|
-
* guessing.
|
|
77006
|
-
*
|
|
77007
|
-
* The leading-`-` clause is stated as the GATE rather than as a parse, because
|
|
77008
|
-
* the gate is wider than Commander: `--all` really is parsed as the flag, while
|
|
77009
|
-
* a BARE `-` Commander takes positionally (measured) and this refuses it
|
|
77010
|
-
* anyway. Writing "would be read as an option" would be false of that one name.
|
|
77011
|
-
*
|
|
77012
|
-
* Naming the ACTUAL reason needs the gate to return it, and deriving it here
|
|
77013
|
-
* from a second copy of the predicates is the exact defect go-to-k/cdkd#3499
|
|
77014
|
-
* closed one file over. So this states the rule and leaves the reason to the
|
|
77015
|
-
* go-to-k/cdkd#3436 fold-in, where `pasteableCommand` supplies it.
|
|
77016
|
-
*/
|
|
77017
|
-
const WITHHELD_COMMAND_REASON = "a name is printed in a command only when it renders exactly, is non-empty, fits the reference cap, does not begin with '-', and is not a 'cdkd deploy' pattern — this one fails at least one of those.";
|
|
77018
|
-
/**
|
|
77019
|
-
* Does `value` reach the terminal as itself — sanitizing changes nothing, and
|
|
77020
|
-
* the state-reference cap does not cut it?
|
|
77021
|
-
*
|
|
77022
|
-
* Module-private and shared by {@link stackCommandFor} and
|
|
77023
|
-
* {@link stackIdentityLine}: the identity line and the command it sits above
|
|
77024
|
-
* must agree about which names are safe to print, and two spellings of this
|
|
77025
|
-
* predicate is how they would come to disagree.
|
|
77026
|
-
*/
|
|
77027
|
-
function rendersExactly(value) {
|
|
77028
|
-
if (value === "") return false;
|
|
77029
|
-
const safe = displaySafe(value, { asciiOnly: true });
|
|
77030
|
-
return safe === value && !truncateCodePoints(safe, 1152).truncated;
|
|
77031
|
-
}
|
|
77032
|
-
/**
|
|
77033
77239
|
* The `Stack: '<name>'` line that carries a record's identity NEXT TO a
|
|
77034
77240
|
* pasteable command, or `undefined` when the name cannot be printed at all.
|
|
77035
77241
|
*
|
|
77036
77242
|
* A labelled command line is a trusted-looking shape, and a stack name is an
|
|
77037
77243
|
* S3 key segment `listStacks` validates only for non-emptiness — so a name
|
|
77038
77244
|
* carrying a newline printed ABOVE one forges a second labelled line that the
|
|
77039
|
-
* operator has every reason to trust.
|
|
77040
|
-
*
|
|
77041
|
-
*
|
|
77042
|
-
*
|
|
77043
|
-
*
|
|
77044
|
-
*
|
|
77045
|
-
*
|
|
77046
|
-
*
|
|
77047
|
-
*
|
|
77048
|
-
*
|
|
77049
|
-
*
|
|
77050
|
-
*
|
|
77051
|
-
*
|
|
77245
|
+
* operator has every reason to trust.
|
|
77246
|
+
*
|
|
77247
|
+
* `isPasteableIdent`, not the command gate's exactness — M16 of the
|
|
77248
|
+
* go-to-k/cdkd#3613 review. The command gate answers the shell: a `$(...)`
|
|
77249
|
+
* name is inert inside `'...'`. This line answers what an operator READS: it
|
|
77250
|
+
* sits beside a labelled command, so it takes `isPasteableIdent` per
|
|
77251
|
+
* `state-malformed-containers.md` (go-to-k/cdkd#3328), which refuses the
|
|
77252
|
+
* space and the `:` exactness keeps — the characters a name uses to spell a
|
|
77253
|
+
* fake `Migrate with:` row once the terminal wraps. Since M17 the COMMAND
|
|
77254
|
+
* beside this line takes the same predicate (`pasteableCommand`'s
|
|
77255
|
+
* `plainIdent`), so `$(printf INJECTED)` is withheld from BOTH — an earlier
|
|
77256
|
+
* version of this comment recorded it as named by the command and withheld
|
|
77257
|
+
* here, which was true between M16 and M17 and left the command line as the
|
|
77258
|
+
* forgery's carrier.
|
|
77259
|
+
*
|
|
77260
|
+
* USED BY SITE 1 ALONE, deliberately. Sites 2–4 also print labelled commands
|
|
77261
|
+
* now (through `mayNameTarget`, `isPasteableIdent` on both identifiers), but
|
|
77262
|
+
* their blocks ALSO display the stack name in their own headers, so a separate
|
|
77263
|
+
* identity line there would be a second copy of a value the block already
|
|
77264
|
+
* shows. An earlier version of this comment said those sites "keep their
|
|
77265
|
+
* command in prose"; they did until this PR, and the sentence outlived it.
|
|
77052
77266
|
*/
|
|
77053
77267
|
function stackIdentityLine(stackName, indent = "") {
|
|
77054
|
-
return
|
|
77055
|
-
}
|
|
77056
|
-
/**
|
|
77057
|
-
* A pasteable `cdkd ...` command addressing ONE state record, or `undefined`
|
|
77058
|
-
* when this stack name cannot be named safely — in which case the caller names
|
|
77059
|
-
* the command in prose and leaves the operator to supply the name.
|
|
77060
|
-
*
|
|
77061
|
-
* Every name these messages carry comes out of an S3 KEY (`listStacks`, and the
|
|
77062
|
-
* `report.stackName` derived from it), so it is as untrusted as a state record's
|
|
77063
|
-
* body (issue [#3307](https://github.com/go-to-k/cdkd/issues/3307)). Four gates,
|
|
77064
|
-
* and each closes a different failure:
|
|
77065
|
-
*
|
|
77066
|
-
* - SANITIZE, then compare against the RAW value. `displaySafe` drops the
|
|
77067
|
-
* forgery class (C0 + DEL, `U+0085` and C1, `U+2028`/`U+2029`, the bidi
|
|
77068
|
-
* overrides), so a name carrying one is never NAMED IN A COMMAND; and a name
|
|
77069
|
-
* it ALTERED addresses a DIFFERENT record, the misdirection
|
|
77070
|
-
* `malformedDestroyResourcesRefusalMessage` and `orphanCommandFor` already
|
|
77071
|
-
* gate for. `asciiOnly` here rather than the denylist, because a stack name's
|
|
77072
|
-
* charset is the S3 key's. What this does NOT do is sanitize the identity the
|
|
77073
|
-
* surrounding prose prints: `report.stackName` reaches ~20 message sites in
|
|
77074
|
-
* this file raw, which is the DISPLAY class go-to-k/cdkd#3232 records, not
|
|
77075
|
-
* this gate's.
|
|
77076
|
-
* - CAP at `STACK_REF_MAX_CODE_POINTS`, the state-reference grammar, so a
|
|
77077
|
-
* multi-kilobyte planted name cannot grow the pasted payload without bound,
|
|
77078
|
-
* while a legitimate multi-level nested child (`Parent~Child~...`) still
|
|
77079
|
-
* renders. It bounds the PAYLOAD and nothing more — a name at the cap still
|
|
77080
|
-
* wraps across a terminal, which is `display-safe.ts`'s own caveat on the
|
|
77081
|
-
* constant (go-to-k/cdkd#3179).
|
|
77082
|
-
* - SHELL-QUOTE, and print the command LAST and UNWRAPPED on its own labelled
|
|
77083
|
-
* line. `shellQuote` is only as good as the quote context around it: inside
|
|
77084
|
-
* prose `'...'` a quoted value turns the quoting inside out and a pasted span
|
|
77085
|
-
* RUNS (measured in go-to-k/cdkd#3363; the class is go-to-k/cdkd#3436).
|
|
77086
|
-
* - REFUSE a name the COMMAND would read as something other than a name. A
|
|
77087
|
-
* leading `-` is refused CONSERVATIVELY: `--all` survives sanitizing, the cap
|
|
77088
|
-
* and quoting and is then parsed by Commander as the flag, addressing every
|
|
77089
|
-
* stack. (A BARE `-` Commander takes positionally, so the refusal is wider
|
|
77090
|
-
* than the parse — the gate is "starts with `-`", not "parses as an option".)
|
|
77091
|
-
* And `cdkd deploy` matches its argument as a PATTERN
|
|
77092
|
-
* (`src/cli/stack-matcher.ts`), where `*` is a wildcard and `/` selects by
|
|
77093
|
-
* display path. `patternMatched` asks for the last two; `/` cannot arrive
|
|
77094
|
-
* through a key (`listStacks` splits keys on it), so that half is defensive.
|
|
77095
|
-
*
|
|
77096
|
-
* **`region` and `flags` have NO production caller today, and neither does
|
|
77097
|
-
* `stackIdentityLine`'s `indent`** (M16 / m17 of the go-to-k/cdkd#3486 review;
|
|
77098
|
-
* the one call site is the legacy region-less refusal, which has no region by
|
|
77099
|
-
* definition and passes only `patternMatched`). They are kept, with their
|
|
77100
|
-
* cases, as the landing place for the three `cdkd drift` sites
|
|
77101
|
-
* go-to-k/cdkd#3436 owns — the `--stack-region` requirement go-to-k/cdkd#3307
|
|
77102
|
-
* states for `:6139` is exactly what `region` exists to satisfy. Read their
|
|
77103
|
-
* hazard-matrix cases as a SPECIFICATION for that landing, not as coverage of
|
|
77104
|
-
* a live path. `region` takes the same gates as the NAME — sanitize,
|
|
77105
|
-
* exactness, the cap, emptiness and the leading `-` — because a region is a
|
|
77106
|
-
* key SEGMENT, no more trusted than the name.
|
|
77107
|
-
*
|
|
77108
|
-
* Exported for `tests/unit/cli/drift.test.ts`, which drives the hazard matrix
|
|
77109
|
-
* through it directly; the one call site is driven through the CLI separately,
|
|
77110
|
-
* since what a site PASSES is not something a helper test can see.
|
|
77111
|
-
*/
|
|
77112
|
-
function stackCommandFor(command, stackName, opts = {}) {
|
|
77113
|
-
if (!rendersExactly(stackName) || stackName.startsWith("-")) return void 0;
|
|
77114
|
-
if (opts.patternMatched && (stackName.includes("*") || stackName.includes("/"))) return void 0;
|
|
77115
|
-
if (opts.region !== void 0 && (!rendersExactly(opts.region) || opts.region.startsWith("-"))) return;
|
|
77116
|
-
const parts = [command, shellQuote(stackName)];
|
|
77117
|
-
if (opts.flags !== void 0) parts.push(opts.flags);
|
|
77118
|
-
if (opts.region !== void 0) parts.push(`--stack-region ${shellQuote(opts.region)}`);
|
|
77119
|
-
return parts.join(" ");
|
|
77268
|
+
return isPasteableIdent(stackName) ? `${indent}Stack: ${shellQuote(stackName)}` : void 0;
|
|
77120
77269
|
}
|
|
77121
77270
|
/**
|
|
77122
77271
|
* Reusable `--stack-region <region>` option (mirrors `state show`).
|
|
@@ -77496,7 +77645,7 @@ async function destroyCommand(stackArgs, options) {
|
|
|
77496
77645
|
* Create destroy command
|
|
77497
77646
|
*/
|
|
77498
77647
|
function createDestroyCommand() {
|
|
77499
|
-
const cmd = new Command("destroy").description("Destroy all resources in the stack").argument("[stacks...]", "Stack name(s) to destroy. Accepts physical CloudFormation names (e.g. 'MyStage-Api') or CDK display paths (e.g. 'MyStage/Api'). Supports wildcards (e.g. 'MyStage/*').").option("--all", "Destroy all stacks", false).option("--purge-events",
|
|
77648
|
+
const cmd = new Command("destroy").description("Destroy all resources in the stack").argument("[stacks...]", "Stack name(s) to destroy. Accepts physical CloudFormation names (e.g. 'MyStage-Api') or CDK display paths (e.g. 'MyStage/Api'). Supports wildcards (e.g. 'MyStage/*').").option("--all", "Destroy all stacks", false).option("--purge-events", `After a clean destroy, also delete the stack's deployment-event history (issue #808 store) so an object listing of the state bucket comes back empty. Where the state bucket is versioned — which cdkd bootstrap enables — earlier versions of those keys survive and stay readable with GetObject and a VersionId. By default events survive destroy as post-mortem context. Skipped when the destroy fails or is interrupted (those events aid the retry). Equivalent for an already-destroyed stack: cdkd events prune ${commandHole("stack")} --all.`, false).action(withErrorHandling(destroyCommand));
|
|
77500
77649
|
[
|
|
77501
77650
|
...commonOptions,
|
|
77502
77651
|
...appOptions,
|
|
@@ -78490,37 +78639,6 @@ function routeDestinationNormalizationIsModelled(value) {
|
|
|
78490
78639
|
return canonicalizeIpv4Cidr(value) !== void 0 || ROUTE_PREFIX_LIST_ID_PATTERN.test(value);
|
|
78491
78640
|
}
|
|
78492
78641
|
/**
|
|
78493
|
-
* Return the host-bit-cleared form of an IPv4 CIDR (`100.68.0.18/18` ->
|
|
78494
|
-
* `100.68.0.0/18`), or `undefined` when the input is not an IPv4 CIDR at all
|
|
78495
|
-
* (an IPv6 CIDR, a `pl-…` prefix-list id, or anything malformed).
|
|
78496
|
-
*
|
|
78497
|
-
* This exists to recognize the ONE benign reason an `AWS::EC2::Route`'s stored
|
|
78498
|
-
* destination can differ from its physicalId segment: AWS rewrites a
|
|
78499
|
-
* non-canonical CIDR on `CreateRoute`, and the Cloud Control path records what
|
|
78500
|
-
* AWS returned while the template kept what the user wrote. Returning
|
|
78501
|
-
* `undefined` for the shapes it does not model is load-bearing — the caller
|
|
78502
|
-
* uses it to decide whether a divergence is conclusive or merely unexplained.
|
|
78503
|
-
*/
|
|
78504
|
-
function canonicalizeIpv4Cidr(value) {
|
|
78505
|
-
const match = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\/(\d{1,2})$/.exec(value);
|
|
78506
|
-
if (!match) return void 0;
|
|
78507
|
-
const octets = [
|
|
78508
|
-
match[1],
|
|
78509
|
-
match[2],
|
|
78510
|
-
match[3],
|
|
78511
|
-
match[4]
|
|
78512
|
-
].map(Number);
|
|
78513
|
-
const prefixLength = Number(match[5]);
|
|
78514
|
-
if (prefixLength > 32 || octets.some((octet) => octet > 255)) return void 0;
|
|
78515
|
-
const network = ((octets[0] << 24 | octets[1] << 16 | octets[2] << 8 | octets[3]) >>> 0 & (prefixLength === 0 ? 0 : 4294967295 << 32 - prefixLength >>> 0)) >>> 0;
|
|
78516
|
-
return `${[
|
|
78517
|
-
network >>> 24,
|
|
78518
|
-
network >>> 16 & 255,
|
|
78519
|
-
network >>> 8 & 255,
|
|
78520
|
-
network & 255
|
|
78521
|
-
].join(".")}/${prefixLength}`;
|
|
78522
|
-
}
|
|
78523
|
-
/**
|
|
78524
78642
|
* Build a splitter for an `AWS::ApiGateway::*` child type whose CFn primary
|
|
78525
78643
|
* identifier is the parent `RestApiId` plus one child field.
|
|
78526
78644
|
*
|
|
@@ -79049,7 +79167,48 @@ async function resolveIdentifierValue(entry, ctx, deps) {
|
|
|
79049
79167
|
* today and would never stop being blocked by a re-import.
|
|
79050
79168
|
*/
|
|
79051
79169
|
function maskedIdentifierAttributeReason(field, logicalId) {
|
|
79052
|
-
return `cdkd state holds only the redaction mask ('***') at attributes.${field} for
|
|
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.\nRepair with: ${importRepairCommand(logicalId)}`;
|
|
79171
|
+
}
|
|
79172
|
+
/**
|
|
79173
|
+
* The `cdkd import` line `maskedIdentifierAttributeReason` tells the operator
|
|
79174
|
+
* to run.
|
|
79175
|
+
*
|
|
79176
|
+
* It is a named helper for ONE caller on purpose. A SECOND site prints the same
|
|
79177
|
+
* remedy — `buildImportPlan`'s resolved-identifier refusal — written
|
|
79178
|
+
* independently, and it still carries go-to-k/cdkd#3363's shape: a prose
|
|
79179
|
+
* `'...'` span holding a `cdkd` verb AND an interpolation, its opening quote in
|
|
79180
|
+
* one concatenated literal and its interpolation in the next. The source fence
|
|
79181
|
+
* found it only once its `+` runs were folded; a grep for the gate's name never
|
|
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.
|
|
79189
|
+
*
|
|
79190
|
+
* The POSITIONAL is a hole on purpose, and the load-bearing half is what it is
|
|
79191
|
+
* NOT: an earlier cut passed the LOGICAL ID there, producing a command that
|
|
79192
|
+
* names a resource where `cdkd import`'s declared `[stack]` goes. No shape
|
|
79193
|
+
* check can see that — both spellings are equally well-formed to one — and only
|
|
79194
|
+
* reading the command can.
|
|
79195
|
+
*
|
|
79196
|
+
* It is a hole rather than a name because its caller,
|
|
79197
|
+
* {@link maskedIdentifierAttributeReason}, has no stack name in scope at all.
|
|
79198
|
+
* (`buildImportPlan` does have one, so when that site joins this helper it
|
|
79199
|
+
* could fill it — a separate change with its own gating question, and not a
|
|
79200
|
+
* reason to grow two spellings here.)
|
|
79201
|
+
*/
|
|
79202
|
+
function importRepairCommand(logicalId) {
|
|
79203
|
+
const named = isPasteableIdent(logicalId);
|
|
79204
|
+
return `${pasteableCommand("cdkd import", [{ hole: "stack" }, named ? {
|
|
79205
|
+
flag: "--resource",
|
|
79206
|
+
value: logicalId,
|
|
79207
|
+
hole: "logicalId"
|
|
79208
|
+
} : {
|
|
79209
|
+
flag: "--resource",
|
|
79210
|
+
hole: "logicalId"
|
|
79211
|
+
}]).command}=${commandHole("physicalId")} --force`;
|
|
79053
79212
|
}
|
|
79054
79213
|
/**
|
|
79055
79214
|
* Build the {@link CompositePhysicalIdIdentifier} for a type whose CFn
|
|
@@ -79623,7 +79782,7 @@ function safeDetail(value) {
|
|
|
79623
79782
|
*/
|
|
79624
79783
|
function orphanCommandFor(stackName, region) {
|
|
79625
79784
|
const shownStack = safeSegment(stackName);
|
|
79626
|
-
if (!(typeof stackName === "string" && shownStack === stackName && !stackName.startsWith("-") && typeof region === "string" && safeSegment(region) === region && !region.startsWith("-"))) return
|
|
79785
|
+
if (!(typeof stackName === "string" && shownStack === stackName && !stackName.startsWith("-") && typeof region === "string" && safeSegment(region) === region && !region.startsWith("-"))) return `cdkd state orphan ${commandHole("stack")} --stack-region ${commandHole("region")} — spelled out because this record's name or region does NOT render exactly, so another record may render identically; list them as stored with 'cdkd state list --long' and act on the one whose key matches`;
|
|
79627
79786
|
return `cdkd state orphan ${shellQuote(shownStack)} --stack-region ${shellQuote(safeSegment(region))}`;
|
|
79628
79787
|
}
|
|
79629
79788
|
/**
|
|
@@ -79981,7 +80140,7 @@ async function buildImportPlan(state, template, cfnClient, parentStackName, opti
|
|
|
79981
80140
|
blocked.push({
|
|
79982
80141
|
logicalId,
|
|
79983
80142
|
resourceType,
|
|
79984
|
-
reason:
|
|
80143
|
+
reason: `cdkd state holds only the redaction mask ('***') for at least one property, and cdkd cannot re-derive the value. There are two ways a record comes to hold it. (1) A NoEcho custom-resource value: forcing the custom resource to update does NOT clear this — the handler supplies the value to the deploy and cdkd re-masks it on the way into state, so the export still has nothing to declare. Stop setting NoEcho on that response and re-deploy, then export again. (2) The value was SPLICED from a masked record of ANOTHER resource — by 'cdkd orphan --force', or by 'cdkd import' resolving an Fn::GetAtt or a Ref over a value the Cloud Control fallback had masked. Repair the record that HOLDS the mask with cdkd import ${commandHole("stack")} --resource ${commandHole("logicalId")}=${commandHole("physicalId")} --force (granting cloudformation:DescribeType first if the import warned that it could not read the schema), then re-run whichever command wrote this property. Either way you can also export this stack without that resource and adopt it into CloudFormation by hand. See https://github.com/go-to-k/cdkd/issues/2274.`
|
|
79985
80144
|
});
|
|
79986
80145
|
continue;
|
|
79987
80146
|
}
|
|
@@ -81596,7 +81755,7 @@ async function runPerStackImportLoop(args) {
|
|
|
81596
81755
|
}
|
|
81597
81756
|
if (stateDeletionFailures.length > 0) {
|
|
81598
81757
|
const lines = stateDeletionFailures.map((f) => ` - cdkd/${safeSegment(f.stackName)}/${safeSegment(f.region)}/state.json: ${safeDetail(f.reason)}`).join("\n");
|
|
81599
|
-
throw new Error(`${stateDeletionFailures.length} cdkd state record(s) could not be deleted after a successful per-stack IMPORT loop. Every stack in the tree IS CFn-managed (the migration succeeded AWS-side); orphan state remains under:\n${lines}\nRecover with
|
|
81758
|
+
throw new Error(`${stateDeletionFailures.length} cdkd state record(s) could not be deleted after a successful per-stack IMPORT loop. Every stack in the tree IS CFn-managed (the migration succeeded AWS-side); orphan state remains under:\n${lines}\nRecover with the command below, once per record.\nRecover with: cdkd state orphan ${commandHole("stack")} --stack-region ${commandHole("region")}`);
|
|
81600
81759
|
}
|
|
81601
81760
|
if (sessionIntrinsicSkipped.size > 0) {
|
|
81602
81761
|
const detail = [...sessionIntrinsicSkipped.entries()].map(([cdkdName, params]) => `${safeSegment(cdkdName)} (${params.join(", ")})`).join("; ");
|
|
@@ -82038,6 +82197,25 @@ function safe$1(value) {
|
|
|
82038
82197
|
return displaySafe(value, { asciiOnly: true }) || "<unrenderable>";
|
|
82039
82198
|
}
|
|
82040
82199
|
/**
|
|
82200
|
+
* `state resources` / `state show` refusing a legacy region-less record. The
|
|
82201
|
+
* name is the operator's own positional, rendered through `safe` in the prose;
|
|
82202
|
+
* the `cdkd deploy` beside the labelled line takes `plainIdent`, as
|
|
82203
|
+
* `refresh-observed`'s legacy refusal does (go-to-k/cdkd#3696), so all three
|
|
82204
|
+
* decide "may I name this target" by one predicate and explain a hole with the
|
|
82205
|
+
* gate's own reason.
|
|
82206
|
+
*/
|
|
82207
|
+
function legacyRecordRefusal(stackName) {
|
|
82208
|
+
const migrate = pasteableCommand("cdkd deploy", [{
|
|
82209
|
+
value: stackName,
|
|
82210
|
+
hole: "stack",
|
|
82211
|
+
opts: {
|
|
82212
|
+
patternMatched: true,
|
|
82213
|
+
plainIdent: true
|
|
82214
|
+
}
|
|
82215
|
+
}]);
|
|
82216
|
+
return /* @__PURE__ */ new Error(`Stack '${safe$1(stackName)}' has only a legacy state record without a region. A cdkd write migrates it to the region-scoped layout; re-run this command after it.` + withheldTargetClause(migrate, "stack", "cdkd deploy") + `\nMigrate with: ${migrate.command}`);
|
|
82217
|
+
}
|
|
82218
|
+
/**
|
|
82041
82219
|
* Resolve a stack name + optional region flag against the `listStacks` index
|
|
82042
82220
|
* built up front. When a name resolves to multiple regions and the caller
|
|
82043
82221
|
* didn't pin one, surface a clear error listing the candidates so the user
|
|
@@ -82289,11 +82467,7 @@ async function stateResourcesCommand(stackName, options) {
|
|
|
82289
82467
|
const setup = await setupStateBackend(options);
|
|
82290
82468
|
try {
|
|
82291
82469
|
const ref = resolveSingleRegion(stackName, await setup.stateBackend.listStacks(), options.stackRegion);
|
|
82292
|
-
if (!ref.region) throw
|
|
82293
|
-
value: stackName,
|
|
82294
|
-
hole: "stack",
|
|
82295
|
-
opts: { patternMatched: true }
|
|
82296
|
-
}]).command}`);
|
|
82470
|
+
if (!ref.region) throw legacyRecordRefusal(stackName);
|
|
82297
82471
|
const stateResult = await setup.stateBackend.getState(stackName, ref.region);
|
|
82298
82472
|
if (!stateResult) throw new Error(`No state found for stack '${safe$1(stackName)}' (${safe$1(ref.region)}) in s3://${setup.bucket}/${setup.prefix}/. Run 'cdkd state list' to see available stacks.`);
|
|
82299
82473
|
if (repairMalformedResourcesForReadOnly(stateResult.state)) logger.warn(malformedResourcesWarning(stackName, ref.region));
|
|
@@ -82500,11 +82674,7 @@ async function stateShowCommand(stackName, options) {
|
|
|
82500
82674
|
const setup = await setupStateBackend(options);
|
|
82501
82675
|
try {
|
|
82502
82676
|
const ref = resolveSingleRegion(stackName, await setup.stateBackend.listStacks(), options.stackRegion);
|
|
82503
|
-
if (!ref.region) throw
|
|
82504
|
-
value: stackName,
|
|
82505
|
-
hole: "stack",
|
|
82506
|
-
opts: { patternMatched: true }
|
|
82507
|
-
}]).command}`);
|
|
82677
|
+
if (!ref.region) throw legacyRecordRefusal(stackName);
|
|
82508
82678
|
const [stateResult, lockInfo] = await Promise.all([setup.stateBackend.getState(stackName, ref.region), setup.lockManager.getLockInfo(stackName, ref.region)]);
|
|
82509
82679
|
if (!stateResult) throw new Error(`No state found for stack '${safe$1(stackName)}' (${safe$1(ref.region)}) in s3://${setup.bucket}/${setup.prefix}/. Run 'cdkd state list' to see available stacks.`);
|
|
82510
82680
|
if (options.showNested) {
|
|
@@ -82944,7 +83114,7 @@ function createStateShowCommand() {
|
|
|
82944
83114
|
async function stateOrphanCommand(stackArgs, options) {
|
|
82945
83115
|
const logger = getLogger();
|
|
82946
83116
|
if (options.verbose) logger.setLevel("debug");
|
|
82947
|
-
if (stackArgs.length === 0) throw new Error(
|
|
83117
|
+
if (stackArgs.length === 0) throw new Error(`Stack name is required. Usage: cdkd state orphan ${commandHole("stacks...")}`);
|
|
82948
83118
|
const setup = await setupStateBackend(options);
|
|
82949
83119
|
try {
|
|
82950
83120
|
const refs = await setup.stateBackend.listStacks();
|
|
@@ -82972,11 +83142,15 @@ async function stateOrphanCommand(stackArgs, options) {
|
|
|
82972
83142
|
}
|
|
82973
83143
|
if (!options.yes && !options.force) {
|
|
82974
83144
|
const targetList = targets.map((t) => formatStackRefSafe(t)).join(", ");
|
|
82975
|
-
|
|
83145
|
+
const destroyCmd = pasteableCommand("cdkd destroy", [{
|
|
82976
83146
|
value: stackName,
|
|
82977
83147
|
hole: "stack",
|
|
82978
|
-
opts: {
|
|
82979
|
-
|
|
83148
|
+
opts: {
|
|
83149
|
+
patternMatched: true,
|
|
83150
|
+
plainIdent: true
|
|
83151
|
+
}
|
|
83152
|
+
}]);
|
|
83153
|
+
process.stdout.write(`\nWARNING: This removes cdkd's state record for [${targetList}] only. AWS resources will NOT be deleted.\nDelete the actual resources instead with the command below.` + withheldTargetClause(destroyCmd, "stack", "cdkd destroy") + `\nDestroy with: ${destroyCmd.command}\n\n`);
|
|
82980
83154
|
if (!await confirmStateOrphanRemoval(`Remove state for ${targetList} from s3://${setup.bucket}/${setup.prefix}/?`)) {
|
|
82981
83155
|
logger.info(`Cancelled removal of state for stack: ${stackName}`);
|
|
82982
83156
|
continue;
|
|
@@ -83068,7 +83242,7 @@ async function stateDestroyCommand(stackArgs, options) {
|
|
|
83068
83242
|
}
|
|
83069
83243
|
validateResourceTimeouts(options);
|
|
83070
83244
|
setResolvedResourceTimeouts(options.resourceTimeout);
|
|
83071
|
-
if (!options.all && stackArgs.length === 0) throw new Error(
|
|
83245
|
+
if (!options.all && stackArgs.length === 0) throw new Error(`Stack name is required. Usage: cdkd state destroy ${commandHole("stacks...")} | --all`);
|
|
83072
83246
|
const setup = await setupStateBackend(options);
|
|
83073
83247
|
const providerRegistry = new ProviderRegistry();
|
|
83074
83248
|
registerAllProviders(providerRegistry);
|
|
@@ -83509,67 +83683,11 @@ function createStateInfoCommand() {
|
|
|
83509
83683
|
}
|
|
83510
83684
|
/**
|
|
83511
83685
|
* The hole the legacy refusal's `cdkd deploy` prints for a name it cannot
|
|
83512
|
-
* name, and the key {@link
|
|
83686
|
+
* name, and the key {@link withheldTargetClause} reads the reason back by. ONE
|
|
83513
83687
|
* spelling so the two cannot drift apart (m22 of the go-to-k/cdkd#3499 review).
|
|
83514
83688
|
*/
|
|
83515
83689
|
const STACK_HOLE = "stack";
|
|
83516
83690
|
/**
|
|
83517
|
-
* The sentence for a name `pasteableCommand` would not print, rendered from the
|
|
83518
|
-
* REASON it gave rather than from a predicate of this site's own — M11 of the
|
|
83519
|
-
* go-to-k/cdkd#3499 review. Keying it on a second predicate got both directions
|
|
83520
|
-
* wrong at once: `Old;Stack` renders exactly, so a rendering-based clause called
|
|
83521
|
-
* a command that names it "not exact", and `--all` also renders exactly, so the
|
|
83522
|
-
* same clause said nothing above a hole the operator was then invited to fill
|
|
83523
|
-
* with the name printed beside it.
|
|
83524
|
-
*
|
|
83525
|
-
* THREE of the five reasons are reachable from this call site, and the other
|
|
83526
|
-
* two are bounded out by where the name comes from — an S3 key segment:
|
|
83527
|
-
*
|
|
83528
|
-
* - `altered`, `option-shaped` and `pattern-shaped` are all reachable: a
|
|
83529
|
-
* planted key can spell a name any of those ways in a handful of bytes.
|
|
83530
|
-
* - `empty` is not. `listStacks` drops a key whose stack segment is empty
|
|
83531
|
-
* (`s3-state-backend.ts`'s `if (!stackName) continue`), so `target.stackName`
|
|
83532
|
-
* is non-empty by the time the refusal is built.
|
|
83533
|
-
* - `too-long` is not either, and the bound is not obvious: the cap is
|
|
83534
|
-
* `STACK_REF_MAX_CODE_POINTS` (1152), while S3 caps the WHOLE key at 1024
|
|
83535
|
-
* bytes, leaving at most 1008 for the name inside `cdkd/<name>/state.json`.
|
|
83536
|
-
* A multi-byte character only lowers the code-point count further, so a name
|
|
83537
|
-
* arriving through `listStacks` can never reach the cap.
|
|
83538
|
-
*
|
|
83539
|
-
* Both unreachable arms stay, and are covered, because the REASON is the
|
|
83540
|
-
* gate's and not this site's: `pasteableCommand` can return either to a caller
|
|
83541
|
-
* whose value comes from somewhere else. A missing arm is no longer a silent
|
|
83542
|
-
* fall-through — the `switch` below is exhaustive over `WithholdReason`, so
|
|
83543
|
-
* dropping one is a compile error (M13). What the cases buy on top of that is
|
|
83544
|
-
* the SENTENCE: the type checker knows an arm exists, not that it says the
|
|
83545
|
-
* right thing, and substituting one arm's text for another's is exactly the
|
|
83546
|
-
* disagreement M11 closed.
|
|
83547
|
-
*/
|
|
83548
|
-
function withheldNameClause(built) {
|
|
83549
|
-
const reason = built.withheld.find((w) => w.hole === STACK_HOLE)?.reason;
|
|
83550
|
-
if (reason === void 0) return "";
|
|
83551
|
-
let why;
|
|
83552
|
-
switch (reason) {
|
|
83553
|
-
case "altered":
|
|
83554
|
-
why = `does NOT render exactly, so another record may render identically`;
|
|
83555
|
-
break;
|
|
83556
|
-
case "empty":
|
|
83557
|
-
why = `is empty`;
|
|
83558
|
-
break;
|
|
83559
|
-
case "too-long":
|
|
83560
|
-
why = `is too long to print`;
|
|
83561
|
-
break;
|
|
83562
|
-
case "option-shaped":
|
|
83563
|
-
why = "begins with a '-', so it is not safe to print as an argument to 'cdkd deploy' — a name like '--all' is parsed as the FLAG and targets every stack";
|
|
83564
|
-
break;
|
|
83565
|
-
case "pattern-shaped":
|
|
83566
|
-
why = `would be read as a PATTERN by 'cdkd deploy', which can match other stacks`;
|
|
83567
|
-
break;
|
|
83568
|
-
default: throw new Error(`withheldNameClause: unhandled WithholdReason ${String(reason)}`);
|
|
83569
|
-
}
|
|
83570
|
-
return ` This record's name ${why} — so it is not named in the command below; list the records as stored with 'cdkd state list --long' and act on the one whose key matches.`;
|
|
83571
|
-
}
|
|
83572
|
-
/**
|
|
83573
83691
|
* `cdkd state refresh-observed <stack>` command implementation.
|
|
83574
83692
|
*
|
|
83575
83693
|
* Walks every resource in the given stack(s) and refreshes its
|
|
@@ -83589,10 +83707,28 @@ function withheldNameClause(built) {
|
|
|
83589
83707
|
*
|
|
83590
83708
|
* Behavior:
|
|
83591
83709
|
* - Acquires a per-stack lock (scope: `state-refresh-observed`).
|
|
83592
|
-
* - Calls
|
|
83593
|
-
*
|
|
83594
|
-
*
|
|
83595
|
-
*
|
|
83710
|
+
* - Calls `provider.readCurrentState` in parallel (Promise.all) for the
|
|
83711
|
+
* resources that REACH it. FOUR paths do not, and review had to correct
|
|
83712
|
+
* this sentence twice — first from "every resource", then from three arms
|
|
83713
|
+
* to four. A resource whose record carries `observedBaselineRefused` (v10)
|
|
83714
|
+
* is SKIPPED before the provider is consulted and warned about separately,
|
|
83715
|
+
* since refreshing it could persist a resolved secret in plaintext. The
|
|
83716
|
+
* other three all count as `unsupported`: a type
|
|
83717
|
+
* `ProviderRegistry.shouldSkipResource` declines (returning before the
|
|
83718
|
+
* lookup), a type with no registered provider, and a provider that does not
|
|
83719
|
+
* implement `readCurrentState`. A per-resource failure is
|
|
83720
|
+
* COUNTED and logged at
|
|
83721
|
+
* `warn` naming the resource and the error, the rest of the stack is
|
|
83722
|
+
* still refreshed and saved, and the affected resource keeps whatever
|
|
83723
|
+
* `observedProperties` it already had (or none). So drift keeps
|
|
83724
|
+
* comparing against that RETAINED baseline where one exists, and falls
|
|
83725
|
+
* back to `properties` only where there is none — review caught the
|
|
83726
|
+
* unqualified claim, which said it always falls back. The run
|
|
83727
|
+
* then ends in `PartialFailureError` (exit 2) naming the count, which
|
|
83728
|
+
* is what distinguishes it from a crash. (This block travelled here
|
|
83729
|
+
* from `src/utils/pasteable-command.ts`, where it documented nothing;
|
|
83730
|
+
* review measured that it also described the old, swallow-and-debug
|
|
83731
|
+
* behaviour rather than the current one.)
|
|
83596
83732
|
* - Writes state with optimistic locking (`expectedEtag`).
|
|
83597
83733
|
* - Prints a per-stack summary: `N refreshed, M unsupported, K failed`.
|
|
83598
83734
|
*
|
|
@@ -83608,7 +83744,7 @@ function withheldNameClause(built) {
|
|
|
83608
83744
|
async function stateRefreshObservedCommand(stackArgs, options) {
|
|
83609
83745
|
const logger = getLogger();
|
|
83610
83746
|
if (options.verbose) logger.setLevel("debug");
|
|
83611
|
-
if (!options.all && stackArgs.length === 0) throw new Error(
|
|
83747
|
+
if (!options.all && stackArgs.length === 0) throw new Error(`Stack name is required. Usage: cdkd state refresh-observed ${commandHole("stacks...")} | --all`);
|
|
83612
83748
|
const setup = await setupStateBackend(options);
|
|
83613
83749
|
const providerRegistry = new ProviderRegistry();
|
|
83614
83750
|
registerAllProviders(providerRegistry);
|
|
@@ -83659,13 +83795,16 @@ async function stateRefreshObservedCommand(stackArgs, options) {
|
|
|
83659
83795
|
}
|
|
83660
83796
|
}
|
|
83661
83797
|
for (const target of targets) if (!target.region) {
|
|
83662
|
-
const
|
|
83798
|
+
const subject = isPasteableIdent(target.stackName) ? `Stack ${target.stackName}` : `A stack whose name is not a plain identifier (see 'cdkd state list --long')`;
|
|
83663
83799
|
const migrate = pasteableCommand("cdkd deploy", [{
|
|
83664
83800
|
value: target.stackName,
|
|
83665
83801
|
hole: STACK_HOLE,
|
|
83666
|
-
opts: {
|
|
83802
|
+
opts: {
|
|
83803
|
+
patternMatched: true,
|
|
83804
|
+
plainIdent: true
|
|
83805
|
+
}
|
|
83667
83806
|
}]);
|
|
83668
|
-
throw new Error(
|
|
83807
|
+
throw new Error(`${subject} has only a legacy state record without a region. Migrate it to the region-scoped layout with any cdkd write, then re-run refresh-observed.` + withheldTargetClause(migrate, STACK_HOLE, "cdkd deploy") + `\nMigrate with: ${migrate.command}`);
|
|
83669
83808
|
}
|
|
83670
83809
|
let totalRefreshed = 0;
|
|
83671
83810
|
let totalUnsupported = 0;
|
|
@@ -92177,7 +92316,7 @@ async function waitForRieReady(host, port, timeoutMs = 5e3) {
|
|
|
92177
92316
|
await setTimeout$1(100);
|
|
92178
92317
|
}
|
|
92179
92318
|
const tail = lastError instanceof Error ? `: ${lastError.message}` : "";
|
|
92180
|
-
throw new Error(`RIE did not become ready on ${host}
|
|
92319
|
+
throw new Error(`RIE did not become ready on ${host} port ${port} within ${timeoutMs}ms${tail}. The container may have exited early — check 'docker logs' output.`);
|
|
92181
92320
|
}
|
|
92182
92321
|
/**
|
|
92183
92322
|
* Issue a tiny HTTP request to confirm RIE's HTTP listener is up (not
|
|
@@ -92189,7 +92328,7 @@ async function httpProbe(host, port, timeoutMs) {
|
|
|
92189
92328
|
const controller = new AbortController();
|
|
92190
92329
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
92191
92330
|
try {
|
|
92192
|
-
await (await fetch(`http://${host
|
|
92331
|
+
await (await fetch(`http://${formatAuthority(host, port)}/`, {
|
|
92193
92332
|
method: "POST",
|
|
92194
92333
|
headers: { "Content-Type": "application/json" },
|
|
92195
92334
|
body: "{}",
|
|
@@ -92231,7 +92370,7 @@ function isTransientNetworkError(err) {
|
|
|
92231
92370
|
* the timeout in v1, but it's the right ballpark.
|
|
92232
92371
|
*/
|
|
92233
92372
|
async function invokeRie(host, port, event, timeoutMs) {
|
|
92234
|
-
const url = `http://${host
|
|
92373
|
+
const url = `http://${formatAuthority(host, port)}${INVOKE_PATH}`;
|
|
92235
92374
|
const body = JSON.stringify(event ?? {});
|
|
92236
92375
|
const controller = new AbortController();
|
|
92237
92376
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
@@ -93272,6 +93411,14 @@ function clampConcurrency(input) {
|
|
|
93272
93411
|
//#endregion
|
|
93273
93412
|
//#region src/cli/commands/local-start-api.ts
|
|
93274
93413
|
/**
|
|
93414
|
+
* The `Server listening on <url> (<label>)` ready banner. Integ fixtures
|
|
93415
|
+
* grep this prefix and read the port out of it, and users paste the URL into
|
|
93416
|
+
* curl / `wscat`, so an IPv6 host must be bracketed or the URL does not parse.
|
|
93417
|
+
*/
|
|
93418
|
+
function formatServerListeningBanner(scheme, host, port, pathSuffix, label) {
|
|
93419
|
+
return `Server listening on ${scheme}://${formatAuthority(host, port)}${pathSuffix} (${label})\n`;
|
|
93420
|
+
}
|
|
93421
|
+
/**
|
|
93275
93422
|
* `cdkd local start-api` — long-running local HTTP server that maps
|
|
93276
93423
|
* synthesized API routes to Lambda invocations against the AWS Lambda
|
|
93277
93424
|
* Runtime Interface Emulator (Docker required).
|
|
@@ -93604,10 +93751,10 @@ async function localStartApiCommand(target, options) {
|
|
|
93604
93751
|
warnUnsupportedRoutes(allRoutes, logger);
|
|
93605
93752
|
warnSsrfRiskyIntegrations(allRoutes, logger);
|
|
93606
93753
|
logger.info(`Per-Lambda concurrency: ${perLambdaConcurrency} (override with --per-lambda-concurrency)`);
|
|
93607
|
-
for (const { group, server } of servers) process.stdout.write(
|
|
93754
|
+
for (const { group, server } of servers) process.stdout.write(formatServerListeningBanner(server.scheme, server.host, server.port, "", group.displayName));
|
|
93608
93755
|
for (const ws of wsServers) {
|
|
93609
93756
|
const scheme = ws.server.scheme === "https" ? "wss" : "ws";
|
|
93610
|
-
process.stdout.write(
|
|
93757
|
+
process.stdout.write(formatServerListeningBanner(scheme, ws.server.host, ws.server.port, ws.apiPath, `${ws.api.apiLogicalId} (WebSocket API)`));
|
|
93611
93758
|
}
|
|
93612
93759
|
process.stdout.write("^C to stop and clean up containers.\n");
|
|
93613
93760
|
let watcher;
|
|
@@ -94609,7 +94756,7 @@ function filterSpecsForGroup(group, allSpecs) {
|
|
|
94609
94756
|
*/
|
|
94610
94757
|
function printPerServerRouteTables(servers) {
|
|
94611
94758
|
for (const { group, server } of servers) {
|
|
94612
|
-
process.stdout.write(`\n${group.displayName} (http://${server.host
|
|
94759
|
+
process.stdout.write(`\n${group.displayName} (http://${formatAuthority(server.host, server.port)})\n`);
|
|
94613
94760
|
printRouteTable(group.routes);
|
|
94614
94761
|
}
|
|
94615
94762
|
}
|
|
@@ -99144,4 +99291,4 @@ function buildProgram() {
|
|
|
99144
99291
|
|
|
99145
99292
|
//#endregion
|
|
99146
99293
|
export { buildProgram };
|
|
99147
|
-
//# sourceMappingURL=program-
|
|
99294
|
+
//# sourceMappingURL=program-WCBWtvb0.js.map
|