@go-to-k/cdkd 0.285.7 → 0.285.8
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-B1EEjygi.js → asg-provider-CvYAGRMV.js} +3 -3
- package/dist/{asg-provider-B1EEjygi.js.map → asg-provider-CvYAGRMV.js.map} +1 -1
- package/dist/cli.js +2 -2
- package/dist/{deploy-engine-DmWPwiyQ.js → deploy-engine-D4QA_B1V.js} +4 -4
- package/dist/{deploy-engine-DmWPwiyQ.js.map → deploy-engine-D4QA_B1V.js.map} +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/{logger-DyTk5GeO.js → logger-Dw-3y48G.js} +23 -13
- package/dist/{logger-DyTk5GeO.js.map → logger-Dw-3y48G.js.map} +1 -1
- package/dist/{program-CjlLza5f.js → program-CjJoJOIE.js} +286 -131
- package/dist/{program-CjlLza5f.js.map → program-CjJoJOIE.js.map} +1 -1
- package/dist/{version-DlUEyyGa.js → version-DFdq83MF.js} +2 -2
- package/dist/{version-DlUEyyGa.js.map → version-DFdq83MF.js.map} +1 -1
- package/package.json +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { $ as DEFAULT_STATE_PREFIX, $n as CFN_TEMPLATE_BODY_LIMIT, $t as maskSecretsInError, A as bold, An as describeAwsFailure, Ar as NestedStackChildDirectDestroyError, At as requireConfigObject, B as secretBearingStateKeyWarning, Bn as Synthesizer, Bt as DiffCalculator, C as unsupportedFinalSnapshotError, Cn as getBootstrapMarkerKey, Cr as DeployCancelledError, Ct as assertRegionMatch, D as isStatefulRecreateTargetSync, Dn as validateAssetBucketName, Dr as LocalStartServiceError, Dt as readConfigString, E as MULTI_REGION_RECREATE_BLOCKED_TYPES, En as readBootstrapMarkerBody, Er as LocalMigrateError, Et as configStringRefusal, F as yellow, Fn as partitionSensitiveEnv, Fr as StackHasActiveImportsError, Ft as s3BucketDomainName, G as clearOnUpdateRemoval, Gn as resolveAutoAssetStorage, Gr as isThrottlingError, Gt as TemplateParser, H as getCurrentResourceSecrets, Hn as getDefaultStateBucketName, Hr as withErrorHandling, Ht as describeTypeWithThrottleRetry, I as collectDeclaredOutputNames, In as runDockerForeground, Ir as StackTerminationProtectionError, It as s3BucketDualStackDomainName, J as findSilentDropProperties, Jn as resolveStateBucketWithDefault, Jr as markRedactedCause, Jt as TEMPLATE_SOURCED_RULES, K as ProviderRegistry, Kn as resolveCaptureObservedState, Kr as isTransientServerError, Kt as STATE_SOURCED_CROSS_GENERATION_RULES, L as collectPublishedOutputNames, Ln as runDockerStreaming, Lt as s3BucketRegionalDomainName, M as gray, Mn as dockerSpawnEnvWithSensitive, Mr as ProvisioningError, Mt as classifyReplaySecretRegion, N as green, Nn as formatDockerLoginError, Nr as ResourceTimeoutError, Nt as producerRegionsFromState, O as renderStatefulReason, On as validateContainerRepoName, Ot as replayWarn, P as red, Pn as getDockerCmd, Pr as ResourceUpdateNotSupportedError, Pt as s3BucketArn, Q as CUSTOM_RESOURCE_RESPONSE_PREFIX, Qn as warnDeprecatedNoPrefixCliFlag, Qt as isSingleDynamicReferenceToken, R as exportAliasCollisionScrubWarning, Rn as AssetManifestLoader, Rt as s3BucketWebsiteUrl, S as refusesFinalSnapshot, Sn as ensureAssetStorage, St as resolveExplicitPhysicalId, T as extractDeploymentEventError, Tn as parseBootstrapMarker, Tr as LocalInvokeBuildError$1, Tt as configBooleanRefusal, U as IAMRoleProvider, Un as getLegacyStateBucketName, Ur as isMarkedNonRetryable, Ut as withRetry, V as stateKeySecretExposure, Vn as synthesisStatusMessage, Vr as normalizeAwsError, Vt as INTRINSIC_KEYS, W as collectInlinePolicyNamesManagedBySiblings, Wn as resolveApp, Wr as isRetryableTransientError, Wt as DagBuilder, X as maskDeep, Xn as resolveUseCdkBootstrapAssets, Xt as dynamicReferenceTokens, Y as createMaskedRetryLogger, Yn as resolveStateBucketWithDefaultAndSource, Yr as retryClassificationText, Yt as createSecretMasker, Z as maskerOrIdentity, Zn as stateBucketExistenceConfirmed, Zt as errorCauseChain, _ as PRE_DELETE_SNAPSHOT_TYPES, _n as escapeRegExp, _r as setAwsClients, _t as isUnboundTemplateParameter, a as DeploymentEventsStore, an as rebuildClientForBucketRegion, ar as displaySafe, at as CloudControlProvider, b as createPreDeleteFinalSnapshot, bn as BOOTSTRAP_MARKER_PREFIX, bt as WAFv2WebACLProvider, c as replayFailedOperations, cn as importableOutputs, cr as canonicalizeRegion, ct as deleteIndeterminateGuards, d as updatePartialReason, dn as stringifyValue, dr as processStackMessages, dt as isTerminationProtectionPropagationError, en as maskSecretsInText, er as CFN_TEMPLATE_URL_LIMIT, et as beginCommandInterruptScope, f as withResourceDeadline, fn as WorkGraph, ft as IntrinsicFunctionResolver, g as ATOMIC_FINAL_SNAPSHOT_TYPES, gn as rewriteTemplateAssetReferences, gr as resetAwsClients, gt as getAccountInfo, h as computeImplicitDeleteEdges, hn as loadPublishableAssetManifest, hr as getAwsClients, ht as coerceParameterTypedValue, i as DeploymentEventsReader, in as S3StateBackend, ir as CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION, it as startInterruptWatch, j as cyan, jn as buildDockerImage, jr as PartialFailureError, jt as requireConfigString, k as formatResourceLine, kn as buildDenyExternalAccessPolicy, kr as MissingCdkCliError, kt as requireConfigArray, l as replayRollback, ln as shouldRetainResource, lr as derivePartitionAndUrlSuffix, lt as deleteSkipReason, m as IMPLICIT_DELETE_DEPENDENCIES, mn as createAssetRedirectResolver, mr as AwsClients, mt as cfnRefValueFromPhysicalId, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as scrubResourceRecord, nr as findLargeInlineResources, nt as interruptWatchListenerCount, o as planFailedOps, on as exportNamesCarriedFrom, or as expectedOwnerParam, ot as slowCcOperationTimeoutMs, p as maskingRetryLogger, pn as buildAssetRedirectMap, pr as resolveBucketRegion, pt as carriesDynamicReference, q as findActionableSilentDrops, qn as resolveSkipPrefix, qr as markNonRetryable, qt as STATE_SOURCED_READBACK_RULES, r as DeployEngine, rn as LockManager, rr as uploadCfnTemplate, rt as isInterruptedWaitError, s as planRollback, sn as importableOutputKeys, sr as PARTITION_TABLE, st as UNSPECIFIED_SKIP_REASON, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as redactSecretsForState, tr as MIGRATE_TMP_PREFIX, tt as endCommandInterruptScope, u as updatePartialMessage, un as AssetPublisher, ur as AssemblyReader, ut as disableInstanceApiTermination, v as buildFinalSnapshotIdentifier, vn as stripControlChars, vt as parameterTypeMayLoseSecretIdentity, w as makeCanonicalizePropertiesFn, wn as isCrossRegionRedirect, wr as DynamicReferenceRegionAmbiguousError, wt as coerceCfnBoolean, x as isFinalSnapshotError, xn as assertAssetBucketRegion, xr as CrossAccountSecretRefusalError, xt as normalizeAwsTagsToCfn, y as ccRoutedFinalSnapshotError, yn as AssetModeResolver, yr as CdkdError, yt as refStateLookupFromResource, z as isExportAliasCollision, zn as getDockerImageBySourceHash, zt as applyRoleArnIfSet } from "./deploy-engine-
|
|
2
|
-
import { _ as withStackName, c as PATTERN_B_NAME_OPTIONS, f as generateResourceName, g as withSkipPrefix, i as reserveStdoutForPayload, l as PATTERN_B_NAME_PROPERTIES, m as getCurrentStackName, n as getLogger, o as runStackBuffered, p as generateResourceNameWithFallback, s as getLiveRenderer, u as PATTERN_B_RESOURCE_TYPES } from "./logger-
|
|
1
|
+
import { $ as DEFAULT_STATE_PREFIX, $n as CFN_TEMPLATE_BODY_LIMIT, $t as maskSecretsInError, A as bold, An as describeAwsFailure, Ar as NestedStackChildDirectDestroyError, At as requireConfigObject, B as secretBearingStateKeyWarning, Bn as Synthesizer, Bt as DiffCalculator, C as unsupportedFinalSnapshotError, Cn as getBootstrapMarkerKey, Cr as DeployCancelledError, Ct as assertRegionMatch, D as isStatefulRecreateTargetSync, Dn as validateAssetBucketName, Dr as LocalStartServiceError, Dt as readConfigString, E as MULTI_REGION_RECREATE_BLOCKED_TYPES, En as readBootstrapMarkerBody, Er as LocalMigrateError, Et as configStringRefusal, F as yellow, Fn as partitionSensitiveEnv, Fr as StackHasActiveImportsError, Ft as s3BucketDomainName, G as clearOnUpdateRemoval, Gn as resolveAutoAssetStorage, Gr as isThrottlingError, Gt as TemplateParser, H as getCurrentResourceSecrets, Hn as getDefaultStateBucketName, Hr as withErrorHandling, Ht as describeTypeWithThrottleRetry, I as collectDeclaredOutputNames, In as runDockerForeground, Ir as StackTerminationProtectionError, It as s3BucketDualStackDomainName, J as findSilentDropProperties, Jn as resolveStateBucketWithDefault, Jr as markRedactedCause, Jt as TEMPLATE_SOURCED_RULES, K as ProviderRegistry, Kn as resolveCaptureObservedState, Kr as isTransientServerError, Kt as STATE_SOURCED_CROSS_GENERATION_RULES, L as collectPublishedOutputNames, Ln as runDockerStreaming, Lt as s3BucketRegionalDomainName, M as gray, Mn as dockerSpawnEnvWithSensitive, Mr as ProvisioningError, Mt as classifyReplaySecretRegion, N as green, Nn as formatDockerLoginError, Nr as ResourceTimeoutError, Nt as producerRegionsFromState, O as renderStatefulReason, On as validateContainerRepoName, Ot as replayWarn, P as red, Pn as getDockerCmd, Pr as ResourceUpdateNotSupportedError, Pt as s3BucketArn, Q as CUSTOM_RESOURCE_RESPONSE_PREFIX, Qn as warnDeprecatedNoPrefixCliFlag, Qt as isSingleDynamicReferenceToken, R as exportAliasCollisionScrubWarning, Rn as AssetManifestLoader, Rt as s3BucketWebsiteUrl, S as refusesFinalSnapshot, Sn as ensureAssetStorage, St as resolveExplicitPhysicalId, T as extractDeploymentEventError, Tn as parseBootstrapMarker, Tr as LocalInvokeBuildError$1, Tt as configBooleanRefusal, U as IAMRoleProvider, Un as getLegacyStateBucketName, Ur as isMarkedNonRetryable, Ut as withRetry, V as stateKeySecretExposure, Vn as synthesisStatusMessage, Vr as normalizeAwsError, Vt as INTRINSIC_KEYS, W as collectInlinePolicyNamesManagedBySiblings, Wn as resolveApp, Wr as isRetryableTransientError, Wt as DagBuilder, X as maskDeep, Xn as resolveUseCdkBootstrapAssets, Xt as dynamicReferenceTokens, Y as createMaskedRetryLogger, Yn as resolveStateBucketWithDefaultAndSource, Yr as retryClassificationText, Yt as createSecretMasker, Z as maskerOrIdentity, Zn as stateBucketExistenceConfirmed, Zt as errorCauseChain, _ as PRE_DELETE_SNAPSHOT_TYPES, _n as escapeRegExp, _r as setAwsClients, _t as isUnboundTemplateParameter, a as DeploymentEventsStore, an as rebuildClientForBucketRegion, ar as displaySafe, at as CloudControlProvider, b as createPreDeleteFinalSnapshot, bn as BOOTSTRAP_MARKER_PREFIX, bt as WAFv2WebACLProvider, c as replayFailedOperations, cn as importableOutputs, cr as canonicalizeRegion, ct as deleteIndeterminateGuards, d as updatePartialReason, dn as stringifyValue, dr as processStackMessages, dt as isTerminationProtectionPropagationError, en as maskSecretsInText, er as CFN_TEMPLATE_URL_LIMIT, et as beginCommandInterruptScope, f as withResourceDeadline, fn as WorkGraph, ft as IntrinsicFunctionResolver, g as ATOMIC_FINAL_SNAPSHOT_TYPES, gn as rewriteTemplateAssetReferences, gr as resetAwsClients, gt as getAccountInfo, h as computeImplicitDeleteEdges, hn as loadPublishableAssetManifest, hr as getAwsClients, ht as coerceParameterTypedValue, i as DeploymentEventsReader, in as S3StateBackend, ir as CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION, it as startInterruptWatch, j as cyan, jn as buildDockerImage, jr as PartialFailureError, jt as requireConfigString, k as formatResourceLine, kn as buildDenyExternalAccessPolicy, kr as MissingCdkCliError, kt as requireConfigArray, l as replayRollback, ln as shouldRetainResource, lr as derivePartitionAndUrlSuffix, lt as deleteSkipReason, m as IMPLICIT_DELETE_DEPENDENCIES, mn as createAssetRedirectResolver, mr as AwsClients, mt as cfnRefValueFromPhysicalId, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as scrubResourceRecord, nr as findLargeInlineResources, nt as interruptWatchListenerCount, o as planFailedOps, on as exportNamesCarriedFrom, or as expectedOwnerParam, ot as slowCcOperationTimeoutMs, p as maskingRetryLogger, pn as buildAssetRedirectMap, pr as resolveBucketRegion, pt as carriesDynamicReference, q as findActionableSilentDrops, qn as resolveSkipPrefix, qr as markNonRetryable, qt as STATE_SOURCED_READBACK_RULES, r as DeployEngine, rn as LockManager, rr as uploadCfnTemplate, rt as isInterruptedWaitError, s as planRollback, sn as importableOutputKeys, sr as PARTITION_TABLE, st as UNSPECIFIED_SKIP_REASON, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as redactSecretsForState, tr as MIGRATE_TMP_PREFIX, tt as endCommandInterruptScope, u as updatePartialMessage, un as AssetPublisher, ur as AssemblyReader, ut as disableInstanceApiTermination, v as buildFinalSnapshotIdentifier, vn as stripControlChars, vt as parameterTypeMayLoseSecretIdentity, w as makeCanonicalizePropertiesFn, wn as isCrossRegionRedirect, wr as DynamicReferenceRegionAmbiguousError, wt as coerceCfnBoolean, x as isFinalSnapshotError, xn as assertAssetBucketRegion, xr as CrossAccountSecretRefusalError, xt as normalizeAwsTagsToCfn, y as ccRoutedFinalSnapshotError, yn as AssetModeResolver, yr as CdkdError, yt as refStateLookupFromResource, z as isExportAliasCollision, zn as getDockerImageBySourceHash, zt as applyRoleArnIfSet } from "./deploy-engine-D4QA_B1V.js";
|
|
2
|
+
import { _ as withStackName, c as PATTERN_B_NAME_OPTIONS, f as generateResourceName, g as withSkipPrefix, i as reserveStdoutForPayload, l as PATTERN_B_NAME_PROPERTIES, m as getCurrentStackName, n as getLogger, o as runStackBuffered, p as generateResourceNameWithFallback, s as getLiveRenderer, u as PATTERN_B_RESOURCE_TYPES } from "./logger-Dw-3y48G.js";
|
|
3
3
|
import { t as awsClientDefaults } from "./aws-client-defaults-D-iYiIJ6.js";
|
|
4
|
-
import { t as getCdkdVersion } from "./version-
|
|
5
|
-
import { t as ASGProvider } from "./asg-provider-
|
|
4
|
+
import { t as getCdkdVersion } from "./version-DFdq83MF.js";
|
|
5
|
+
import { t as ASGProvider } from "./asg-provider-CvYAGRMV.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, 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";
|
|
@@ -2675,14 +2675,32 @@ async function promptRecreateConfirm(input) {
|
|
|
2675
2675
|
//#endregion
|
|
2676
2676
|
//#region src/cli/commands/confirm-prompt.ts
|
|
2677
2677
|
/**
|
|
2678
|
-
*
|
|
2679
|
-
*
|
|
2680
|
-
*
|
|
2681
|
-
*
|
|
2682
|
-
*
|
|
2678
|
+
* The CLI's two shared confirmation-prompt helpers.
|
|
2679
|
+
*
|
|
2680
|
+
* They have OPPOSITE defaults and opposite non-interactive behaviour, which is
|
|
2681
|
+
* why both live here rather than one being expressed in terms of the other:
|
|
2682
|
+
*
|
|
2683
|
+
* - {@link promptYesNo} — default-YES (`[Y/n]`, empty input accepts). Used by
|
|
2684
|
+
* the issue #1007 asset-storage auto-create on interactive TTY deploys
|
|
2685
|
+
* without `--yes`. It deliberately carries NO non-interactive guard: its
|
|
2686
|
+
* only caller (`deploy.ts`, at the `options.yes || !process.stdin.isTTY`
|
|
2687
|
+
* short-circuit) never reaches it on a non-TTY stdin, and a deploy that
|
|
2688
|
+
* assumes "yes" is the one place in the CLI where auto-confirming is the
|
|
2689
|
+
* documented choice.
|
|
2690
|
+
* - {@link confirmOrRefuse} — default-NO (`[y/N]`), and REFUSES outright on a
|
|
2691
|
+
* non-interactive stdin. This is the one every MUTATING command uses.
|
|
2692
|
+
*
|
|
2693
|
+
* Kept in its own module (mirrors `recreate-confirm-prompt.ts`) so the
|
|
2694
|
+
* accept/decline parsing is unit-testable without importing whole command
|
|
2695
|
+
* files.
|
|
2696
|
+
*/
|
|
2697
|
+
/**
|
|
2698
|
+
* Default-YES confirmation prompt (`[Y/n]`, empty input = yes).
|
|
2699
|
+
*
|
|
2700
|
+
* See the module doc for why this one is deliberately unguarded.
|
|
2683
2701
|
*/
|
|
2684
2702
|
async function promptYesNo(prompt) {
|
|
2685
|
-
const rl = readline.createInterface({
|
|
2703
|
+
const rl = readline$1.createInterface({
|
|
2686
2704
|
input: process.stdin,
|
|
2687
2705
|
output: process.stdout
|
|
2688
2706
|
});
|
|
@@ -2693,6 +2711,79 @@ async function promptYesNo(prompt) {
|
|
|
2693
2711
|
rl.close();
|
|
2694
2712
|
}
|
|
2695
2713
|
}
|
|
2714
|
+
/** Suffix appended to a {@link confirmOrRefuse} prompt when none is given. */
|
|
2715
|
+
const DEFAULT_CONFIRM_SUFFIX = " [y/N] ";
|
|
2716
|
+
/**
|
|
2717
|
+
* Default-NO confirmation prompt that REFUSES a non-interactive run instead of
|
|
2718
|
+
* hanging on it (issue #2275, the class issue #2259 fixed for `cdkd destroy`).
|
|
2719
|
+
*
|
|
2720
|
+
* `rl.question` never settles when stdin is already at EOF, and EOF delivers
|
|
2721
|
+
* no signal, so nothing wakes it: a command that prompts without this guard
|
|
2722
|
+
* parks FOREVER in CI rather than failing, burning the job's whole timeout
|
|
2723
|
+
* budget. Measured on Node 24.15.0, the version `.node-version` pins, against
|
|
2724
|
+
* real `node:readline/promises`: `echo y |` resolves `"y"`, while both
|
|
2725
|
+
* `printf 'y' |` (a real answer with no trailing newline) and `< /dev/null`
|
|
2726
|
+
* stay pending indefinitely.
|
|
2727
|
+
*
|
|
2728
|
+
* REFUSE rather than auto-confirm, at every one of the nine sites this helper
|
|
2729
|
+
* replaced. Every one of them guards a MUTATION — a rollback replay, a state
|
|
2730
|
+
* record removal, an observed-property refresh, an orphan, an import, an
|
|
2731
|
+
* export-then-delete-state, a drift accept/revert, a CloudFormation stack
|
|
2732
|
+
* retirement, a state-bucket migration — so silently answering "yes" on
|
|
2733
|
+
* behalf of an absent operator is never the safe reading. `deploy.ts`'s
|
|
2734
|
+
* auto-confirm (`options.yes || !process.stdin.isTTY` -> proceed) stays the
|
|
2735
|
+
* deliberate exception, because a deploy that assumes "yes" is recoverable.
|
|
2736
|
+
*
|
|
2737
|
+
* A first cut of this guard (in `state.ts`, see the long comment at the
|
|
2738
|
+
* `state destroy --all` prompt) raced the question against readline's `close`
|
|
2739
|
+
* event and turned EOF into a decline. That lost three measured ways — a real
|
|
2740
|
+
* answer with no trailing newline was silently discarded, a delayed answer
|
|
2741
|
+
* lost the race, and an interactive Ctrl-C landed on the EOF arm — so do not
|
|
2742
|
+
* reintroduce it. A refusal has none of those.
|
|
2743
|
+
*
|
|
2744
|
+
* POSITION IS LOAD-BEARING, and this helper gets it for free: every call site
|
|
2745
|
+
* sits INSIDE the caller's `--yes` / `--force` short-circuit
|
|
2746
|
+
* (`if (!options.yes && !options.force) { ... }`), so a flagged
|
|
2747
|
+
* non-interactive run never reaches this function and never consults stdin at
|
|
2748
|
+
* all. Keep it that way — hoisting a call above its flag check would make
|
|
2749
|
+
* `--yes` refuse instead of proceed, which is the inverse bug.
|
|
2750
|
+
*
|
|
2751
|
+
* Throws {@link CdkdError} with the `NON_INTERACTIVE_CONFIRM` code, matching
|
|
2752
|
+
* `gc.ts` and `bootstrap-destroy.ts` — the only two of the five originally
|
|
2753
|
+
* guarded prompts that carry a code (the other three throw a bare `Error` or
|
|
2754
|
+
* a `LocalMigrateError`). `handleError` maps it to exit 1, so CI can branch on
|
|
2755
|
+
* it.
|
|
2756
|
+
*
|
|
2757
|
+
* TWO GUARDED PROMPTS DELIBERATELY DO NOT ROUTE THROUGH HERE:
|
|
2758
|
+
* `destroy-runner.ts`'s per-stack prompt (the issue #2259 fix) and
|
|
2759
|
+
* `state.ts`'s `state destroy --all` batch prompt (issue #2247). Both already
|
|
2760
|
+
* carry this exact guard inline, and both differ in ways a shared helper would
|
|
2761
|
+
* have to grow parameters for — `destroy-runner.ts` has a default-YES bare
|
|
2762
|
+
* form alongside a default-NO `--remove-protection` form, and `state.ts`
|
|
2763
|
+
* passes an abort `signal` for the issue #2117 Ctrl-C handling. Folding them
|
|
2764
|
+
* in would also drag `destroy-runner.ts` (in the `integ-destroy` AND
|
|
2765
|
+
* `integ-broad` gate scopes) into a pure refactor's blast radius, buying a
|
|
2766
|
+
* real-AWS run for no behaviour change. The other five pre-existing guarded
|
|
2767
|
+
* prompts (`gc.ts`, `bootstrap-destroy.ts`, `recreate-confirm-prompt.ts`,
|
|
2768
|
+
* `prefix-migration-check.ts`, `migrate-command.ts`) stay put for the same
|
|
2769
|
+
* reason: each guards its own flow with its own error type.
|
|
2770
|
+
*
|
|
2771
|
+
* @param prompt the question, WITHOUT its trailing `[y/N]` marker
|
|
2772
|
+
* @returns `true` only for `y` / `yes` (any case, trimmed)
|
|
2773
|
+
*/
|
|
2774
|
+
async function confirmOrRefuse(prompt, options) {
|
|
2775
|
+
if (process.stdin.isTTY !== true) throw new CdkdError(options.refusal, "NON_INTERACTIVE_CONFIRM");
|
|
2776
|
+
const rl = readline$1.createInterface({
|
|
2777
|
+
input: process.stdin,
|
|
2778
|
+
output: options.output ?? process.stdout
|
|
2779
|
+
});
|
|
2780
|
+
try {
|
|
2781
|
+
const ans = await rl.question(`${prompt}${options.suffix ?? " [y/N] "}`);
|
|
2782
|
+
return /^y(es)?$/i.test(ans.trim());
|
|
2783
|
+
} finally {
|
|
2784
|
+
rl.close();
|
|
2785
|
+
}
|
|
2786
|
+
}
|
|
2696
2787
|
|
|
2697
2788
|
//#endregion
|
|
2698
2789
|
//#region src/cli/commands/deployment-events-run.ts
|
|
@@ -62830,6 +62921,36 @@ const TEMPLATE_BODY_LIMIT = CFN_TEMPLATE_BODY_LIMIT;
|
|
|
62830
62921
|
*/
|
|
62831
62922
|
const TEMPLATE_URL_LIMIT = CFN_TEMPLATE_URL_LIMIT;
|
|
62832
62923
|
/**
|
|
62924
|
+
* Best-effort reaper for the transient template bodies this flow uploads to
|
|
62925
|
+
* the state bucket under `cdkd-migrate-tmp/`.
|
|
62926
|
+
*
|
|
62927
|
+
* ONE implementation because {@link retireCloudFormationStack} drains from
|
|
62928
|
+
* four different exits — the recursive walk's `catch`, the confirmation
|
|
62929
|
+
* gate's decline AND its non-interactive refusal, the no-modification fast
|
|
62930
|
+
* path, and the post-`UpdateStack` `finally`. Each used to carry its own copy
|
|
62931
|
+
* of this loop, and the copies were how the refusal exit came to have none at
|
|
62932
|
+
* all: a `throw` from the gate passes every one of the other three.
|
|
62933
|
+
*
|
|
62934
|
+
* Best-effort by design. A leaked transient object costs pennies and lives
|
|
62935
|
+
* under an explicitly-named prefix, while a failed DELETE that propagated
|
|
62936
|
+
* would turn a successful retire into a reported failure. The retire's
|
|
62937
|
+
* success is governed by CloudFormation, not by S3 — so each cleanup's own
|
|
62938
|
+
* error becomes a `warn` naming the prefix to sweep manually.
|
|
62939
|
+
*
|
|
62940
|
+
* `what` / `when` keep the four sites' distinct wording (a caller says
|
|
62941
|
+
* whether these are the parent's own upload or a nested child's, and whether
|
|
62942
|
+
* it is unwinding); the SENTENCE they sit in is shared.
|
|
62943
|
+
*/
|
|
62944
|
+
async function drainTemplateUploads(cleanups, stateBucket, labels) {
|
|
62945
|
+
const logger = getLogger();
|
|
62946
|
+
for (const cleanup of cleanups) try {
|
|
62947
|
+
await cleanup();
|
|
62948
|
+
} catch (cleanupErr) {
|
|
62949
|
+
const msg = cleanupErr instanceof Error ? cleanupErr.message : String(cleanupErr);
|
|
62950
|
+
logger.warn(`Failed to delete ${labels.what} from '${stateBucket}'${labels.when ? ` ${labels.when}` : ""}. Clean up manually under prefix '${MIGRATE_TMP_PREFIX}/'. Cause: ${msg}`);
|
|
62951
|
+
}
|
|
62952
|
+
}
|
|
62953
|
+
/**
|
|
62833
62954
|
* Retire a CloudFormation stack whose resources have just been adopted into
|
|
62834
62955
|
* cdkd state. The 4-step procedure is the one AWS recommends for handing
|
|
62835
62956
|
* over resources between management tools without deleting them:
|
|
@@ -62893,35 +63014,31 @@ async function retireCloudFormationStack(options) {
|
|
|
62893
63014
|
format = recursive.format;
|
|
62894
63015
|
nestedCleanups.push(...recursive.cleanups);
|
|
62895
63016
|
} catch (err) {
|
|
62896
|
-
if (err instanceof RecursiveRetainInjectionError)
|
|
62897
|
-
|
|
62898
|
-
|
|
62899
|
-
|
|
62900
|
-
logger.warn(`Failed to delete partial nested-template upload from '${stateBucket}' during error recovery. Clean up manually under prefix '${MIGRATE_TMP_PREFIX}/'. Cause: ${msg}`);
|
|
62901
|
-
}
|
|
63017
|
+
if (err instanceof RecursiveRetainInjectionError) await drainTemplateUploads(err.cleanups, stateBucket, {
|
|
63018
|
+
what: "partial nested-template upload",
|
|
63019
|
+
when: "during error recovery"
|
|
63020
|
+
});
|
|
62902
63021
|
throw err;
|
|
62903
63022
|
}
|
|
62904
63023
|
} else ({body: newBody, modified, format} = injectRetainPolicies(tpl.TemplateBody, cfnStackName));
|
|
62905
63024
|
if (!yes) {
|
|
62906
|
-
|
|
63025
|
+
let proceed = false;
|
|
63026
|
+
try {
|
|
63027
|
+
proceed = await confirmPrompt$6(`Set DeletionPolicy=Retain and UpdateReplacePolicy=Retain on every resource in CloudFormation stack '${cfnStackName}', then delete the stack? AWS resources will NOT be deleted (cdkd state has been written).`);
|
|
63028
|
+
} finally {
|
|
63029
|
+
if (!proceed) await drainTemplateUploads(nestedCleanups, stateBucket, {
|
|
63030
|
+
what: "temporary nested-template upload",
|
|
63031
|
+
when: "during cancel cleanup"
|
|
63032
|
+
});
|
|
63033
|
+
}
|
|
63034
|
+
if (!proceed) {
|
|
62907
63035
|
logger.info("CloudFormation stack retirement cancelled. cdkd state is unaffected.");
|
|
62908
|
-
for (const cleanup of nestedCleanups) try {
|
|
62909
|
-
await cleanup();
|
|
62910
|
-
} catch (cleanupErr) {
|
|
62911
|
-
const msg = cleanupErr instanceof Error ? cleanupErr.message : String(cleanupErr);
|
|
62912
|
-
logger.warn(`Failed to delete temporary nested-template upload from '${stateBucket}' during cancel cleanup. Clean up manually under prefix '${MIGRATE_TMP_PREFIX}/'. Cause: ${msg}`);
|
|
62913
|
-
}
|
|
62914
63036
|
return { outcome: "cancelled" };
|
|
62915
63037
|
}
|
|
62916
63038
|
}
|
|
62917
63039
|
if (!modified) {
|
|
62918
63040
|
logger.info(`[2/4] Template already has Retain on every resource — skipping UpdateStack.`);
|
|
62919
|
-
|
|
62920
|
-
await cleanup();
|
|
62921
|
-
} catch (cleanupErr) {
|
|
62922
|
-
const msg = cleanupErr instanceof Error ? cleanupErr.message : String(cleanupErr);
|
|
62923
|
-
logger.warn(`Failed to delete temporary nested-template upload from '${stateBucket}'. Clean up manually under prefix '${MIGRATE_TMP_PREFIX}/'. Cause: ${msg}`);
|
|
62924
|
-
}
|
|
63041
|
+
await drainTemplateUploads(nestedCleanups, stateBucket, { what: "temporary nested-template upload" });
|
|
62925
63042
|
} else {
|
|
62926
63043
|
logger.info(`[2/4] Injected DeletionPolicy=Retain and UpdateReplacePolicy=Retain.`);
|
|
62927
63044
|
if (newBody.length > TEMPLATE_URL_LIMIT) throw new Error(`Modified template is ${newBody.length} bytes, exceeds the CloudFormation UpdateStack TemplateURL limit (${TEMPLATE_URL_LIMIT}). cdkd state has already been written; retire the stack manually with (1) shrink the template, then (2) UpdateStack with Retain policies, (3) DeleteStack — or split the stack and retry.`);
|
|
@@ -62967,13 +63084,7 @@ async function retireCloudFormationStack(options) {
|
|
|
62967
63084
|
maxDelay: 10
|
|
62968
63085
|
}, { StackName: cfnStackName });
|
|
62969
63086
|
} finally {
|
|
62970
|
-
|
|
62971
|
-
for (const cleanup of allCleanups) try {
|
|
62972
|
-
await cleanup();
|
|
62973
|
-
} catch (cleanupErr) {
|
|
62974
|
-
const msg = cleanupErr instanceof Error ? cleanupErr.message : String(cleanupErr);
|
|
62975
|
-
logger.warn(`Failed to delete temporary template upload from '${stateBucket}'. Clean up manually under prefix '${MIGRATE_TMP_PREFIX}/'. Cause: ${msg}`);
|
|
62976
|
-
}
|
|
63087
|
+
await drainTemplateUploads([...s3Cleanup ? [s3Cleanup] : [], ...nestedCleanups], stateBucket, { what: "temporary template upload" });
|
|
62977
63088
|
}
|
|
62978
63089
|
}
|
|
62979
63090
|
logger.info(`[4/4] Deleting CloudFormation stack '${cfnStackName}' (resources retained)...`);
|
|
@@ -63284,17 +63395,30 @@ async function walkCfnStackTree(stackName, physicalId, cfnClient) {
|
|
|
63284
63395
|
nested
|
|
63285
63396
|
};
|
|
63286
63397
|
}
|
|
63398
|
+
/**
|
|
63399
|
+
* The CloudFormation-stack retirement confirmation prompt, reached from
|
|
63400
|
+
* `cdkd import --migrate-from-cloudformation` and `cdkd migrate
|
|
63401
|
+
* --retire-cfn-stack` (both spell the skip flag `-y` / `--yes`). Its only call
|
|
63402
|
+
* site is inside the `if (!yes)` block above, which is what keeps
|
|
63403
|
+
* `confirmOrRefuse`'s non-interactive refusal (issue #2275) from firing on a
|
|
63404
|
+
* `--yes` run.
|
|
63405
|
+
*
|
|
63406
|
+
* TWO commands reach it, so the refusal NAMES BOTH. Every other site names one
|
|
63407
|
+
* command because it has one; a refusal that named neither would leave a CI
|
|
63408
|
+
* user knowing a flag is missing without knowing which invocation to put it
|
|
63409
|
+
* on, and `confirmOrRefuse`'s own contract is that the refusal is the only
|
|
63410
|
+
* thing that user sees.
|
|
63411
|
+
*
|
|
63412
|
+
* It also states that cdkd state has ALREADY been written. This prompt is the
|
|
63413
|
+
* only one of the nine that fires AFTER its command's state write, so a
|
|
63414
|
+
* refusal here leaves a genuine split brain — cdkd claims the resources while
|
|
63415
|
+
* the CloudFormation stack is still live — and the operator has to know that
|
|
63416
|
+
* before deciding whether to re-run or finish by hand.
|
|
63417
|
+
*
|
|
63418
|
+
* Exported for unit testing — internal to the command flow otherwise.
|
|
63419
|
+
*/
|
|
63287
63420
|
async function confirmPrompt$6(prompt) {
|
|
63288
|
-
|
|
63289
|
-
input: process.stdin,
|
|
63290
|
-
output: process.stdout
|
|
63291
|
-
});
|
|
63292
|
-
try {
|
|
63293
|
-
const ans = await rl.question(`${prompt} [y/N] `);
|
|
63294
|
-
return /^y(es)?$/i.test(ans.trim());
|
|
63295
|
-
} finally {
|
|
63296
|
-
rl.close();
|
|
63297
|
-
}
|
|
63421
|
+
return confirmOrRefuse(prompt, { refusal: "The CloudFormation stack retirement confirmation prompt cannot run in a non-interactive environment. Pass -y / --yes on whichever command you ran — cdkd import --migrate-from-cloudformation or cdkd migrate --retire-cfn-stack — or run it from a real terminal. NOTE cdkd state has already been written: the resources are recorded in cdkd state while the CloudFormation stack is still live, so re-run with -y / --yes (or retire the stack by hand) to finish the migration." });
|
|
63298
63422
|
}
|
|
63299
63423
|
/**
|
|
63300
63424
|
* Flat `logicalId -> physicalId` map for ONE CloudFormation stack, or `null`
|
|
@@ -69335,24 +69459,26 @@ async function runWithConcurrency(tasks, concurrency) {
|
|
|
69335
69459
|
await Promise.all(workers);
|
|
69336
69460
|
}
|
|
69337
69461
|
/**
|
|
69338
|
-
*
|
|
69462
|
+
* `cdkd drift --accept` / `--revert`'s confirmation prompt: ask the operator to
|
|
69463
|
+
* confirm a mutation. Both call sites sit inside an `if (!options.yes)` block,
|
|
69464
|
+
* which is what keeps `confirmOrRefuse`'s non-interactive refusal (issue
|
|
69465
|
+
* #2275) from firing on a `--yes` run.
|
|
69466
|
+
*
|
|
69467
|
+
* Issue #2230 is why this site passes an explicit `output`: the prompt is
|
|
69468
|
+
* written to `out.stream`, not unconditionally to `process.stdout` — under
|
|
69469
|
+
* `--json` that stream carries the payload, and a bare `[y/N] ` spliced into
|
|
69470
|
+
* it is the same corruption as a status line, so the sink is `process.stderr`
|
|
69471
|
+
* there. The prompt is still SHOWN; only its stream changes. See the
|
|
69472
|
+
* `HumanTextSink` doc above for why the STREAM (not a closure) is what gets
|
|
69473
|
+
* handed to `createInterface`.
|
|
69339
69474
|
*
|
|
69340
|
-
*
|
|
69341
|
-
* `process.stdout` — under `--json` that stream carries the payload, and a
|
|
69342
|
-
* bare `[y/N] ` spliced into it is the same corruption as a status line.
|
|
69343
|
-
* The prompt is still SHOWN; only its stream changes.
|
|
69475
|
+
* Exported for unit testing — internal to the command flow otherwise.
|
|
69344
69476
|
*/
|
|
69345
69477
|
async function confirmPrompt$5(prompt, out) {
|
|
69346
|
-
|
|
69347
|
-
|
|
69348
|
-
|
|
69478
|
+
return confirmOrRefuse(prompt, {
|
|
69479
|
+
output: out.stream,
|
|
69480
|
+
refusal: "The cdkd drift confirmation prompt cannot run in a non-interactive environment. Pass -y / --yes to confirm, or run the command from a real terminal."
|
|
69349
69481
|
});
|
|
69350
|
-
try {
|
|
69351
|
-
const ans = await rl.question(`${prompt} [y/N] `);
|
|
69352
|
-
return /^y(es)?$/i.test(ans.trim());
|
|
69353
|
-
} finally {
|
|
69354
|
-
rl.close();
|
|
69355
|
-
}
|
|
69356
69482
|
}
|
|
69357
69483
|
function writeJsonReport(reports) {
|
|
69358
69484
|
const payload = reports.map((r) => {
|
|
@@ -70083,17 +70209,15 @@ async function emptyBucketAllVersions(s3, bucket) {
|
|
|
70083
70209
|
versionIdMarker = resp.NextVersionIdMarker;
|
|
70084
70210
|
} while (keyMarker || versionIdMarker);
|
|
70085
70211
|
}
|
|
70212
|
+
/**
|
|
70213
|
+
* `cdkd state migrate`'s confirmation prompt. Its only call site is inside the
|
|
70214
|
+
* `if (!options.yes)` block above, which is what keeps `confirmOrRefuse`'s
|
|
70215
|
+
* non-interactive refusal (issue #2275) from firing on a `--yes` run.
|
|
70216
|
+
*
|
|
70217
|
+
* Exported for unit testing — internal to the command flow otherwise.
|
|
70218
|
+
*/
|
|
70086
70219
|
async function confirmPrompt$4(prompt) {
|
|
70087
|
-
|
|
70088
|
-
input: process.stdin,
|
|
70089
|
-
output: process.stdout
|
|
70090
|
-
});
|
|
70091
|
-
try {
|
|
70092
|
-
const ans = await rl.question(`${prompt} [y/N] `);
|
|
70093
|
-
return /^y(es)?$/i.test(ans.trim());
|
|
70094
|
-
} finally {
|
|
70095
|
-
rl.close();
|
|
70096
|
-
}
|
|
70220
|
+
return confirmOrRefuse(prompt, { refusal: "The cdkd state migrate confirmation prompt cannot run in a non-interactive environment. Pass -y / --yes to confirm the migration, or run the command from a real terminal." });
|
|
70097
70221
|
}
|
|
70098
70222
|
/**
|
|
70099
70223
|
* Create the `cdkd state migrate` subcommand.
|
|
@@ -73705,17 +73829,18 @@ function printNextSteps(args) {
|
|
|
73705
73829
|
}
|
|
73706
73830
|
logger.info("");
|
|
73707
73831
|
}
|
|
73832
|
+
/**
|
|
73833
|
+
* `cdkd export`'s confirmation prompt, shared by its THREE call sites (the
|
|
73834
|
+
* rollback-journal override, the single-stack migration confirm, and the
|
|
73835
|
+
* nested-stack tree-wide confirm in `runPerStackImportLoop`). Every one of
|
|
73836
|
+
* them sits inside an `if (!options.yes ...)` block, which is what keeps
|
|
73837
|
+
* `confirmOrRefuse`'s non-interactive refusal (issue #2275) from firing on a
|
|
73838
|
+
* `--yes` run.
|
|
73839
|
+
*
|
|
73840
|
+
* Exported for unit testing — internal to the export flow otherwise.
|
|
73841
|
+
*/
|
|
73708
73842
|
async function confirmPrompt$3(prompt) {
|
|
73709
|
-
|
|
73710
|
-
input: process.stdin,
|
|
73711
|
-
output: process.stdout
|
|
73712
|
-
});
|
|
73713
|
-
try {
|
|
73714
|
-
const ans = await rl.question(`${prompt} [y/N] `);
|
|
73715
|
-
return /^y(es)?$/i.test(ans.trim());
|
|
73716
|
-
} finally {
|
|
73717
|
-
rl.close();
|
|
73718
|
-
}
|
|
73843
|
+
return confirmOrRefuse(prompt, { refusal: "The cdkd export confirmation prompt cannot run in a non-interactive environment. Pass -y / --yes to confirm, or run the command from a real terminal." });
|
|
73719
73844
|
}
|
|
73720
73845
|
function createExportCommand() {
|
|
73721
73846
|
const cmd = new Command("export").description("Hand a cdkd-managed stack over to CloudFormation via CFn IMPORT (changeset). AWS resources are unchanged; cdkd state for the stack is deleted on success. Mirror of `cdkd import` (AWS → cdkd) in the reverse direction (cdkd → CFn). Accepts JSON and YAML templates (YAML via a CFn-aware codec that preserves !Ref / !GetAtt / !Sub shorthand). Aborts if any resource is not CFn-importable.").argument("[stack]", "Stack name to export (auto-detected for single-stack apps)").option("--cfn-stack-name <name>", "Name of the destination CloudFormation stack for the root stack. Defaults to the cdkd stack name (or the cdkd2cfnStackName mapping when the name contains '~'). For per-nested-child overrides, use --cfn-child-stack-name.").option("--cfn-child-stack-name <pair...>", "Per-nested-child CFn stack-name override. Repeatable. Format: '<cdkdName>=<cfnName>' (e.g. --cfn-child-stack-name 'MyApp~Database=my-app-db'). The cdkd stack name for a nested child is '<parent>~<childLogicalId>' (v6 state-key form). Without an override the CFn name is derived by replacing '~' with '-'. Only consulted when the exported stack tree contains nested children; ignored for flat stacks.").option("--template <path>", "Path to a pre-rendered CloudFormation template (JSON or YAML — format auto-detected). Skips synth.").option("--stack-region <region>", "Region of the cdkd state record to operate on. Required when the same stack name has state in multiple regions.").option("--dry-run", "Print the import plan without creating a changeset.", false).option("--accept-transient-context", "Allow CLI -c key=value overrides at export time even though they are not persisted to cdk.json / cdk.context.json (default: refuse). When set, the user is responsible for passing the same -c flags to every future cdk deploy.", false).option("--include-non-importable", "Run a 2-phase migration when the stack contains non-importable resources (Custom::*). Phase 1 imports the importable resources; phase 2 CFn-CREATEs the non-importable ones, which re-invokes each Custom Resource's onCreate handler. Make sure onCreate is idempotent before enabling.", false).option("--parameter <key=value...>", "CFn template Parameter override, repeatable. Required when the synthesized template has Parameters without Default values; otherwise overrides the template's default value. Format: --parameter Key=Value.").option("--strict-cross-stack", "Refuse to export when sibling cdkd stacks in the same CDK app reference the exporting stack via Fn::GetStackOutput. Without the flag, cdkd warns and proceeds — the consumers keep resolving via the CloudFormation fallback (weak reference) unless they deploy with --no-cfn-fallback.", false).option("--skip-import-support-preflight", "Skip the pre-flight that refuses resource types whose CloudFormation registry schema says CFn cannot IMPORT them (no read handler AND NON_PROVISIONABLE), and let CreateChangeSet answer instead. The pre-flight is a registry HEURISTIC, not AWS's supported-for-import list, so this is the escape hatch for a type AWS has since made importable. Expect the changeset to be rejected if the heuristic was right.", false).option("--no-recreate-import-unsupported", "Block instead of auto-handling resource types AWS does NOT support in IMPORT changesets (currently only AWS::ApiGatewayV2::Stage, emitted by CDK HttpApi). Default behavior: cdkd skips these from phase 1, deletes the AWS-side resource between phases, and lets CFn re-CREATE in phase 2 (brief unavailability window). With this flag, the export aborts with a clear error instead.").action(withErrorHandling(exportCommand));
|
|
@@ -73739,6 +73864,26 @@ function formatStackRef(ref) {
|
|
|
73739
73864
|
return ref.region ? `${ref.stackName} (${ref.region})` : ref.stackName;
|
|
73740
73865
|
}
|
|
73741
73866
|
/**
|
|
73867
|
+
* {@link formatStackRef} for a sentence a CONFIRMATION PROMPT renders.
|
|
73868
|
+
*
|
|
73869
|
+
* Both halves come from an S3 key segment (or, for a legacy record, a state
|
|
73870
|
+
* body), so both are attacker-influenced in exactly the way issue #2170 round
|
|
73871
|
+
* 4 found for the lock error sixty lines below this helper's callers: a
|
|
73872
|
+
* planted `\n` forged a whole line inside that sentence. A forged line in a
|
|
73873
|
+
* PROMPT is strictly worse than one in an error, because the sentence it
|
|
73874
|
+
* corrupts is the one the operator answers `y` to.
|
|
73875
|
+
*
|
|
73876
|
+
* `asciiOnly` matches the lock error's own call on these same values — a
|
|
73877
|
+
* stack name and an AWS region both have a known charset — and is a no-op on
|
|
73878
|
+
* every ordinary input, so the shipped prompt strings are byte-identical.
|
|
73879
|
+
* `UNRENDERABLE` stands in when sanitising leaves nothing, since an empty
|
|
73880
|
+
* `()` would read as "no region" rather than "a region cdkd will not print".
|
|
73881
|
+
*/
|
|
73882
|
+
function formatStackRefSafe(ref) {
|
|
73883
|
+
const stack = displaySafe(ref.stackName, { asciiOnly: true }) || "<unrenderable>";
|
|
73884
|
+
return ref.region ? `${stack} (${displaySafe(ref.region, { asciiOnly: true }) || "<unrenderable>"})` : stack;
|
|
73885
|
+
}
|
|
73886
|
+
/**
|
|
73742
73887
|
* Resolve a stack name + optional region flag against the `listStacks` index
|
|
73743
73888
|
* built up front. When a name resolves to multiple regions and the caller
|
|
73744
73889
|
* didn't pin one, surface a clear error listing the candidates so the user
|
|
@@ -73842,7 +73987,7 @@ function sortRefs(refs) {
|
|
|
73842
73987
|
async function stateListCommand(options) {
|
|
73843
73988
|
const logger = getLogger();
|
|
73844
73989
|
if (options.verbose) logger.setLevel("debug");
|
|
73845
|
-
|
|
73990
|
+
reserveStdoutForPayload();
|
|
73846
73991
|
const setup = await setupStateBackend(options);
|
|
73847
73992
|
try {
|
|
73848
73993
|
const refs = sortRefs(await setup.stateBackend.listStacks());
|
|
@@ -74311,16 +74456,9 @@ async function stateOrphanCommand(stackArgs, options) {
|
|
|
74311
74456
|
}
|
|
74312
74457
|
}
|
|
74313
74458
|
if (!options.yes && !options.force) {
|
|
74314
|
-
const targetList = targets.map((t) =>
|
|
74459
|
+
const targetList = targets.map((t) => formatStackRefSafe(t)).join(", ");
|
|
74315
74460
|
process.stdout.write(`\nWARNING: This removes cdkd's state record for [${targetList}] only. AWS resources will NOT be deleted.\nUse 'cdkd destroy ${stackName}' if you want to delete the actual resources.\n\n`);
|
|
74316
|
-
|
|
74317
|
-
input: process.stdin,
|
|
74318
|
-
output: process.stdout
|
|
74319
|
-
});
|
|
74320
|
-
const answer = await rl.question(`Remove state for ${targetList} from s3://${setup.bucket}/${setup.prefix}/? (y/N): `);
|
|
74321
|
-
rl.close();
|
|
74322
|
-
const trimmed = answer.trim().toLowerCase();
|
|
74323
|
-
if (trimmed !== "y" && trimmed !== "yes") {
|
|
74461
|
+
if (!await confirmStateOrphanRemoval(`Remove state for ${targetList} from s3://${setup.bucket}/${setup.prefix}/?`)) {
|
|
74324
74462
|
logger.info(`Cancelled removal of state for stack: ${stackName}`);
|
|
74325
74463
|
continue;
|
|
74326
74464
|
}
|
|
@@ -74886,7 +75024,7 @@ async function stateRefreshObservedCommand(stackArgs, options) {
|
|
|
74886
75024
|
}
|
|
74887
75025
|
}
|
|
74888
75026
|
if (!options.yes && !options.dryRun) {
|
|
74889
|
-
const targetList = targets.map(
|
|
75027
|
+
const targetList = targets.map(formatStackRefSafe).join(", ");
|
|
74890
75028
|
if (!await confirmRefresh(`Refresh observedProperties for ${targets.length} stack(s) (${targetList})?`)) {
|
|
74891
75029
|
logger.info("Aborted.");
|
|
74892
75030
|
return;
|
|
@@ -75067,17 +75205,34 @@ async function refreshObservedForStack(stackName, region, stateBackend, lockMana
|
|
|
75067
75205
|
});
|
|
75068
75206
|
}
|
|
75069
75207
|
}
|
|
75070
|
-
|
|
75071
|
-
|
|
75072
|
-
|
|
75073
|
-
|
|
75208
|
+
/**
|
|
75209
|
+
* `cdkd state orphan`'s confirmation prompt. Its only call site is inside the
|
|
75210
|
+
* `if (!options.yes && !options.force)` block in `stateOrphanCommand`, which
|
|
75211
|
+
* is what keeps `confirmOrRefuse`'s non-interactive refusal (issue #2275)
|
|
75212
|
+
* from firing on a flagged run.
|
|
75213
|
+
*
|
|
75214
|
+
* The `(y/N): ` suffix is preserved verbatim from before issue #2275 folded
|
|
75215
|
+
* the guard in: it is user-visible output, and only this prompt and
|
|
75216
|
+
* `cdkd rollback` ever spelled it that way.
|
|
75217
|
+
*
|
|
75218
|
+
* Exported for unit testing — internal to the state-orphan flow otherwise.
|
|
75219
|
+
*/
|
|
75220
|
+
async function confirmStateOrphanRemoval(prompt) {
|
|
75221
|
+
return confirmOrRefuse(prompt, {
|
|
75222
|
+
suffix: " (y/N): ",
|
|
75223
|
+
refusal: "The cdkd state orphan confirmation prompt cannot run in a non-interactive environment. Pass -y / --yes (or -f / --force) to confirm the removal, or run the command from a real terminal."
|
|
75074
75224
|
});
|
|
75075
|
-
|
|
75076
|
-
|
|
75077
|
-
|
|
75078
|
-
|
|
75079
|
-
|
|
75080
|
-
|
|
75225
|
+
}
|
|
75226
|
+
/**
|
|
75227
|
+
* `cdkd state refresh-observed`'s confirmation prompt. Its only call site is
|
|
75228
|
+
* inside the `if (!options.yes && !options.dryRun)` block above, which is what
|
|
75229
|
+
* keeps `confirmOrRefuse`'s non-interactive refusal (issue #2275) from firing
|
|
75230
|
+
* on a `--yes` run.
|
|
75231
|
+
*
|
|
75232
|
+
* Exported for unit testing — internal to the refresh-observed flow otherwise.
|
|
75233
|
+
*/
|
|
75234
|
+
async function confirmRefresh(prompt) {
|
|
75235
|
+
return confirmOrRefuse(prompt, { refusal: "The cdkd state refresh-observed confirmation prompt cannot run in a non-interactive environment. Pass -y / --yes to confirm the refresh, or run the command from a real terminal." });
|
|
75081
75236
|
}
|
|
75082
75237
|
/**
|
|
75083
75238
|
* Create the `state refresh-observed` subcommand.
|
|
@@ -75208,17 +75363,20 @@ function failedActionLabel(item, skipFinalSnapshot) {
|
|
|
75208
75363
|
case "skip-failed-absent": return ` - skip ${op.logicalId} (${op.resourceType}) — no previous state available`;
|
|
75209
75364
|
}
|
|
75210
75365
|
}
|
|
75366
|
+
/**
|
|
75367
|
+
* `cdkd rollback`'s confirmation prompt. Exported for unit testing — internal
|
|
75368
|
+
* to the rollback flow otherwise, whose only call site is inside the
|
|
75369
|
+
* `if (!skipConfirmation)` block below.
|
|
75370
|
+
*
|
|
75371
|
+
* The `(y/N): ` suffix is preserved verbatim from before issue #2275 folded
|
|
75372
|
+
* the non-interactive guard into `confirmOrRefuse`: it is user-visible output,
|
|
75373
|
+
* and only this site and `cdkd state orphan` ever spelled it that way.
|
|
75374
|
+
*/
|
|
75211
75375
|
async function confirm(question) {
|
|
75212
|
-
|
|
75213
|
-
|
|
75214
|
-
|
|
75376
|
+
return confirmOrRefuse(question, {
|
|
75377
|
+
suffix: " (y/N): ",
|
|
75378
|
+
refusal: "The cdkd rollback confirmation prompt cannot run in a non-interactive environment. Pass --force (or -y / --yes) to confirm the rollback, or run the command from a real terminal."
|
|
75215
75379
|
});
|
|
75216
|
-
try {
|
|
75217
|
-
const t = (await rl.question(`${question} (y/N): `)).trim().toLowerCase();
|
|
75218
|
-
return t === "y" || t === "yes";
|
|
75219
|
-
} finally {
|
|
75220
|
-
rl.close();
|
|
75221
|
-
}
|
|
75222
75380
|
}
|
|
75223
75381
|
async function rollbackCommand(stackArg, options) {
|
|
75224
75382
|
const logger = getLogger();
|
|
@@ -77691,17 +77849,16 @@ function stringifyForAudit(value) {
|
|
|
77691
77849
|
if (typeof value === "string") return JSON.stringify(value);
|
|
77692
77850
|
return JSON.stringify(value);
|
|
77693
77851
|
}
|
|
77852
|
+
/**
|
|
77853
|
+
* `cdkd orphan`'s confirmation prompt. Its only call site is inside the
|
|
77854
|
+
* `if (!options.yes && !options.force)` block above, which is what keeps
|
|
77855
|
+
* `confirmOrRefuse`'s non-interactive refusal (issue #2275) from firing on a
|
|
77856
|
+
* flagged run.
|
|
77857
|
+
*
|
|
77858
|
+
* Exported for unit testing — internal to the command flow otherwise.
|
|
77859
|
+
*/
|
|
77694
77860
|
async function confirmPrompt$1(prompt) {
|
|
77695
|
-
|
|
77696
|
-
input: process.stdin,
|
|
77697
|
-
output: process.stdout
|
|
77698
|
-
});
|
|
77699
|
-
try {
|
|
77700
|
-
const ans = await rl.question(`${prompt} [y/N] `);
|
|
77701
|
-
return /^y(es)?$/i.test(ans.trim());
|
|
77702
|
-
} finally {
|
|
77703
|
-
rl.close();
|
|
77704
|
-
}
|
|
77861
|
+
return confirmOrRefuse(prompt, { refusal: "The cdkd orphan confirmation prompt cannot run in a non-interactive environment. Pass -y / --yes (or -f / --force) to confirm the orphan, or run the command from a real terminal." });
|
|
77705
77862
|
}
|
|
77706
77863
|
/**
|
|
77707
77864
|
* Create the top-level `cdkd orphan` command.
|
|
@@ -78714,17 +78871,15 @@ function formatOutcome(outcome) {
|
|
|
78714
78871
|
case "failed": return "✗";
|
|
78715
78872
|
}
|
|
78716
78873
|
}
|
|
78874
|
+
/**
|
|
78875
|
+
* `cdkd import`'s confirmation prompt. Its only call site is inside the
|
|
78876
|
+
* `if (!options.yes)` block above, which is what keeps `confirmOrRefuse`'s
|
|
78877
|
+
* non-interactive refusal (issue #2275) from firing on a `--yes` run.
|
|
78878
|
+
*
|
|
78879
|
+
* Exported for unit testing — internal to the command flow otherwise.
|
|
78880
|
+
*/
|
|
78717
78881
|
async function confirmPrompt(prompt) {
|
|
78718
|
-
|
|
78719
|
-
input: process.stdin,
|
|
78720
|
-
output: process.stdout
|
|
78721
|
-
});
|
|
78722
|
-
try {
|
|
78723
|
-
const ans = await rl.question(`${prompt} [y/N] `);
|
|
78724
|
-
return /^y(es)?$/i.test(ans.trim());
|
|
78725
|
-
} finally {
|
|
78726
|
-
rl.close();
|
|
78727
|
-
}
|
|
78882
|
+
return confirmOrRefuse(prompt, { refusal: "The cdkd import confirmation prompt cannot run in a non-interactive environment. Pass -y / --yes to confirm the state write, or run the command from a real terminal." });
|
|
78728
78883
|
}
|
|
78729
78884
|
/**
|
|
78730
78885
|
* Create the `cdkd import` top-level command.
|
|
@@ -89038,4 +89193,4 @@ function buildProgram() {
|
|
|
89038
89193
|
|
|
89039
89194
|
//#endregion
|
|
89040
89195
|
export { buildProgram };
|
|
89041
|
-
//# sourceMappingURL=program-
|
|
89196
|
+
//# sourceMappingURL=program-CjJoJOIE.js.map
|