@go-to-k/cdkd 0.290.43 → 0.290.45
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-C9R-ND4b.js → asg-provider-CVB0Ky06.js} +3 -3
- package/dist/{asg-provider-C9R-ND4b.js.map → asg-provider-CVB0Ky06.js.map} +1 -1
- package/dist/cli.js +2 -2
- package/dist/{deploy-engine-Bw8VoyEi.js → deploy-engine-DhZW4if5.js} +565 -55
- package/dist/deploy-engine-DhZW4if5.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/{logger-D-2HeLmd.js → logger-DjBU2Ap3.js} +10 -1
- package/dist/logger-DjBU2Ap3.js.map +1 -0
- package/dist/{program-Bh8a5wjj.js → program-BDy35kIL.js} +131 -113
- package/dist/{program-Bh8a5wjj.js.map → program-BDy35kIL.js.map} +1 -1
- package/dist/{version-ChfV4K6h.js → version-DMaX1bq2.js} +2 -2
- package/dist/{version-ChfV4K6h.js.map → version-DMaX1bq2.js.map} +1 -1
- package/package.json +1 -1
- package/dist/deploy-engine-Bw8VoyEi.js.map +0 -1
- package/dist/logger-D-2HeLmd.js.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { $ as yellow, $i as
|
|
2
|
-
import { C as displayAwsMessage, D as truncateCodePoints, E as isPasteableIdent, 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-
|
|
1
|
+
import { $ as yellow, $i as AssemblyReader, $n as safeStackName, $r as assertAssetBucketRegion, $t as requireConfigObject, A as createPreDeleteFinalSnapshot, Aa as ResourceTimeoutError, Ai as resolveCaptureObservedState, An as malformedOutputsRefusalMessage, Ar as formatLockExpiry, At as carriesDynamicReference, B as isStatefulRecreateTargetSync, Ba as isMarkedNonRetryable, Bi as MIGRATE_TMP_PREFIX, Bn as refuseMalformedOrphansForDestroy, Br as isReadableBag, Bt as isSettledInstanceState, C as namesAnyDeclaredParameter, Ca as LocalInvokeBuildError$1, Ci as getDockerImageBySourceHash, Cn as isReadableResourceEntry, Cr as LockManager, Ct as slowCcOperationTimeoutMs, D as PRE_DELETE_SNAPSHOT_TYPES, Da as NestedStackChildDirectDestroyError, Di as getLegacyStateBucketName, Dn as malformedOrphanRecordsWarning, Dr as buildForceUnlockCommand, Dt as disableInstanceApiTermination, E as ATOMIC_FINAL_SNAPSHOT_TYPES, Ea as MalformedProducerRecordRefusalError, Ei as getDefaultStateBucketName, En as malformedLocalOutputsWarning, Er as UNREPRODUCIBLE_LOCK_CLAUSE, Et as deleteSkipReason, F as extractDeploymentEventError, Fa as SynthesisError, Fi as stateBucketExistenceConfirmed, Fn as malformedResourcesWarning, Fr as hasReadableExportSet, Ft as isImpossibleEmptyStoredAttribute, G as toCfnInteger, Ga as markRedactedCause, Gi as injectiveKeyPrefix, Gn as refuseMalformedResourcesForDestroy, Gr as stringifyValue, Gt as coerceCfnBoolean, H as WARM_THROUGHPUT_MEMBERS, Ha as isThrottlingError, Hi as uploadCfnTemplate, Hn as refuseMalformedOutputsForDestroy, Hr as orphansCarriedFrom, Ht as normalizeAwsTagsToCfn, I as makeSiblingClaimReader, Ii as warnDeprecatedNoPrefixCliFlag, In as malformedStateRefusalMessage, Ir as hasReasonlessBaselineRefusal, It as isNamelessDynamicReferenceError, J as bold, Ja as safeStringify, Ji as decodeListingKey, Jn as repairMalformedOutputsForReadOnly, Jr as createAssetRedirectResolver, Jt as configIntegerRefusal, K as toFiniteNumber, Ka as retryClassificationText, Ki as producerCoordinateKey, Kn as refuseMalformedState, Kr as WorkGraph, Kt as coerceCfnInteger, L as planOrphanAdoption, Li as ssmResolvedValueType, Ln as refuseDivergentRecordRegionForDestroy, Lr as hasUnverifiableParameterRefusal, Lt as isUnboundTemplateParameter, M as refusesFinalSnapshot, Ma as StackHasActiveImportsError, Mi as resolveStateBucketWithDefault, Mn as malformedRenderedContainersWarning, Mr as CUSTOM_RESOURCE_RESPONSE_PREFIX, Mt as cfnRefValueFromPhysicalId, N as unsupportedFinalSnapshotError, Na as StackTerminationProtectionError, Ni as resolveStateBucketWithDefaultAndSource, Nn as malformedResourceEntriesWarning, Nr as DEFAULT_STATE_PREFIX, Nt as coerceParameterTypedValue, O as buildFinalSnapshotIdentifier, Oa as PartialFailureError, Oi as resolveApp, On as malformedOrphansRefusalMessage, Or as buildLockContentionMessage, Ot as isTerminationProtectionPropagationError, P as makeCanonicalizePropertiesFn, Pi as resolveUseCdkBootstrapAssets, Pn as malformedResourcePropertiesWarning, Pr as exportNamesCarriedFrom, Pt as getAccountInfo, Q as red, Qi as derivePartitionAndUrlSuffix, Qn as safeRegion, Qr as BOOTSTRAP_MARKER_PREFIX, Qt as requireConfigArray, R as MULTI_REGION_RECREATE_BLOCKED_TYPES, Ra as normalizeAwsError, Ri as CFN_TEMPLATE_BODY_LIMIT, Rn as refuseMalformedNestedChildOutputs, Rr as importableOutputKeys, Rt as parameterTypeMayLoseSecretIdentity, S as computeParameterTaint, Sa as IntrinsicResolutionRefusalError, Si as AssetManifestLoader, Sn as hasReadableResources, Sr as scrubResourceRecord, St as isWaitAbandonedError, T as resourcesNamingDeclaredParameter, Ti as synthesisStatusMessage, Tn as malformedExportSourceWarning, Tr as rebuildClientForBucketRegion, Tt as deleteIndeterminateGuards, U as coerceWarmThroughput$1, Ua as isTransientServerError, Ui as CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION, Un as refuseMalformedResourceEntries, Ur as shouldRetainResource, Ut as resolveExplicitPhysicalId, V as renderStatefulReason, Va as isRetryableTransientError, Vi as findLargeInlineResources, Vn as refuseMalformedOutputs, Vr as orphansAfterRollback, Vt as WAFv2WebACLProvider, W as isWarmThroughputDecrease, Wa as markNonRetryable, Wi as injectiveKey, Wn as refuseMalformedResourcePropertiesForOrphan, Wr as AssetPublisher, Wt as assertRegionMatch, X as gray, Xi as PARTITION_TABLE, Xn as repairMalformedResourcePropertiesForReadOnly, Xr as rewriteTemplateAssetReferences, Xt as readConfigString, Y as cyan, Yi as expectedOwnerParam, Yn as repairMalformedResourceEntriesForReadOnly, Yr as loadPublishableAssetManifest, Yt as configStringRefusal, Z as green, Zi as canonicalizeRegion, Zn as repairMalformedResourcesForReadOnly, Zr as AssetModeResolver, Zt as replayWarn, _ as bagHoldsSecretExpression, _i as redactDockerArgvValues, _n as UNREADABLE_ORPHANS_CONTAINER_ROW, _r as maskSecretsInError, _t as endCommandInterruptScope, a as DeploymentEventsStore, aa as nullPrototypeRecord, ai as validateAssetBucketName, an as s3BucketDomainName, ar as TemplateParser, at as secretBearingStateKeyWarning, b as mergeNoChangeOutputs, ba as DeployCancelledError, bi as escapeRegExp, bn as hasReadableOrphans, br as recoverMaskedOutput, bt as startInterruptWatch, c as replayFailedOperations, ca as resolveAssemblyPath, ci as buildDockerImage, cn as s3BucketWebsiteUrl, cr as STATE_SOURCED_READBACK_RULES, ct as IAMRoleProvider, d as updatePartialMessage, da as AwsClients, di as describeDockerExecFailure, dn as applyCallerIdentityCredentials, dr as createSecretMasker, dt as ProviderRegistry, ea as failedStageNote, ei as ensureAssetStorage, en as requireConfigString, er as findActionableSilentDrops, et as collectDeclaredOutputNames, f as updatePartialReason, fa as getAwsClients, fi as describeDockerFailure, fn as callerEnvCredentials, fr as dynamicReferenceTokens, ft as wouldReturnToSdkProvider, g as computeImplicitDeleteEdges, ga as CdkdError, gi as partitionSensitiveEnv, gn as STATE_RESOURCES_MALFORMED, gr as markSameGenerationBag, gt as beginCommandInterruptScope, h as IMPLICIT_DELETE_DEPENDENCIES, hi as getDockerCmd, hn as INTRINSIC_KEYS, hr as isSingleDynamicReferenceToken, ht as maskerOrIdentity, i as DeploymentEventsReader, ia as hasPlainPrototype, ii as readBootstrapMarkerBody, in as s3BucketArn, ir as DagBuilder, it as secretBearing, j as isFinalSnapshotError, ja as ResourceUpdateNotSupportedError, ji as resolveSkipPrefix, jn as malformedOutputsWarning, jr as shellQuote, jt as carriesFetchableDynamicReference, k as ccRoutedFinalSnapshotError, ka as ProvisioningError, ki as resolveAutoAssetStorage, kn as malformedOrphansWarning, kr as forceQuitRecoveryClause, kt as IntrinsicFunctionResolver, l as replayRollback, li as resolveDockerContextDirectory, ln as applyRoleArnIfSet, lr as TEMPLATE_SOURCED_RULES, lt as collectInlinePolicyNamesManagedBySiblings, m as maskingRetryLogger, ma as setAwsClients, mi as formatDockerLoginError, mn as DiffCalculator, mr as identityKeyFor, mt as maskDeep, n as DEFAULT_RESOURCE_WARN_AFTER_MS, na as defineOwnKey, ni as isCrossRegionRedirect, nn as producerRegionsFromState, nr as describeTypeWithThrottleRetry, nt as exportAliasCollisionScrubWarning, o as planFailedOps, oa as ownValue, oi as validateContainerRepoName, on as s3BucketDualStackDomainName, or as STATE_SOURCED_BASELINE_RULES, ot as secretSafeKeyDisplay, p as withResourceDeadline, pa as resetAwsClients, pi as dockerSpawnEnvWithSensitive, pn as envCredentialsAreAssumedRole, pr as errorCauseChain, pt as createMaskedRetryLogger, q as formatResourceLine, qa as describeAwsFailure, qi as producerRecordKey, qn as repairMalformedOrphansForReadOnly, qr as buildAssetRedirectMap, qt as configBooleanRefusal, r as DeployEngine, ra as hasOwnKey, ri as parseBootstrapMarker, rn as withSharedDrainBudget, rr as withRetry, rt as isExportAliasCollision, s as planRollback, sa as renderAssemblyPathEscape, si as buildDenyExternalAccessPolicy, sn as s3BucketRegionalDomainName, sr as STATE_SOURCED_CROSS_GENERATION_RULES, st as getCurrentResourceSecrets, t as DEFAULT_RESOURCE_TIMEOUT_MS, ta as processStackMessages, ti as getBootstrapMarkerKey, tn as classifyReplaySecretRegion, tr as findSilentDropProperties, tt as collectPublishedOutputNames, u as resolveReplacementOldType, ua as resolveBucketRegion, ui as describeDockerCapturedOutput, un as AWS_CREDENTIAL_ENV_KEYS, ur as carriesSecretMask, ut as clearOnUpdateRemoval, v as isSecretBearingReferenceString, va as CrossAccountSecretRefusalError, vi as runDockerForeground, vn as UNREADABLE_RESOURCES_MAP_ROW, vr as maskSecretsInText, vt as interruptWatchListenerCount, w as reachableDivergentParameters, wa as LocalStartServiceError, wi as Synthesizer, wn as malformedExportNamesWarning, wr as S3StateBackend, wt as UNSPECIFIED_SKIP_REASON, x as bindingSkippedOutputs, xa as DynamicReferenceRegionAmbiguousError, xi as stripControlChars, xn as hasReadableOutputs, xr as redactSecretsForState, xt as CloudControlProvider, y as keptWholeReasonText, yi as runDockerStreaming, yn as displayLogicalId, yr as recordMaskOnlyValue, yt as isInterruptedWaitError, z as isStatefulRecreateTargetForReplace, za as withErrorHandling, zi as CFN_TEMPLATE_URL_LIMIT, zn as refuseMalformedOrphans, zr as importableOutputs, zt as refStateLookupFromResource } from "./deploy-engine-DhZW4if5.js";
|
|
2
|
+
import { C as displayAwsMessage, D as truncateCodePoints, E as isPasteableIdent, 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-DjBU2Ap3.js";
|
|
3
3
|
import { n as awsClientDefaults } from "./aws-client-defaults-BoIxyCir.js";
|
|
4
|
-
import { t as getCdkdVersion } from "./version-
|
|
5
|
-
import { a as renderDisableCommand, i as protectedReplacementAdvice, r as UNNAMEABLE_ID_CLAUSE, t as ASGProvider } from "./asg-provider-
|
|
4
|
+
import { t as getCdkdVersion } from "./version-DMaX1bq2.js";
|
|
5
|
+
import { a as renderDisableCommand, i as protectedReplacementAdvice, r as UNNAMEABLE_ID_CLAUSE, t as ASGProvider } from "./asg-provider-CVB0Ky06.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";
|
|
@@ -2361,6 +2361,25 @@ function createSynthCommand() {
|
|
|
2361
2361
|
|
|
2362
2362
|
//#endregion
|
|
2363
2363
|
//#region src/cli/stack-matcher.ts
|
|
2364
|
+
/**
|
|
2365
|
+
* Match stacks against user-supplied name patterns.
|
|
2366
|
+
*
|
|
2367
|
+
* Patterns are evaluated against two fields:
|
|
2368
|
+
*
|
|
2369
|
+
* - `stackName` — the physical CloudFormation stack name (e.g. `MyStage-MyStack`)
|
|
2370
|
+
* - `displayName` — the hierarchical CDK path (e.g. `MyStage/MyStack`); falls
|
|
2371
|
+
* back to `stackName` when the assembly does not carry one
|
|
2372
|
+
*
|
|
2373
|
+
* Routing is decided by whether the pattern contains `/`:
|
|
2374
|
+
*
|
|
2375
|
+
* - Pattern contains `/` → matched only against `displayName` (a `/` cannot
|
|
2376
|
+
* appear in a CloudFormation stack name, so this is unambiguous)
|
|
2377
|
+
* - Pattern contains no `/` → matched only against `stackName`
|
|
2378
|
+
*
|
|
2379
|
+
* Wildcards (`*`) are supported in either case. Results are de-duplicated by
|
|
2380
|
+
* `stackName`, so a pattern that incidentally matches the same stack via both
|
|
2381
|
+
* fields is returned only once.
|
|
2382
|
+
*/
|
|
2364
2383
|
function matchStacks(stacks, patterns) {
|
|
2365
2384
|
if (patterns.length === 0) return [];
|
|
2366
2385
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -2375,10 +2394,57 @@ function matchStacks(stacks, patterns) {
|
|
|
2375
2394
|
* Render a stack for diagnostic messages. When `displayName` differs from the
|
|
2376
2395
|
* physical name, both are shown so the user can see which forms are valid as
|
|
2377
2396
|
* patterns (e.g. `MyStage-Api (MyStage/Api)`).
|
|
2397
|
+
*
|
|
2398
|
+
* Both names come from the Cloud Assembly, and every one of this helper's
|
|
2399
|
+
* render sites interpolates the result into PROSE cdkd authors — `Available:
|
|
2400
|
+
* ...`, `Multiple stacks found: ...`, `Publishing assets for stack: ...`, the
|
|
2401
|
+
* last of which prints on a normal run rather than only on an error. So they
|
|
2402
|
+
* go through `displayIdent` ([#3277](https://github.com/go-to-k/cdkd/issues/3277)):
|
|
2403
|
+
* a `stackName` carrying `ESC [ 2 K` plus a carriage return ERASES cdkd's own
|
|
2404
|
+
* line and a newline forges a second one, and a value carrying quotes and
|
|
2405
|
+
* periods writes a cdkd-sounding clause.
|
|
2406
|
+
*
|
|
2407
|
+
* It is the identity on every legitimate `stackName` — a CloudFormation stack
|
|
2408
|
+
* name is `[A-Za-z0-9-]`, inside `PLAIN_IDENT`. It is NOT the identity on
|
|
2409
|
+
* every legitimate `displayName`: CDK sets that to the construct path, and
|
|
2410
|
+
* `constructs` rewrites only `/` in an id, so `new Stack(app, 'My Stack')` is
|
|
2411
|
+
* legal and prints `MyStack ("My Stack")`. Those quotes are not part of any
|
|
2412
|
+
* pattern, in a clause whose job is to say which forms ARE valid as patterns —
|
|
2413
|
+
* accepted, because the alternative is `displaySafe`, which passes the quotes
|
|
2414
|
+
* and spaces a crafted value needs, and the pattern still matches the RAW
|
|
2415
|
+
* name either way (`matchStacks` never sees this rendering).
|
|
2416
|
+
*
|
|
2417
|
+
* Sanitizing HERE rather than at the call sites is what keeps the rule whole:
|
|
2418
|
+
* the sites include `scrub.ts` and `destroy.ts`, which this change does not
|
|
2419
|
+
* touch, and a rule widened by hand is how the class survived being closed
|
|
2420
|
+
* twice already.
|
|
2378
2421
|
*/
|
|
2379
2422
|
function describeStack(stack) {
|
|
2380
|
-
|
|
2381
|
-
return stack.
|
|
2423
|
+
const name = displayIdent(stack.stackName, { maxCodePoints: STACK_REF_MAX_CODE_POINTS });
|
|
2424
|
+
if (stack.displayName && stack.displayName !== stack.stackName) return `${name} (${displayIdent(stack.displayName, { maxCodePoints: STACK_REF_MAX_CODE_POINTS })})`;
|
|
2425
|
+
return name;
|
|
2426
|
+
}
|
|
2427
|
+
/**
|
|
2428
|
+
* The message a command raises when SELECTION came back empty — shared by
|
|
2429
|
+
* `deploy`, `diff`, `list` and `publish-assets`, which all built the identical
|
|
2430
|
+
* string by hand.
|
|
2431
|
+
*
|
|
2432
|
+
* `assembly` is required AND so is its `failedStages` member, which is the
|
|
2433
|
+
* point: a Stage that failed to load dropped every stack under it from
|
|
2434
|
+
* `available`, so "no stacks matching" names the wrong problem unless the
|
|
2435
|
+
* failure is reported with it (issue
|
|
2436
|
+
* [#3482](https://github.com/go-to-k/cdkd/issues/3482)). A REQUIRED member,
|
|
2437
|
+
* not an optional one — `{ failedStages?: ... }` accepts `{}`, so it fences
|
|
2438
|
+
* the argument while leaving the content unfenced, which is the wiring hole
|
|
2439
|
+
* this signature exists to close. `SynthesisResult.failedStages` is required
|
|
2440
|
+
* for the same reason, so passing the result satisfies it and an ad-hoc `{}`
|
|
2441
|
+
* does not.
|
|
2442
|
+
*
|
|
2443
|
+
* What it does NOT fence: a caller passing a STALE or empty list. That is
|
|
2444
|
+
* behaviour, not shape, and it is covered by a wiring test per command.
|
|
2445
|
+
*/
|
|
2446
|
+
function renderNoStackMatch(patterns, available, assembly) {
|
|
2447
|
+
return (patterns.length > 0 ? `No stacks matching ${patterns.join(", ")} found in assembly. ` + (available.length > 0 ? `Available: ${available.map(describeStack).join(", ")}` : "The assembly has no stacks") : "No stacks found in assembly") + failedStageNote(patterns, assembly.failedStages);
|
|
2382
2448
|
}
|
|
2383
2449
|
function stackMatchesPattern(stack, pattern) {
|
|
2384
2450
|
const target = pattern.includes("/") ? stack.displayName ?? stack.stackName : stack.stackName;
|
|
@@ -2456,10 +2522,11 @@ async function listCommand(patterns, options) {
|
|
|
2456
2522
|
...Object.keys(context).length > 0 && { context },
|
|
2457
2523
|
deferMacroExpansion: true
|
|
2458
2524
|
};
|
|
2459
|
-
const
|
|
2460
|
-
|
|
2525
|
+
const result = await synthesizer.synthesize(synthOptions);
|
|
2526
|
+
const allStacks = result.stacks;
|
|
2527
|
+
if (allStacks.length === 0) throw new Error(renderNoStackMatch(patterns, allStacks, result));
|
|
2461
2528
|
const selected = patterns.length > 0 ? matchStacks(allStacks, patterns) : allStacks;
|
|
2462
|
-
if (selected.length === 0) throw new Error(
|
|
2529
|
+
if (selected.length === 0) throw new Error(renderNoStackMatch(patterns, allStacks, result));
|
|
2463
2530
|
const sorted = sortByDependency(selected);
|
|
2464
2531
|
if (options.long) {
|
|
2465
2532
|
emitStructured(sorted.map((s) => toLongRecord(s, options.showDependencies)), options.json);
|
|
@@ -63995,6 +64062,7 @@ async function runDestroyForStack(stackName, state, ctx) {
|
|
|
63995
64062
|
const guardIndeterminateTargets = /* @__PURE__ */ new Set();
|
|
63996
64063
|
const regionForState = state.region ?? ctx.baseRegion;
|
|
63997
64064
|
refuseMalformedResourcesForDestroy(state, stackName, regionForState);
|
|
64065
|
+
refuseMalformedOrphansForDestroy(state, stackName, regionForState);
|
|
63998
64066
|
refuseDivergentRecordRegionForDestroy(state, stackName, regionForState, ctx.divergentBodyRegion);
|
|
63999
64067
|
const resourceCount = Object.keys(state.resources).length;
|
|
64000
64068
|
const orphanCount = (state.orphans ?? []).length;
|
|
@@ -64045,7 +64113,10 @@ async function runDestroyForStack(stackName, state, ctx) {
|
|
|
64045
64113
|
emptyLockHeld = true;
|
|
64046
64114
|
try {
|
|
64047
64115
|
const recheck = await ctx.stateBackend.getState(stackName, regionForState);
|
|
64048
|
-
if (recheck)
|
|
64116
|
+
if (recheck) {
|
|
64117
|
+
refuseMalformedResourcesForDestroy(recheck.state, stackName, regionForState);
|
|
64118
|
+
refuseMalformedOrphansForDestroy(recheck.state, stackName, regionForState);
|
|
64119
|
+
}
|
|
64049
64120
|
const recheckResources = recheck ? Object.keys(recheck.state.resources).length : 0;
|
|
64050
64121
|
const recheckOrphans = recheck ? (recheck.state.orphans ?? []).length : 0;
|
|
64051
64122
|
if (!(!recheck || recheckResources === 0 && recheckOrphans === 0)) throw new Error(`Stack '${stackName}' (${regionForState}) was empty when this run started but now has ${recheckResources} resource(s) and ${recheckOrphans} rollback-orphaned resource(s) — another cdkd process wrote to it. Re-run the destroy to act on the current state.`);
|
|
@@ -66034,11 +66105,12 @@ async function deployCommand(stacks, options) {
|
|
|
66034
66105
|
logger.debug(`Found ${allStacks.length} stack(s) in assembly`);
|
|
66035
66106
|
const stackPatterns = stacks.length > 0 ? stacks : options.stack ? [options.stack] : [];
|
|
66036
66107
|
let targetStacks;
|
|
66108
|
+
if (allStacks.length === 0) throw new Error(renderNoStackMatch(stackPatterns, allStacks, result));
|
|
66037
66109
|
if (options.all) targetStacks = allStacks;
|
|
66038
66110
|
else if (stackPatterns.length > 0) targetStacks = matchStacks(allStacks, stackPatterns);
|
|
66039
66111
|
else if (allStacks.length === 1) targetStacks = allStacks;
|
|
66040
66112
|
else throw new Error(`Multiple stacks found: ${allStacks.map(describeStack).join(", ")}. Specify stack name(s) or use --all`);
|
|
66041
|
-
if (targetStacks.length === 0) throw new Error(stackPatterns
|
|
66113
|
+
if (targetStacks.length === 0) throw new Error(renderNoStackMatch(stackPatterns, allStacks, result));
|
|
66042
66114
|
const inferredCrossStackDeps = inferCrossStackStackDeps(allStacks);
|
|
66043
66115
|
const effectiveStackDeps = (stackName, deps) => {
|
|
66044
66116
|
const union = new Set(deps);
|
|
@@ -66287,7 +66359,7 @@ async function deployCommand(stacks, options) {
|
|
|
66287
66359
|
awsClients: stackAwsClients,
|
|
66288
66360
|
stateBucket,
|
|
66289
66361
|
exportIndexStore,
|
|
66290
|
-
nestedTemplates: stackInfo.nestedTemplates ??
|
|
66362
|
+
nestedTemplates: stackInfo.nestedTemplates ?? nullPrototypeRecord(),
|
|
66291
66363
|
dagBuilder,
|
|
66292
66364
|
diffCalculator,
|
|
66293
66365
|
options: deployEngineOptions,
|
|
@@ -67902,7 +67974,7 @@ function readNestedTemplate(templatePath) {
|
|
|
67902
67974
|
*/
|
|
67903
67975
|
function indexNestedChildTemplates(template, templatePath) {
|
|
67904
67976
|
const dir = path.dirname(templatePath);
|
|
67905
|
-
const result =
|
|
67977
|
+
const result = nullPrototypeRecord();
|
|
67906
67978
|
for (const [logicalId, resource] of Object.entries(template.Resources ?? {})) {
|
|
67907
67979
|
if (resource?.Type !== "AWS::CloudFormation::Stack") continue;
|
|
67908
67980
|
const assetPath = resource.Metadata?.["aws:asset:path"];
|
|
@@ -67931,6 +68003,10 @@ async function loadStateOrEmpty(stackName, region, stateBackend) {
|
|
|
67931
68003
|
const unreadableProps = repairMalformedResourcePropertiesForReadOnly(result.state);
|
|
67932
68004
|
if (unreadableProps.length > 0) logger.warn(malformedResourcePropertiesWarning(stackName, region, unreadableProps));
|
|
67933
68005
|
if (repairMalformedOutputsForReadOnly(result.state)) logger.warn(malformedOutputsWarning(stackName, region));
|
|
68006
|
+
if (repairMalformedOrphansForReadOnly(result.state)) {
|
|
68007
|
+
logger.warn(malformedOrphansWarning(stackName, region));
|
|
68008
|
+
unreadable.push(UNREADABLE_ORPHANS_CONTAINER_ROW);
|
|
68009
|
+
}
|
|
67934
68010
|
if (isReadableBag(result.state.outputs) && !hasReadableExportSet(result.state)) logger.warn(malformedExportNamesWarning(stackName, region));
|
|
67935
68011
|
return {
|
|
67936
68012
|
state: result.state,
|
|
@@ -68707,10 +68783,10 @@ function renderDiffTree(node, isRoot, logFn) {
|
|
|
68707
68783
|
if (outputs.add + outputs.change + outputs.remove > 0) logFn(`${outputs.add} output(s) to add, ${outputs.change} to change, ${outputs.remove} to remove`);
|
|
68708
68784
|
if (node.adoptedOrphans.length > 0) logFn(`${node.adoptedOrphans.length} resource(s) to adopt from a previous rollback: ${node.adoptedOrphans.map(stripControlChars).join(", ")}`);
|
|
68709
68785
|
if (node.unreadable.length > 0) {
|
|
68710
|
-
const named = node.unreadable.slice(0, UNREADABLE_PREVIEW_NAMES).map((id) => id === "(resources map)" ? id : displayLogicalId(id));
|
|
68786
|
+
const named = node.unreadable.slice(0, UNREADABLE_PREVIEW_NAMES).map((id) => id === "(resources map)" || id === "(orphans container)" ? id : displayLogicalId(id));
|
|
68711
68787
|
const rest = node.unreadable.length - named.length;
|
|
68712
|
-
const
|
|
68713
|
-
logFn(`${node.unreadable.length} state record row(s) could not be read: ${named.join(", ")}${rest > 0 ? ` and ${rest} more` : ""}.` + (
|
|
68788
|
+
const onlyContainerRows = node.unreadable.every((id) => id === "(resources map)" || id === "(orphans container)");
|
|
68789
|
+
logFn(`${node.unreadable.length} state record row(s) could not be read: ${named.join(", ")}${rest > 0 ? ` and ${rest} more` : ""}.` + (onlyContainerRows ? "" : " One the template still declares is shown above as a create; one it no longer declares is not shown above."));
|
|
68714
68790
|
}
|
|
68715
68791
|
}
|
|
68716
68792
|
if (node.blocking.length > 0) {
|
|
@@ -68804,15 +68880,17 @@ async function diffCommand(stacks, options) {
|
|
|
68804
68880
|
...options.profile && { macroExpandS3ClientOpts: { profile: options.profile } },
|
|
68805
68881
|
deferMacroExpansion: true
|
|
68806
68882
|
};
|
|
68807
|
-
const
|
|
68883
|
+
const result = await synthesizer.synthesize(synthOptions);
|
|
68884
|
+
const { stacks: allStacks } = result;
|
|
68808
68885
|
logger.info(`Found ${allStacks.length} stack(s) in assembly`);
|
|
68809
68886
|
const stackPatterns = stacks.length > 0 ? stacks : options.stack ? [options.stack] : [];
|
|
68810
68887
|
let targetStacks;
|
|
68888
|
+
if (allStacks.length === 0) throw new Error(renderNoStackMatch(stackPatterns, allStacks, result));
|
|
68811
68889
|
if (options.all) targetStacks = allStacks;
|
|
68812
68890
|
else if (stackPatterns.length > 0) targetStacks = matchStacks(allStacks, stackPatterns);
|
|
68813
68891
|
else if (allStacks.length === 1) targetStacks = allStacks;
|
|
68814
68892
|
else throw new Error(`Multiple stacks found: ${allStacks.map(describeStack).join(", ")}. Specify stack name(s) or use --all`);
|
|
68815
|
-
if (targetStacks.length === 0) throw new Error(stackPatterns
|
|
68893
|
+
if (targetStacks.length === 0) throw new Error(renderNoStackMatch(stackPatterns, allStacks, result));
|
|
68816
68894
|
await synthesizer.expandMacrosForStacks(targetStacks, synthOptions);
|
|
68817
68895
|
const stateConfig = {
|
|
68818
68896
|
bucket: stateBucket,
|
|
@@ -68876,7 +68954,7 @@ async function diffCommand(stacks, options) {
|
|
|
68876
68954
|
displayName: stackInfo.stackName,
|
|
68877
68955
|
region: stackRegion,
|
|
68878
68956
|
template: stackInfo.template,
|
|
68879
|
-
nestedTemplates: stackInfo.nestedTemplates ??
|
|
68957
|
+
nestedTemplates: stackInfo.nestedTemplates ?? nullPrototypeRecord(),
|
|
68880
68958
|
recursive,
|
|
68881
68959
|
stateBackend,
|
|
68882
68960
|
diffCalculator,
|
|
@@ -69286,6 +69364,12 @@ async function scrubCommand(stacks, options) {
|
|
|
69286
69364
|
*/
|
|
69287
69365
|
const malformedOutputRecords = [];
|
|
69288
69366
|
/**
|
|
69367
|
+
* Stacks whose `orphans` CONTAINER could not be read (go-to-k/cdkd#3379).
|
|
69368
|
+
* Its own list for the reason `malformedOutputRecords` is its own: the
|
|
69369
|
+
* audited error names the container that is broken.
|
|
69370
|
+
*/
|
|
69371
|
+
const malformedOrphanRecords = [];
|
|
69372
|
+
/**
|
|
69289
69373
|
* Stacks whose scrub met a PRODUCER record with an unreadable `outputs` map
|
|
69290
69374
|
* (go-to-k/cdkd#3192 review round 5).
|
|
69291
69375
|
*
|
|
@@ -69373,6 +69457,7 @@ async function scrubCommand(stacks, options) {
|
|
|
69373
69457
|
} else if (scrubbed.secretBearingKeys === 0 && scrubbed.unverifiableReads === 0 && scrubbed.unverifiableLeaves === 0 && indexConverged === 0) logger.info(`No plaintext secrets found in ${stack.stackName}`);
|
|
69374
69458
|
if (scrubbed.malformedResources) malformedRecords.push(stack.stackName);
|
|
69375
69459
|
if (scrubbed.malformedOutputs) malformedOutputRecords.push(stack.stackName);
|
|
69460
|
+
if (scrubbed.malformedOrphans) malformedOrphanRecords.push(stack.stackName);
|
|
69376
69461
|
if (scrubbed.unverifiableLeaves > 0) {
|
|
69377
69462
|
totalStacksWithUnverifiableLeaves++;
|
|
69378
69463
|
logger.warn(`${scrubbed.unverifiableLeaves} scan(s) in ${stack.stackName} were ABANDONED mid-value because a {{resolve:...}} reference could not be resolved (see the warnings above). The resolver stops at the first failing token, so a real secret after it in the same value recorded no needle — this stack is not reported clean. The count is per abandoned SCAN, not per secret: one record can contribute more than once (an output whose Export.Name and Value both abandon), and one abandoned scan can hide several unexamined leaves.`);
|
|
@@ -69408,7 +69493,7 @@ async function scrubCommand(stacks, options) {
|
|
|
69408
69493
|
totalIndexEntriesUnexamined += unexamined.length;
|
|
69409
69494
|
logger.info(`Exports index (${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.`);
|
|
69410
69495
|
}
|
|
69411
|
-
if (totalStacksScrubbed === 0 && totalStacksWithUnscrubbableKeys === 0 && totalStacksWithUnverifiableReads === 0 && totalStacksWithUnverifiableLeaves === 0 && totalIndexEntriesConverged === 0 && indexUnwritten.length === 0 && indexUnreadable.length === 0 && malformedRecords.length === 0 && malformedOutputRecords.length === 0) {
|
|
69496
|
+
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) {
|
|
69412
69497
|
if (failures.length === 0) {
|
|
69413
69498
|
logger.info("\nNo plaintext secrets found in any target stack state. Nothing to scrub.");
|
|
69414
69499
|
return;
|
|
@@ -69432,7 +69517,7 @@ async function scrubCommand(stacks, options) {
|
|
|
69432
69517
|
else logger.info(`\nPlan: no state record can be rewritten.${keyNote}${unverifiableNote}${leafNote}${indexNote}${failureNote} ROTATE any exposed secret.`);
|
|
69433
69518
|
if (failures.length > 0) throw scrubStacksFailedError(failures);
|
|
69434
69519
|
if (indexUnwritten.length > 0 || indexUnreadable.length > 0) throw exportIndexIncompleteError(indexUnwritten, indexUnreadable, true);
|
|
69435
|
-
if (malformedRecords.length > 0 || malformedOutputRecords.length > 0) throw malformedRecordsAuditedError(malformedRecords, malformedOutputRecords);
|
|
69520
|
+
if (malformedRecords.length > 0 || malformedOutputRecords.length > 0 || malformedOrphanRecords.length > 0) throw malformedRecordsAuditedError(malformedRecords, malformedOutputRecords, malformedOrphanRecords);
|
|
69436
69521
|
if (damagedProducerStacks.length > 0) throw damagedProducerRecordsError(damagedProducerStacks);
|
|
69437
69522
|
if (options.fail) throw new ScrubNeededError();
|
|
69438
69523
|
return;
|
|
@@ -69441,7 +69526,7 @@ async function scrubCommand(stacks, options) {
|
|
|
69441
69526
|
else logger.info(`\nNo state record was rewritten.${keyNote}${unverifiableNote}${leafNote}${indexNote}${failureNote} ROTATE any exposed secret.`);
|
|
69442
69527
|
if (failures.length > 0) throw scrubStacksFailedError(failures);
|
|
69443
69528
|
if (indexUnwritten.length > 0 || indexUnreadable.length > 0) throw exportIndexIncompleteError(indexUnwritten, indexUnreadable, false);
|
|
69444
|
-
if (malformedRecords.length > 0 || malformedOutputRecords.length > 0) throw malformedRecordsAuditedError(malformedRecords, malformedOutputRecords);
|
|
69529
|
+
if (malformedRecords.length > 0 || malformedOutputRecords.length > 0 || malformedOrphanRecords.length > 0) throw malformedRecordsAuditedError(malformedRecords, malformedOutputRecords, malformedOrphanRecords);
|
|
69445
69530
|
if (damagedProducerStacks.length > 0) throw damagedProducerRecordsError(damagedProducerStacks);
|
|
69446
69531
|
if (options.fail && (totalStacksWithUnscrubbableKeys > 0 || totalStacksWithUnverifiableReads > 0 || totalStacksWithUnverifiableLeaves > 0)) throw new ScrubNeededError();
|
|
69447
69532
|
}
|
|
@@ -70063,11 +70148,12 @@ function damagedProducerRecordsError(stackNames) {
|
|
|
70063
70148
|
const names = stackNames.map((n) => displayIdent(n)).join(", ");
|
|
70064
70149
|
return new ScrubRefusalError(`${stackNames.length} stack(s) import a value from a PRODUCER whose state record has no readable 'outputs' map, so this run could not tell whether that producer still holds the plaintext: ${names}. Those stacks were scrubbed for everything else and are NOT reported clean. Repair the producer record and scrub it first, then re-run. See the warnings above for which producer.`, "SCRUB_PRODUCER_RECORD_UNREADABLE");
|
|
70065
70150
|
}
|
|
70066
|
-
function malformedRecordsAuditedError(stackNames, outputStackNames) {
|
|
70151
|
+
function malformedRecordsAuditedError(stackNames, outputStackNames, orphanStackNames) {
|
|
70067
70152
|
const safeNames = (names) => names.map((n) => displayIdent(n)).join(", ");
|
|
70068
70153
|
const parts = [];
|
|
70069
70154
|
if (stackNames.length > 0) parts.push(`${stackNames.length} stack(s) were audited with an EMPTY resource set because their state record has no readable 'resources' map: ${safeNames(stackNames)}. The report above describes their outputs only — nothing is known about their resources, so this run cannot certify them clean.`);
|
|
70070
70155
|
if (outputStackNames.length > 0) parts.push(`${outputStackNames.length} stack(s) were audited with an EMPTY outputs bag because their state record has no readable 'outputs' map: ${safeNames(outputStackNames)}. The report above describes their resources only — nothing is known about the values their outputs hold, and those values are what the exports index republishes to consumer stacks, so this run cannot certify them clean.`);
|
|
70156
|
+
if (orphanStackNames.length > 0) parts.push(`${orphanStackNames.length} stack(s) were audited with an EMPTY orphan list because their state record has no readable 'orphans' list: ${safeNames(orphanStackNames)}. Nothing is known about resources an earlier failed deploy may have left live in AWS for them, so this run cannot certify them clean.`);
|
|
70071
70157
|
return new ScrubRefusalError(`${parts.join(" ")} See the warnings above for the record to inspect.`, STATE_RESOURCES_MALFORMED);
|
|
70072
70158
|
}
|
|
70073
70159
|
/**
|
|
@@ -71560,6 +71646,13 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
71560
71646
|
logger.warn(malformedOutputsWarning(stack.stackName, region));
|
|
71561
71647
|
}
|
|
71562
71648
|
} else if (!hasReadableOutputs(state)) throw new ScrubRefusalError(malformedOutputsRefusalMessage(stack.stackName, region), STATE_RESOURCES_MALFORMED);
|
|
71649
|
+
let malformedOrphans;
|
|
71650
|
+
if (opts.dryRun) {
|
|
71651
|
+
if (repairMalformedOrphansForReadOnly(state)) {
|
|
71652
|
+
malformedOrphans = true;
|
|
71653
|
+
logger.warn(malformedOrphansWarning(stack.stackName, region));
|
|
71654
|
+
}
|
|
71655
|
+
} else if (!hasReadableOrphans(state)) throw new ScrubRefusalError(malformedOrphansRefusalMessage(stack.stackName, region), STATE_RESOURCES_MALFORMED);
|
|
71563
71656
|
const perResourceTemplateProps = /* @__PURE__ */ new Map();
|
|
71564
71657
|
const outputsTemplateSource = {};
|
|
71565
71658
|
const resolvers = new ScrubResolvers(region);
|
|
@@ -71776,6 +71869,7 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
71776
71869
|
unverifiableLeaves,
|
|
71777
71870
|
...malformedResources ? { malformedResources } : {},
|
|
71778
71871
|
...malformedOutputs ? { malformedOutputs } : {},
|
|
71872
|
+
...malformedOrphans ? { malformedOrphans } : {},
|
|
71779
71873
|
outputs: state.outputs,
|
|
71780
71874
|
exportNameDisplay: (name) => secretSafeKeyDisplay(name, outputSecrets)
|
|
71781
71875
|
};
|
|
@@ -71854,6 +71948,7 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
71854
71948
|
unverifiableLeaves,
|
|
71855
71949
|
...malformedResources ? { malformedResources } : {},
|
|
71856
71950
|
...malformedOutputs ? { malformedOutputs } : {},
|
|
71951
|
+
...malformedOrphans ? { malformedOrphans } : {},
|
|
71857
71952
|
outputs: newOutputs,
|
|
71858
71953
|
exportNameDisplay: (name) => secretSafeKeyDisplay(name, outputSecrets)
|
|
71859
71954
|
};
|
|
@@ -71879,87 +71974,6 @@ function createScrubCommand() {
|
|
|
71879
71974
|
return cmd;
|
|
71880
71975
|
}
|
|
71881
71976
|
|
|
71882
|
-
//#endregion
|
|
71883
|
-
//#region src/utils/own-keys.ts
|
|
71884
|
-
/**
|
|
71885
|
-
* Own-key helpers for the bags that reach cdkd through `JSON.parse` — a
|
|
71886
|
-
* `state.json` record, a Cloud Control `Properties` document, a template — and
|
|
71887
|
-
* for the raw SDK readbacks compared against them.
|
|
71888
|
-
*
|
|
71889
|
-
* `JSON.parse` yields a key literally named `__proto__` as an ORDINARY own
|
|
71890
|
-
* data property, and every comparator / rebuild walk over such a bag has to
|
|
71891
|
-
* keep treating it as one. Two idioms silently do not:
|
|
71892
|
-
*
|
|
71893
|
-
* - **Rebuilding onto a `{}` literal.** `out[k] = v` with `k === '__proto__'`
|
|
71894
|
-
* runs `Object.prototype`'s accessor, SETS the node's prototype and DROPS
|
|
71895
|
-
* the key — on BOTH comparison sides when the walk is a canonicalizer, so a
|
|
71896
|
-
* drift at that key is invisible (issue
|
|
71897
|
-
* [#3121](https://github.com/go-to-k/cdkd/issues/3121)), and on the WRITE
|
|
71898
|
-
* path the member vanishes from the payload (issue
|
|
71899
|
-
* [#2899](https://github.com/go-to-k/cdkd/issues/2899)). Rebuild onto
|
|
71900
|
-
* {@link nullPrototypeRecord} (no accessor there, so plain assignment
|
|
71901
|
-
* defines an own key) or, onto an existing plain object, define the key
|
|
71902
|
-
* with {@link defineOwnKey}.
|
|
71903
|
-
* - **`key in bag` membership.** `in` reads the prototype chain, so a key
|
|
71904
|
-
* named `constructor` / `toString` answers `true` for every plain object
|
|
71905
|
-
* and the recursion then walks `Object`'s function. {@link hasOwnKey} asks
|
|
71906
|
-
* the bag alone; {@link ownValue} is the matching read.
|
|
71907
|
-
*
|
|
71908
|
-
* And ONE shape test every such walk needs FIRST: {@link hasPlainPrototype}.
|
|
71909
|
-
* A non-plain object (`Date`, `Uint8Array`, `Map`, a class instance) has no
|
|
71910
|
-
* own enumerable keys, so a key-walk over one FABRICATES `{}` (or an index
|
|
71911
|
-
* map) and any two of them compare equal. Such a value is returned by
|
|
71912
|
-
* IDENTITY and compared as itself.
|
|
71913
|
-
*
|
|
71914
|
-
* Extracted from `src/cli/commands/drift.ts` (issue #2899, swept by PR #3124)
|
|
71915
|
-
* so the analyzer-side canonicalizers (#3121) share ONE spelling rather than a
|
|
71916
|
-
* fourth copy. A LEAF module, deliberately, and it must stay one: a value
|
|
71917
|
-
* import from a module other suites `vi.mock` wholesale reds those suites
|
|
71918
|
-
* with a missing-export failure (which is why `secret-redaction.ts` keeps its
|
|
71919
|
-
* own `hasPlainPrototype` — several drift suites mock that module).
|
|
71920
|
-
*/
|
|
71921
|
-
/** Own-key membership: `in` reads the prototype chain, which a `JSON.parse`d bag never means. */
|
|
71922
|
-
function hasOwnKey(target, key) {
|
|
71923
|
-
return Object.prototype.hasOwnProperty.call(target, key);
|
|
71924
|
-
}
|
|
71925
|
-
/** An own-key read: `undefined` for an inherited name (`__proto__`, `constructor`, ...). */
|
|
71926
|
-
function ownValue(target, key) {
|
|
71927
|
-
return hasOwnKey(target, key) ? target[key] : void 0;
|
|
71928
|
-
}
|
|
71929
|
-
/** An ordinary (writable, enumerable, configurable) own data property — never the prototype. */
|
|
71930
|
-
function defineOwnKey(target, key, value) {
|
|
71931
|
-
Object.defineProperty(target, key, {
|
|
71932
|
-
value,
|
|
71933
|
-
writable: true,
|
|
71934
|
-
enumerable: true,
|
|
71935
|
-
configurable: true
|
|
71936
|
-
});
|
|
71937
|
-
}
|
|
71938
|
-
/**
|
|
71939
|
-
* Does this value carry an ORDINARY object prototype?
|
|
71940
|
-
*
|
|
71941
|
-
* `typeof v === 'object'` admits `Date` / `Map` / `Set` / `Uint8Array` / class
|
|
71942
|
-
* instances, whose own enumerable keys are `[]` — so a key-walk over one
|
|
71943
|
-
* reports "no contradiction" between two values that actually differ, and a
|
|
71944
|
-
* rebuild over one fabricates `{}`. A NULL prototype counts as plain: it is
|
|
71945
|
-
* what {@link nullPrototypeRecord} yields, and a walk must be able to re-walk
|
|
71946
|
-
* its own output.
|
|
71947
|
-
*/
|
|
71948
|
-
function hasPlainPrototype(value) {
|
|
71949
|
-
const proto = Object.getPrototypeOf(value);
|
|
71950
|
-
return proto === Object.prototype || proto === null;
|
|
71951
|
-
}
|
|
71952
|
-
/**
|
|
71953
|
-
* A fresh rebuild target with NO prototype, so `out['__proto__'] = v` defines
|
|
71954
|
-
* an own key instead of setting the prototype. `JSON.stringify`,
|
|
71955
|
-
* `Object.keys` / `entries` and `structuredClone` all read it like a plain
|
|
71956
|
-
* object; only `instanceof Object` and a direct `.hasOwnProperty()` method call
|
|
71957
|
-
* do not, and no consumer on the drift path uses either.
|
|
71958
|
-
*/
|
|
71959
|
-
function nullPrototypeRecord() {
|
|
71960
|
-
return Object.create(null);
|
|
71961
|
-
}
|
|
71962
|
-
|
|
71963
71977
|
//#endregion
|
|
71964
71978
|
//#region src/analyzer/drift-normalize.ts
|
|
71965
71979
|
/**
|
|
@@ -78153,7 +78167,7 @@ async function exportCommand(stackArg, options) {
|
|
|
78153
78167
|
let synthedRegion;
|
|
78154
78168
|
let templateFormat = "json";
|
|
78155
78169
|
let allSynthStacks = [];
|
|
78156
|
-
let rootNestedTemplatePaths =
|
|
78170
|
+
let rootNestedTemplatePaths = nullPrototypeRecord();
|
|
78157
78171
|
if (options.template) {
|
|
78158
78172
|
if (!stackArg) throw new Error("--template requires a stack name as a positional argument to identify the cdkd state record.");
|
|
78159
78173
|
const parsed = parseTemplateFile(options.template);
|
|
@@ -78182,7 +78196,7 @@ async function exportCommand(stackArg, options) {
|
|
|
78182
78196
|
template = stackInfo.template;
|
|
78183
78197
|
resolvedStackName = stackInfo.stackName;
|
|
78184
78198
|
synthedRegion = stackInfo.region;
|
|
78185
|
-
rootNestedTemplatePaths = stackInfo.nestedTemplates ??
|
|
78199
|
+
rootNestedTemplatePaths = stackInfo.nestedTemplates ?? nullPrototypeRecord();
|
|
78186
78200
|
allSynthStacks = result.stacks.map((s) => ({
|
|
78187
78201
|
stackName: s.stackName,
|
|
78188
78202
|
template: s.template
|
|
@@ -78767,7 +78781,7 @@ function readNestedChildTemplateFile(templatePath, childLogicalId) {
|
|
|
78767
78781
|
* for unit testing.
|
|
78768
78782
|
*/
|
|
78769
78783
|
function indexNestedTemplatePaths(template, templateDir) {
|
|
78770
|
-
const result =
|
|
78784
|
+
const result = nullPrototypeRecord();
|
|
78771
78785
|
const resources = template["Resources"];
|
|
78772
78786
|
if (!resources || typeof resources !== "object" || Array.isArray(resources)) return result;
|
|
78773
78787
|
for (const [logicalId, resource] of Object.entries(resources)) {
|
|
@@ -83035,6 +83049,7 @@ async function rollbackCommand(stackArg, options) {
|
|
|
83035
83049
|
if (!stateData) throw new Error(`Rollback journal exists for '${safeStack(stackName)}' (${safe(region)}) but its state.json is missing (keys: ${safe(setup.prefix)}/${safeStack(stackName)}/${safe(region)}/state.json and .../rollback-journal.json). State appears corrupted — inspect the bucket manually.`);
|
|
83036
83050
|
const baseState = stateData.state;
|
|
83037
83051
|
refuseMalformedState(baseState, stackName, region);
|
|
83052
|
+
refuseMalformedOrphans(baseState, stackName, region);
|
|
83038
83053
|
const stateResources = { ...baseState.resources };
|
|
83039
83054
|
const mintedOrphans = [];
|
|
83040
83055
|
const orphanLogicalIds = new Set(options.orphan ?? []);
|
|
@@ -85740,15 +85755,17 @@ async function publishAssetsCommand(stacks, options) {
|
|
|
85740
85755
|
...options.profile && { profile: options.profile },
|
|
85741
85756
|
...Object.keys(context).length > 0 && { context }
|
|
85742
85757
|
};
|
|
85743
|
-
const
|
|
85758
|
+
const result = await synthesizer.synthesize(synthOptions);
|
|
85759
|
+
const { stacks: allStacks } = result;
|
|
85744
85760
|
logger.debug(`Found ${allStacks.length} stack(s) in assembly`);
|
|
85745
85761
|
const stackPatterns = stacks.length > 0 ? stacks : options.stack ? [options.stack] : [];
|
|
85746
85762
|
let targetStacks;
|
|
85763
|
+
if (allStacks.length === 0) throw new Error(renderNoStackMatch(stackPatterns, allStacks, result));
|
|
85747
85764
|
if (options.all) targetStacks = allStacks;
|
|
85748
85765
|
else if (stackPatterns.length > 0) targetStacks = matchStacks(allStacks, stackPatterns);
|
|
85749
85766
|
else if (allStacks.length === 1) targetStacks = allStacks;
|
|
85750
85767
|
else throw new Error(`Multiple stacks found: ${allStacks.map(describeStack).join(", ")}. Specify stack name(s) or use --all`);
|
|
85751
|
-
if (targetStacks.length === 0) throw new Error(stackPatterns
|
|
85768
|
+
if (targetStacks.length === 0) throw new Error(renderNoStackMatch(stackPatterns, allStacks, result));
|
|
85752
85769
|
const baseRegion = namedCliRegion(options.region) ?? "us-east-1";
|
|
85753
85770
|
const { STSClient, GetCallerIdentityCommand } = await import("@aws-sdk/client-sts");
|
|
85754
85771
|
const stsClient = new STSClient({
|
|
@@ -86250,7 +86267,7 @@ async function importCommand(stackArg, options) {
|
|
|
86250
86267
|
overrides
|
|
86251
86268
|
});
|
|
86252
86269
|
logger.info(`Resolved ${mergeStats.derived} physical ID(s) from CloudFormation` + formatCfnOverrideMergeDetail(mergeStats));
|
|
86253
|
-
validateNestedStackShape(template, migrationTree, stackInfo.stackName, stackInfo.nestedTemplates ??
|
|
86270
|
+
validateNestedStackShape(template, migrationTree, stackInfo.stackName, stackInfo.nestedTemplates ?? nullPrototypeRecord());
|
|
86254
86271
|
}
|
|
86255
86272
|
let accountIdForNestedSynth;
|
|
86256
86273
|
if (migrationTree && migrationTree.nested.size > 0) {
|
|
@@ -86278,6 +86295,7 @@ async function importCommand(stackArg, options) {
|
|
|
86278
86295
|
const existingState = existingResult?.state ?? null;
|
|
86279
86296
|
if (existingState) refuseMalformedState(existingState, stackInfo.stackName, targetRegion);
|
|
86280
86297
|
if (existingState) refuseMalformedOutputs(existingState, stackInfo.stackName, targetRegion);
|
|
86298
|
+
if (existingState) refuseMalformedOrphans(existingState, stackInfo.stackName, targetRegion);
|
|
86281
86299
|
const existingEtag = existingResult?.etag;
|
|
86282
86300
|
const migrationPending = existingResult?.migrationPending ?? false;
|
|
86283
86301
|
if (existingState) {
|
|
@@ -86368,7 +86386,7 @@ async function importCommand(stackArg, options) {
|
|
|
86368
86386
|
lockRecovery,
|
|
86369
86387
|
parentStackName: stackInfo.stackName,
|
|
86370
86388
|
parentRegion: targetRegion,
|
|
86371
|
-
parentNestedTemplates: stackInfo.nestedTemplates ??
|
|
86389
|
+
parentNestedTemplates: stackInfo.nestedTemplates ?? nullPrototypeRecord(),
|
|
86372
86390
|
parentTree: migrationTree,
|
|
86373
86391
|
stateBackend,
|
|
86374
86392
|
lockManager,
|
|
@@ -87654,7 +87672,7 @@ function readNestedChildTemplate(templatePath, childLogicalId) {
|
|
|
87654
87672
|
*/
|
|
87655
87673
|
function indexGrandchildTemplatePaths(childTemplate, childTemplatePath) {
|
|
87656
87674
|
const dir = path.dirname(childTemplatePath);
|
|
87657
|
-
const result =
|
|
87675
|
+
const result = nullPrototypeRecord();
|
|
87658
87676
|
for (const [grandLogicalId, resource] of Object.entries(childTemplate.Resources)) {
|
|
87659
87677
|
if (resource.Type !== "AWS::CloudFormation::Stack") continue;
|
|
87660
87678
|
const assetPath = resource.Metadata?.["aws:asset:path"];
|
|
@@ -97343,4 +97361,4 @@ function buildProgram() {
|
|
|
97343
97361
|
|
|
97344
97362
|
//#endregion
|
|
97345
97363
|
export { buildProgram };
|
|
97346
|
-
//# sourceMappingURL=program-
|
|
97364
|
+
//# sourceMappingURL=program-BDy35kIL.js.map
|