@go-to-k/cdkd 0.291.17 → 0.291.18
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-CHM7_WdJ.js → asg-provider-DR5gOGbi.js} +3 -3
- package/dist/{asg-provider-CHM7_WdJ.js.map → asg-provider-DR5gOGbi.js.map} +1 -1
- package/dist/cli.js +2 -2
- package/dist/{deploy-engine-xxVOQPPr.js → deploy-engine-BwDlgFRs.js} +578 -135
- package/dist/deploy-engine-BwDlgFRs.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/{logger-GASr9bAF.js → logger-Bt0RGDfb.js} +12 -2
- package/dist/logger-Bt0RGDfb.js.map +1 -0
- package/dist/{program-hXXls0hg.js → program-DxyHPT8E.js} +586 -337
- package/dist/{program-hXXls0hg.js.map → program-DxyHPT8E.js.map} +1 -1
- package/dist/{version-DMRkEtU2.js → version-CJkb2usU.js} +2 -2
- package/dist/{version-DMRkEtU2.js.map → version-CJkb2usU.js.map} +1 -1
- package/package.json +2 -2
- package/dist/deploy-engine-xxVOQPPr.js.map +0 -1
- package/dist/logger-GASr9bAF.js.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { $ as yellow, $i as findLargeInlineResources, $n as repairMalformedOutputsForReadOnly, $r as WorkGraph, $t as replayWarn, A as createPreDeleteFinalSnapshot, Aa as setAwsClients, Ai as runDockerStreaming, An as malformedOrphansRefusalMessage, Ar as scrubResourceRecord, At as isTerminationProtectionPropagationError, B as isStatefulRecreateTargetSync, Ba as LocalStartServiceError, Bi as resolveApp, Bn as refuseMalformedNestedChildOutputs, Br as DEFAULT_STATE_PREFIX, Bt as parameterTypeMayLoseSecretIdentity, C as namesAnyDeclaredParameter, Ca as resolveAssemblyPath, Ci as formatDockerLoginError, Cn as hasReadableOutputs, Cr as maskSecretsInError, Ct as CloudControlProvider, D as PRE_DELETE_SNAPSHOT_TYPES, Da as getAwsClients, Di as partitionSensitiveEnv, Dn as malformedExportSourceWarning, Dr as recordMaskOnlyValuesIn, Dt as deleteSkipReason, E as ATOMIC_FINAL_SNAPSHOT_TYPES, Ea as AwsClients, Ei as isMalformedEnvKey, En as malformedExportNamesWarning, Er as recordMaskOnlyValue, Et as deleteIndeterminateGuards, F as extractDeploymentEventError, Fi as getDockerImageBySourceHash, Fn as malformedResourceEntriesWarning, Fr as buildForceUnlockCommand, Ft as coerceParameterTypedValue, G as toCfnInteger, Ga as ProvisioningError, Gi as resolveStateBucketWithDefaultAndSource, Gn as refuseMalformedOutputsForDestroy, Gr as importableOutputKeys, Gt as resolveExplicitPhysicalId, H as WARM_THROUGHPUT_MEMBERS, Ha as MalformedProducerRecordRefusalError, Hi as resolveCaptureObservedState, Hn as refuseMalformedOrphansForDestroy, Hr as hasReadableExportSet, Ht as isSettledInstanceState, I as makeSiblingClaimReader, Ia as DeployCancelledError, Ii as Synthesizer, In as malformedResourcePropertiesWarning, Ir as buildLockContentionMessage, It as getAccountInfo, J as bold, Ja as StackHasActiveImportsError, Ji as warnDeprecatedNoPrefixCliFlag, Jn as refuseMalformedResourceEntriesForOrphan, Jr as orphansAfterRollback, Jt as coerceCfnInteger, K as toFiniteNumber, Ka as ResourceTimeoutError, Ki as resolveUseCdkBootstrapAssets, Kn as refuseMalformedResourceAttributesForOrphan, Kr as importableOutputs, Kt as assertRegionMatch, L as planOrphanAdoption, La as DynamicReferenceRegionAmbiguousError, Li as synthesisStatusMessage, Ln as malformedResourcesWarning, Lr as forceQuitRecoveryClause, Lt as isImpossibleEmptyStoredAttribute, M as refusesFinalSnapshot, Ma as CdkdError, Mi as escapeRegExp, Mn as malformedOutputsRefusalMessage, Mr as S3StateBackend, Mt as carriesDynamicReference, N as unsupportedFinalSnapshotError, Ni as stripControlChars, Nn as malformedOutputsWarning, Nr as rebuildClientForBucketRegion, Nt as carriesFetchableDynamicReference, O as buildFinalSnapshotIdentifier, Oa as resetAwsClients, Oi as redactDockerArgvValues, On as malformedLocalOutputsWarning, Or as recoverMaskedOutput, Ot as isWaitAbandonedError, P as makeCanonicalizePropertiesFn, Pa as CrossAccountSecretRefusalError, Pi as AssetManifestLoader, Pn as malformedRenderedContainersWarning, Pr as UNREPRODUCIBLE_LOCK_CLAUSE, Pt as cfnRefValueFromPhysicalId, Q as red, Qi as MIGRATE_TMP_PREFIX, Qn as repairMalformedOrphansForReadOnly, Qr as stringifyValue, Qt as readConfigString, R as MULTI_REGION_RECREATE_BLOCKED_TYPES, Ra as IntrinsicResolutionRefusalError, Ri as getDefaultStateBucketName, Rn as malformedStateRefusalMessage, Rr as formatLockExpiry, Rt as isNamelessDynamicReferenceError, S as computeParameterTaint, Sa as renderAssemblyPathEscape, Si as finchSecretArgvRefusal, Sn as hasReadableOrphans, Sr as markSameGenerationBag, St as startInterruptWatch, T as resourcesNamingDeclaredParameter, Ta as resolveBucketRegion, Ti as isDockerClientEnvKey, Tn as isReadableResourceEntry, Tr as pathCrossesDottedKey, Tt as UNSPECIFIED_SKIP_REASON, U as coerceWarmThroughput$1, Ua as NestedStackChildDirectDestroyError, Ui as resolveSkipPrefix, Un as refuseMalformedOrphansForOrphan, Ur as hasReasonlessBaselineRefusal, Ut as WAFv2WebACLProvider, V as renderStatefulReason, Vi as resolveAutoAssetStorage, Vn as refuseMalformedOrphans, Vr as exportNamesCarriedFrom, Vt as refStateLookupFromResource, W as isWarmThroughputDecrease, Wa as PartialFailureError, Wi as resolveStateBucketWithDefault, Wn as refuseMalformedOutputs, Wr as hasUnverifiableParameterRefusal, Wt as normalizeAwsTagsToCfn, X as gray, Xi as CFN_TEMPLATE_BODY_LIMIT, Xn as refuseMalformedResourcesForDestroy, Xr as shouldRetainResource, Xt as configIntegerRefusal, Y as cyan, Ya as StackTerminationProtectionError, Yi as ssmResolvedValueType, Yn as refuseMalformedResourcePropertiesForOrphan, Yr as orphansCarriedFrom, Yt as configBooleanRefusal, Z as green, Za as SynthesisError, Zi as CFN_TEMPLATE_URL_LIMIT, Zn as refuseMalformedState, Zr as AssetPublisher, Zt as configStringRefusal, _ as bagHoldsSecretExpression, _a as hasPlainPrototype, _i as resolveDockerContextDirectory, _n as INTRINSIC_KEYS, _r as dynamicReferenceTokens, _t as maskerOrIdentity, a as DeploymentEventsStore, aa as producerRecordKey, ai as BOOTSTRAP_MARKER_PREFIX, an as withSharedDrainBudget, ao as isRetryableTransientError, ar as findActionableSilentDrops, at as secretBearingStateKeyWarning, b as mergeNoChangeOutputs, ba as absoluteAssemblyPathEscape, bi as describeDockerFailure, bn as UNREADABLE_RESOURCES_MAP_ROW, br as isSingleDynamicReferenceToken, bt as interruptWatchListenerCount, c as replayFailedOperations, ca as PARTITION_TABLE, ci as getBootstrapMarkerKey, cn as s3BucketDualStackDomainName, co as markNonRetryable, cr as withRetry, ct as IAMRoleProvider, d as updatePartialMessage, da as AssemblyReader, di as readBootstrapMarkerBody, dn as applyRoleArnIfSet, do as describeAwsFailure, dr as STATE_SOURCED_BASELINE_RULES, dt as definedAttributes, ea as uploadCfnTemplate, ei as buildAssetRedirectMap, en as requireConfigArray, eo as normalizeAwsError, er as repairMalformedResourceEntriesForReadOnly, et as collectDeclaredOutputNames, f as updatePartialReason, fa as failedStageNote, fi as validateAssetBucketName, fn as AWS_CREDENTIAL_ENV_KEYS, fo as safeStringify, fr as STATE_SOURCED_CROSS_GENERATION_RULES, ft as stringifyIfAssigned, g as computeImplicitDeleteEdges, ga as hasOwnKey, gi as buildDockerImage, gn as DiffCalculator, gr as createSecretMasker, gt as maskDeep, h as IMPLICIT_DELETE_DEPENDENCIES, ha as defineOwnKey, hi as assertCdkLocalDockerContextContained, hn as envCredentialsAreAssumedRole, hr as carriesSecretMask, ht as createMaskedRetryLogger, i as DeploymentEventsReader, ia as producerCoordinateKey, ii as AssetModeResolver, in as producerRegionsFromState, io as isMarkedNonRetryable, ir as safeStackName, it as secretBearing, j as isFinalSnapshotError, ji as warnFinchArgvExposure, jn as malformedOrphansWarning, jr as LockManager, jt as IntrinsicFunctionResolver, k as ccRoutedFinalSnapshotError, ka as runWithStackAwsClients, ki as runDockerForeground, kn as malformedOrphanRecordsWarning, kr as redactSecretsForState, kt as disableInstanceApiTermination, l as replayRollback, la as canonicalizeRegion, li as isCrossRegionRedirect, ln as s3BucketRegionalDomainName, lo as markRedactedCause, lr as DagBuilder, lt as collectInlinePolicyNamesManagedBySiblings, m as maskingRetryLogger, ma as processStackMessages, mi as buildDenyExternalAccessPolicy, mn as callerEnvCredentials, mr as TEMPLATE_SOURCED_RULES, mt as wouldReturnToSdkProvider, n as DEFAULT_RESOURCE_WARN_AFTER_MS, na as injectiveKey, ni as loadPublishableAssetManifest, nn as requireConfigString, no as pasteableCommand, nr as repairMalformedResourcesForReadOnly, nt as exportAliasCollisionScrubWarning, o as planFailedOps, oa as decodeListingKey, oi as assertAssetBucketRegion, on as s3BucketArn, oo as isThrottlingError, or as findSilentDropProperties, ot as secretSafeKeyDisplay, p as withResourceDeadline, pa as globMatches, pi as validateContainerRepoName, pn as applyCallerIdentityCredentials, pr as STATE_SOURCED_READBACK_RULES, pt as ProviderRegistry, q as formatResourceLine, qa as ResourceUpdateNotSupportedError, qi as stateBucketExistenceConfirmed, qn as refuseMalformedResourceEntries, qr as isReadableBag, qt as coerceCfnBoolean, r as DeployEngine, ra as injectiveKeyPrefix, ri as rewriteTemplateAssetReferences, rn as classifyReplaySecretRegion, ro as shellQuote, rr as safeRegion, rt as isExportAliasCollision, s as planRollback, sa as expectedOwnerParam, si as ensureAssetStorage, sn as s3BucketDomainName, so as isTransientServerError, sr as describeTypeWithThrottleRetry, st as getCurrentResourceSecrets, t as DEFAULT_RESOURCE_TIMEOUT_MS, ta as CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION, ti as createAssetRedirectResolver, tn as requireConfigObject, to as withErrorHandling, tr as repairMalformedResourcePropertiesForReadOnly, tt as collectPublishedOutputNames, u as resolveReplacementOldType, ua as derivePartitionAndUrlSuffix, ui as parseBootstrapMarker, un as s3BucketWebsiteUrl, uo as retryClassificationText, ur as TemplateParser, ut as clearOnUpdateRemoval, v as isSecretBearingReferenceString, va as nullPrototypeRecord, vi as describeDockerCapturedOutput, vn as STATE_RESOURCES_MALFORMED, vr as errorCauseChain, vt as beginCommandInterruptScope, w as reachableDivergentParameters, wi as getDockerCmd, wn as hasReadableResources, wr as maskSecretsInText, wt as slowCcOperationTimeoutMs, x as bindingSkippedOutputs, xa as displayAssemblyPath, xi as dockerSpawnEnvWithSensitive, xn as displayLogicalId, xr as isUncertifiedBaselineMaskPosition, xt as isInterruptedWaitError, y as keptWholeReasonText, ya as ownValue, yi as describeDockerExecFailure, yn as UNREADABLE_ORPHANS_CONTAINER_ROW, yr as identityKeyFor, yt as endCommandInterruptScope, z as isStatefulRecreateTargetForReplace, za as LocalInvokeBuildError$1, zi as getLegacyStateBucketName, zn as refuseDivergentRecordRegionForDestroy, zr as CUSTOM_RESOURCE_RESPONSE_PREFIX, zt as isUnboundTemplateParameter } from "./deploy-engine-xxVOQPPr.js";
|
|
2
|
-
import { C as displayAwsMessage, D as
|
|
1
|
+
import { $ as yellow, $a as NestedStackChildDirectDestroyError, $i as resolveSkipPrefix, $n as refuseMalformedOutputsForDestroy, $r as hasReadableExportSet, $t as readConfigString, A as createPreDeleteFinalSnapshot, Aa as absoluteAssemblyPathEscape, Ai as describeDockerFailure, An as malformedExportSourceWarning, Ar as identityKeyFor, At as disableInstanceApiTermination, B as isStatefulRecreateTargetSync, Ba as setAwsClients, Bi as runDockerStreaming, Bn as malformedResourceEntriesWarning, Br as redactSecretsForState, Bt as isUnboundTemplateParameter, C as namesAnyDeclaredParameter, Ca as globMatches, Ci as validateAssetBucketName, Cn as displayLogicalId, Cr as STATE_SOURCED_CROSS_GENERATION_RULES, Ct as CloudControlProvider, D as PRE_DELETE_SNAPSHOT_TYPES, Da as hasPlainPrototype, Di as resolveDockerContextDirectory, Dn as isReadableOrphanRecord, Dr as createSecretMasker, Dt as deleteIndeterminateGuards, E as ATOMIC_FINAL_SNAPSHOT_TYPES, Ea as hasOwnKey, Ei as buildDockerImage, En as hasReadableResources, Er as carriesSecretMask, Et as UNSPECIFIED_SKIP_REASON, F as extractDeploymentEventError, Fa as resolveBucketRegion, Fi as isDockerClientEnvKey, Fn as malformedOrphansRefusalMessage, Fr as maskSecretsInText, Ft as cfnRefValueFromPhysicalId, G as toCfnInteger, Gi as getDockerImageBySourceHash, Gn as refuseDivergentRecordRegionForDestroy, Gr as UNREPRODUCIBLE_LOCK_CLAUSE, Gt as normalizeAwsTagsToCfn, H as WARM_THROUGHPUT_MEMBERS, Ha as CdkdError, Hi as escapeRegExp, Hn as malformedResourcesWarning, Hr as LockManager, Ht as refStateLookupFromResource, I as makeSiblingClaimReader, Ia as AwsClients, Ii as isMalformedEnvKey, In as malformedOrphansWarning, Ir as pathCrossesDottedKey, It as coerceParameterTypedValue, J as bold, Ja as IntrinsicResolutionRefusalError, Ji as getDefaultStateBucketName, Jn as refuseMalformedOrphanRecordsForDestroy, Jr as forceQuitRecoveryClause, Jt as coerceCfnBoolean, K as toFiniteNumber, Ka as DeployCancelledError, Ki as Synthesizer, Kn as refuseMalformedNestedChildOutputs, Kr as buildForceUnlockCommand, Kt as resolveExplicitPhysicalId, L as planOrphanAdoption, La as getAwsClients, Li as partitionSensitiveEnv, Ln as malformedOutputsRefusalMessage, Lr as recordMaskOnlyValue, Lt as getAccountInfo, M as refusesFinalSnapshot, Ma as renderAssemblyPathEscape, Mi as finchSecretArgvRefusal, Mn as malformedOrphanRecordsRefusalMessage, Mr as isUncertifiedBaselineMaskPosition, Mt as IntrinsicFunctionResolver, N as unsupportedFinalSnapshotError, Na as resolveAssemblyPath, Ni as formatDockerLoginError, Nn as malformedOrphanRecordsWarning, Nr as markSameGenerationBag, Nt as carriesDynamicReference, O as buildFinalSnapshotIdentifier, Oa as nullPrototypeRecord, Oi as describeDockerCapturedOutput, On as isReadableResourceEntry, Or as dynamicReferenceTokens, Ot as deleteSkipReason, P as makeCanonicalizePropertiesFn, Pi as getDockerCmd, Pn as malformedOrphanRowsKeptWarning, Pr as maskSecretsInError, Pt as carriesFetchableDynamicReference, Q as red, Qa as MalformedProducerRecordRefusalError, Qi as resolveCaptureObservedState, Qn as refuseMalformedOutputs, Qr as exportNamesCarriedFrom, Qt as configStringRefusal, R as MULTI_REGION_RECREATE_BLOCKED_TYPES, Ra as resetAwsClients, Ri as redactDockerArgvValues, Rn as malformedOutputsWarning, Rr as recordMaskOnlyValuesIn, Rt as isImpossibleEmptyStoredAttribute, S as computeParameterTaint, Sa as failedStageNote, Si as readBootstrapMarkerBody, Sn as deployRefusesOrphanRowsReason, So as safeStringify, Sr as STATE_SOURCED_BASELINE_RULES, St as startInterruptWatch, T as resourcesNamingDeclaredParameter, Ta as defineOwnKey, Ti as buildDenyExternalAccessPolicy, Tn as hasReadableOutputs, Tr as TEMPLATE_SOURCED_RULES, Tt as ccProtectionRegistryTypes, U as coerceWarmThroughput$1, Ui as stripControlChars, Un as malformedStateRefusalMessage, Ur as S3StateBackend, Ut as isSettledInstanceState, V as renderStatefulReason, Vi as warnFinchArgvExposure, Vn as malformedResourcePropertiesWarning, Vr as scrubResourceRecord, Vt as parameterTypeMayLoseSecretIdentity, W as isWarmThroughputDecrease, Wa as CrossAccountSecretRefusalError, Wi as AssetManifestLoader, Wn as previewableOrphanRecords, Wr as rebuildClientForBucketRegion, Wt as WAFv2WebACLProvider, X as gray, Xa as LocalStartServiceError, Xi as resolveApp, Xn as refuseMalformedOrphansForDestroy, Xr as CUSTOM_RESOURCE_RESPONSE_PREFIX, Xt as configBooleanRefusal, Y as cyan, Ya as LocalInvokeBuildError$1, Yi as getLegacyStateBucketName, Yn as refuseMalformedOrphans, Yr as formatLockExpiry, Yt as coerceCfnInteger, Z as green, Zi as resolveAutoAssetStorage, Zn as refuseMalformedOrphansForOrphan, Zr as DEFAULT_STATE_PREFIX, Zt as configIntegerRefusal, _ as bagHoldsSecretExpression, _a as expectedOwnerParam, _i as assertAssetBucketRegion, _n as DiffCalculator, _o as isTransientServerError, _r as findSilentDropProperties, _t as maskerOrIdentity, a as DeploymentEventsStore, aa as ssmResolvedValueType, ai as orphansAfterRollback, an as producerRegionsFromState, ao as StackTerminationProtectionError, ar as refuseMalformedState, at as secretBearingStateKeyWarning, b as mergeNoChangeOutputs, ba as derivePartitionAndUrlSuffix, bi as isCrossRegionRedirect, bn as UNREADABLE_ORPHANS_CONTAINER_ROW, bo as retryClassificationText, br as DagBuilder, bt as interruptWatchListenerCount, c as replayFailedOperations, ca as MIGRATE_TMP_PREFIX, ci as AssetPublisher, cn as s3BucketDomainName, cr as repairMalformedOutputsForReadOnly, ct as IAMRoleProvider, d as updatePartialMessage, da as CUSTOM_RESOURCE_RESPONSE_OBJECT_DESCRIPTION, di as buildAssetRedirectMap, dn as s3BucketWebsiteUrl, do as withErrorHandling, dr as repairMalformedResourcesForReadOnly, dt as definedAttributes, ea as resolveStateBucketWithDefault, ei as hasReasonlessBaselineRefusal, en as replayWarn, eo as PartialFailureError, er as refuseMalformedResourceAttributesForOrphan, et as collectDeclaredOutputNames, f as updatePartialReason, fa as injectiveKey, fi as createAssetRedirectResolver, fn as applyRoleArnIfSet, fo as pasteableCommand, fr as safeRegion, ft as stringifyIfAssigned, g as computeImplicitDeleteEdges, ga as decodeListingKey, gi as BOOTSTRAP_MARKER_PREFIX, gn as envCredentialsAreAssumedRole, go as isThrottlingError, gr as findActionableSilentDrops, gt as maskDeep, h as IMPLICIT_DELETE_DEPENDENCIES, ha as producerRecordKey, hi as AssetModeResolver, hn as callerEnvCredentials, ho as isRetryableTransientError, hr as unreadableOrphanRecords, ht as createMaskedRetryLogger, i as DeploymentEventsReader, ia as warnDeprecatedNoPrefixCliFlag, ii as isReadableBag, in as classifyReplaySecretRegion, io as StackHasActiveImportsError, ir as refuseMalformedResourcesForDestroy, it as secretBearing, j as isFinalSnapshotError, ja as displayAssemblyPath, ji as dockerSpawnEnvWithSensitive, jn as malformedLocalOutputsWarning, jr as isSingleDynamicReferenceToken, jt as isTerminationProtectionPropagationError, k as ccRoutedFinalSnapshotError, ka as ownValue, ki as describeDockerExecFailure, kn as malformedExportNamesWarning, kr as errorCauseChain, kt as isWaitAbandonedError, l as replayRollback, la as findLargeInlineResources, li as stringifyValue, ln as s3BucketDualStackDomainName, lr as repairMalformedResourceEntriesForReadOnly, lt as collectInlinePolicyNamesManagedBySiblings, m as maskingRetryLogger, ma as producerCoordinateKey, mi as rewriteTemplateAssetReferences, mn as applyCallerIdentityCredentials, mo as isMarkedNonRetryable, mr as unpreviewableOrphanRecords, mt as wouldReturnToSdkProvider, n as DEFAULT_RESOURCE_WARN_AFTER_MS, na as resolveUseCdkBootstrapAssets, ni as importableOutputKeys, nn as requireConfigObject, no as ResourceTimeoutError, nr as refuseMalformedResourceEntriesForOrphan, nt as exportAliasCollisionScrubWarning, o as planFailedOps, oa as CFN_TEMPLATE_BODY_LIMIT, oi as orphansCarriedFrom, on as withSharedDrainBudget, or as repairMalformedOrphanRecordsForReadOnly, ot as secretSafeKeyDisplay, p as withResourceDeadline, pa as injectiveKeyPrefix, pi as loadPublishableAssetManifest, pn as AWS_CREDENTIAL_ENV_KEYS, po as shellQuote, pr as safeStackName, pt as ProviderRegistry, q as formatResourceLine, qa as DynamicReferenceRegionAmbiguousError, qi as synthesisStatusMessage, qn as refuseMalformedOrphanRecords, qr as buildLockContentionMessage, qt as assertRegionMatch, r as DeployEngine, ra as stateBucketExistenceConfirmed, ri as importableOutputs, rn as requireConfigString, ro as ResourceUpdateNotSupportedError, rr as refuseMalformedResourcePropertiesForOrphan, rt as isExportAliasCollision, s as planRollback, sa as CFN_TEMPLATE_URL_LIMIT, si as shouldRetainResource, sn as s3BucketArn, so as SynthesisError, sr as repairMalformedOrphansForReadOnly, st as getCurrentResourceSecrets, t as DEFAULT_RESOURCE_TIMEOUT_MS, ta as resolveStateBucketWithDefaultAndSource, ti as hasUnverifiableParameterRefusal, tn as requireConfigArray, to as ProvisioningError, tr as refuseMalformedResourceEntries, tt as collectPublishedOutputNames, u as resolveReplacementOldType, ua as uploadCfnTemplate, ui as WorkGraph, un as s3BucketRegionalDomainName, uo as normalizeAwsError, ur as repairMalformedResourcePropertiesForReadOnly, ut as clearOnUpdateRemoval, v as isSecretBearingReferenceString, va as PARTITION_TABLE, vi as ensureAssetStorage, vn as INTRINSIC_KEYS, vo as markNonRetryable, vr as describeTypeWithThrottleRetry, vt as beginCommandInterruptScope, w as reachableDivergentParameters, wa as processStackMessages, wi as validateContainerRepoName, wn as hasReadableOrphans, wr as STATE_SOURCED_READBACK_RULES, wt as slowCcOperationTimeoutMs, x as bindingSkippedOutputs, xa as AssemblyReader, xi as parseBootstrapMarker, xn as UNREADABLE_RESOURCES_MAP_ROW, xo as describeAwsFailure, xr as TemplateParser, xt as isInterruptedWaitError, y as keptWholeReasonText, ya as canonicalizeRegion, yi as getBootstrapMarkerKey, yn as STATE_RESOURCES_MALFORMED, yo as markRedactedCause, yr as withRetry, yt as endCommandInterruptScope, z as isStatefulRecreateTargetForReplace, za as runWithStackAwsClients, zi as runDockerForeground, zn as malformedRenderedContainersWarning, zr as recoverMaskedOutput, zt as isNamelessDynamicReferenceError } from "./deploy-engine-BwDlgFRs.js";
|
|
2
|
+
import { C as displayAwsMessage, D as isPasteableIdent, E as displayStackName, O as truncateCodePoints, S as UNRENDERABLE, T as displaySafe, _ as withSkipPrefix, b as SECRET_REF_MAX_CODE_POINTS, c as PATTERN_B_NAME_OPTIONS, f as explicitNamePropertyFor, h as getCurrentStackName, i as reserveStdoutForPayload, l as PATTERN_B_NAME_PROPERTIES, m as generateResourceNameWithFallback, n as getLogger, o as runStackBuffered, p as generateResourceName, s as getLiveRenderer, u as PATTERN_B_RESOURCE_TYPES, v as withStackName, w as displayIdent, x as STACK_REF_MAX_CODE_POINTS } from "./logger-Bt0RGDfb.js";
|
|
3
3
|
import { n as awsClientDefaults, s as ambientRegion } from "./aws-client-defaults-jISU4PHo.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-CJkb2usU.js";
|
|
5
|
+
import { a as renderDisableCommand, i as protectedReplacementAdvice, r as UNNAMEABLE_ID_CLAUSE, t as ASGProvider } from "./asg-provider-DR5gOGbi.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";
|
|
@@ -284,6 +284,51 @@ function describeStateKey(key, suffix = STATE_FILE_SUFFIX, knownPrefix) {
|
|
|
284
284
|
*/
|
|
285
285
|
const STATE_KEY_MAX_CODE_POINTS = STACK_REF_MAX_CODE_POINTS + 64;
|
|
286
286
|
|
|
287
|
+
//#endregion
|
|
288
|
+
//#region src/provisioning/remove-protection-types.ts
|
|
289
|
+
/**
|
|
290
|
+
* The resource types whose SDK provider's `delete()` flips a protection flag
|
|
291
|
+
* off under `DeleteContext.removeProtection` (issue
|
|
292
|
+
* [#2660](https://github.com/go-to-k/cdkd/issues/2660)).
|
|
293
|
+
*
|
|
294
|
+
* This is the ONE list the `--remove-protection` help strings render from, on
|
|
295
|
+
* `cdkd destroy` and `cdkd state destroy`. The Cloud Control half comes from
|
|
296
|
+
* {@link ccProtectionRegistryTypes}. Both copies of the help were hand-written
|
|
297
|
+
* before, and two types the providers honour (`AWS::EMR::Cluster`,
|
|
298
|
+
* `AWS::DynamoDB::GlobalTable`) were missing from both.
|
|
299
|
+
*
|
|
300
|
+
* `tests/unit/provisioning/remove-protection-types.test.ts` binds this list to
|
|
301
|
+
* the provider tree in both directions: each type's registered provider reads
|
|
302
|
+
* `removeProtection`, and each provider file that reads it registers at least
|
|
303
|
+
* one type here. A new provider gaining the flip fails that test until its type
|
|
304
|
+
* is added.
|
|
305
|
+
*/
|
|
306
|
+
const SDK_REMOVE_PROTECTION_TYPES = [
|
|
307
|
+
"AWS::Logs::LogGroup",
|
|
308
|
+
"AWS::RDS::DBInstance",
|
|
309
|
+
"AWS::RDS::DBCluster",
|
|
310
|
+
"AWS::DocDB::DBCluster",
|
|
311
|
+
"AWS::Neptune::DBCluster",
|
|
312
|
+
"AWS::Neptune::DBInstance",
|
|
313
|
+
"AWS::DynamoDB::Table",
|
|
314
|
+
"AWS::DynamoDB::GlobalTable",
|
|
315
|
+
"AWS::EC2::Instance",
|
|
316
|
+
"AWS::Cognito::UserPool",
|
|
317
|
+
"AWS::AutoScaling::AutoScalingGroup",
|
|
318
|
+
"AWS::ElasticLoadBalancingV2::LoadBalancer",
|
|
319
|
+
"AWS::EMR::Cluster"
|
|
320
|
+
];
|
|
321
|
+
/** Every type `--remove-protection` covers: the SDK list, then the Cloud Control registry. */
|
|
322
|
+
function removeProtectionTypes() {
|
|
323
|
+
return [...SDK_REMOVE_PROTECTION_TYPES, ...ccProtectionRegistryTypes()];
|
|
324
|
+
}
|
|
325
|
+
/** The types as the help prints them: `A, B, and C`. */
|
|
326
|
+
function removeProtectionTypeList() {
|
|
327
|
+
const types = removeProtectionTypes();
|
|
328
|
+
if (types.length < 2) return types.join("");
|
|
329
|
+
return `${types.slice(0, -1).join(", ")}, and ${types[types.length - 1]}`;
|
|
330
|
+
}
|
|
331
|
+
|
|
287
332
|
//#endregion
|
|
288
333
|
//#region src/cli/options.ts
|
|
289
334
|
/**
|
|
@@ -1127,7 +1172,7 @@ function effectiveAssumeRoleArn(logicalId, opt) {
|
|
|
1127
1172
|
*/
|
|
1128
1173
|
const destroyOptions = [
|
|
1129
1174
|
new Option("-f, --force", "Do not ask for confirmation before destroying the stacks").default(false),
|
|
1130
|
-
new Option("--remove-protection",
|
|
1175
|
+
new Option("--remove-protection", `Bypass deletion protection on protected resources by flipping the per-resource protection flag off in-place before delete. Covers stack-level terminationProtection (CDK property) and resource-level protection on ${removeProtectionTypeList()}.`).default(false),
|
|
1131
1176
|
allowUnsupportedTypesOption
|
|
1132
1177
|
];
|
|
1133
1178
|
/**
|
|
@@ -2392,12 +2437,12 @@ function countDeployableResources(template) {
|
|
|
2392
2437
|
*/
|
|
2393
2438
|
function resolveVerboseTemplatePath(outputDir, stackName) {
|
|
2394
2439
|
const resolved = resolveAssemblyPath(outputDir, `${stackName}.template.json`);
|
|
2395
|
-
if (!resolved.contained) throw new SynthesisError(`Stack
|
|
2440
|
+
if (!resolved.contained) throw new SynthesisError(`Stack ${displayStackName(stackName)} would write its template to a path that ${renderAssemblyPathEscape(resolved, outputDir, "write it")}`);
|
|
2396
2441
|
let linked = false;
|
|
2397
2442
|
try {
|
|
2398
2443
|
linked = lstatSync(resolved.path).isSymbolicLink();
|
|
2399
2444
|
} catch {}
|
|
2400
|
-
if (linked) throw new SynthesisError(`Stack
|
|
2445
|
+
if (linked) throw new SynthesisError(`Stack ${displayStackName(stackName)} would write its template over a symbolic link at ${displayAssemblyPath(resolved.path)}. cdkd writes a stack's template as a regular file beside the assembly; a symbolic link there redirects the write to wherever it points, so this indicates the synth output was hand-modified or generated by a non-CDK toolchain. Refusing to write it.`);
|
|
2401
2446
|
return resolved.path;
|
|
2402
2447
|
}
|
|
2403
2448
|
/**
|
|
@@ -3789,15 +3834,16 @@ function findNestedTemplateTreeDefect(nestedTemplates, ancestorTemplatePaths = [
|
|
|
3789
3834
|
/** Hops rendered in full before the middle of a long chain is elided. */
|
|
3790
3835
|
const MAX_RENDERED_HOPS = 8;
|
|
3791
3836
|
/**
|
|
3792
|
-
* `
|
|
3793
|
-
* `
|
|
3837
|
+
* `A (/x/a.json) -> B (/x/b.json)`. The logical id renders through
|
|
3838
|
+
* `displayIdent` and the path through `displayAssemblyPath`, each supplying its
|
|
3839
|
+
* own boundary: this text exists FOR a hand-modified assembly, so a logical id
|
|
3794
3840
|
* (a template key) and a path (derived from `aws:asset:path`) are both
|
|
3795
3841
|
* attacker-controlled, and a bare `Error` message is not sanitized downstream.
|
|
3796
3842
|
* A long chain keeps both ends, since the entry row and the closing row are
|
|
3797
3843
|
* the two a reader needs.
|
|
3798
3844
|
*/
|
|
3799
3845
|
function renderChain(chain) {
|
|
3800
|
-
const hop = (h) =>
|
|
3846
|
+
const hop = (h) => `${displayIdent(h.logicalId)} (${displayAssemblyPath(h.templatePath)})`;
|
|
3801
3847
|
if (chain.length <= MAX_RENDERED_HOPS) return chain.map(hop).join(" -> ");
|
|
3802
3848
|
const keep = MAX_RENDERED_HOPS / 2;
|
|
3803
3849
|
return [
|
|
@@ -3815,21 +3861,19 @@ function renderNestedTemplateTreeDefect(defect, stackName, action) {
|
|
|
3815
3861
|
const owner = (chain) => {
|
|
3816
3862
|
const ids = chain.slice(0, -1).map((h) => h.logicalId);
|
|
3817
3863
|
const keep = MAX_RENDERED_HOPS / 2;
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
];
|
|
3823
|
-
return displaySafe([stackName, ...shown].join("~"));
|
|
3864
|
+
if (ids.length <= MAX_RENDERED_HOPS) return displayStackName([stackName, ...ids].join("~"));
|
|
3865
|
+
const head = displayStackName([stackName, ...ids.slice(0, keep)].join("~"));
|
|
3866
|
+
const tail = displayStackName(ids.slice(-4).join("~"));
|
|
3867
|
+
return `${head}~...${ids.length - 8} more...~${tail}`;
|
|
3824
3868
|
};
|
|
3825
3869
|
if (defect.kind === "cycle") {
|
|
3826
3870
|
const closing = defect.chain[defect.chain.length - 1];
|
|
3827
|
-
return `The nested template tree under stack
|
|
3871
|
+
return `The nested template tree under stack ${displayStackName(stackName)} contains a cycle: ${renderChain(defect.chain)}. Nested stack ${displayIdent(closing.logicalId)} (declared in stack ${owner(defect.chain)}) resolves to a template that is already on that nesting chain, so its Metadata['aws:asset:path'] closes a cycle. ${provenance}`;
|
|
3828
3872
|
}
|
|
3829
|
-
if (defect.kind === "too-large") return `The nested template tree under stack
|
|
3830
|
-
if (defect.kind === "too-deep") return `The nested template tree under stack
|
|
3831
|
-
if (defect.kind === "escaping-path") return `The nested template tree under stack
|
|
3832
|
-
return `The nested template tree under stack
|
|
3873
|
+
if (defect.kind === "too-large") return `The nested template tree under stack ${displayStackName(stackName)} has more than ${MAX_ROWS_FOLLOWED} nested-stack rows to follow (the walk stopped at ${renderChain(defect.chain)}). That is far beyond any CDK-generated assembly. Symlinked directories can give one template file many paths, which multiplies the tree without ever repeating on one chain. Refusing to ${action}.`;
|
|
3874
|
+
if (defect.kind === "too-deep") return `The nested template tree under stack ${displayStackName(stackName)} nests more than ${512} levels deep: ${renderChain(defect.chain)}. No tree that deep can deploy, because each level lengthens the child's state key and S3 caps a key at 1024 bytes. ${provenance}`;
|
|
3875
|
+
if (defect.kind === "escaping-path") return `The nested template tree under stack ${displayStackName(stackName)} has nested stack ${displayIdent(defect.logicalId)} (reached through ${renderChain(defect.chain)}) with Metadata['aws:asset:path']=${displayAssemblyPath(defect.assetPath)} which ${renderAssemblyPathEscape(defect.escape, defect.dir, action)}`;
|
|
3876
|
+
return `The nested template tree under stack ${displayStackName(stackName)} has nested stack ${displayIdent(defect.logicalId)} (reached through ${renderChain(defect.chain)}) with Metadata['aws:asset:path']=${displayAssemblyPath(defect.assetPath)} which is absolute. ${provenance}`;
|
|
3833
3877
|
}
|
|
3834
3878
|
|
|
3835
3879
|
//#endregion
|
|
@@ -4598,8 +4642,8 @@ var ExportIndexStore = class {
|
|
|
4598
4642
|
*/
|
|
4599
4643
|
warnOnForeignOverwrite(existing, exportName, stackName, producerRegion) {
|
|
4600
4644
|
if (!existing || existing.producerStack === stackName) return;
|
|
4601
|
-
const
|
|
4602
|
-
this.logger.warn(`Export
|
|
4645
|
+
const theirs = displayStackName(existing.producerStack);
|
|
4646
|
+
this.logger.warn(`Export ${displayIdent(exportName)} is published by both ${theirs} (${displayIdent(existing.producerRegion)}) and ${displayStackName(stackName)} (${displayIdent(producerRegion)}); the exports index keeps the latest writer, so an Fn::ImportValue on it binds to whichever deployed last. CloudFormation refuses a second producer of the same export name — rename one of the two exports. (If ${theirs} predates cdkd's state schema v9, this is its stale entry for a plain output of that name, and its next deploy clears it.)`);
|
|
4603
4647
|
}
|
|
4604
4648
|
async applyPatch(exportName, entry, requireOwner) {
|
|
4605
4649
|
await this.ensureLoaded();
|
|
@@ -4607,7 +4651,7 @@ var ExportIndexStore = class {
|
|
|
4607
4651
|
if (requireOwner) {
|
|
4608
4652
|
const current = this.loadState.entries.get(exportName);
|
|
4609
4653
|
if (!current || current.producerStack !== requireOwner.producerStack || current.producerRegion !== requireOwner.producerRegion) {
|
|
4610
|
-
this.logger.warn(`Exports index entry ownership changed under a patch; refusing to write it. Expected producer
|
|
4654
|
+
this.logger.warn(`Exports index entry ownership changed under a patch; refusing to write it. Expected producer ${displayStackName(requireOwner.producerStack)} (${displayIdent(requireOwner.producerRegion)}), found ${current ? `${displayStackName(current.producerStack)} (${displayIdent(current.producerRegion)})` : "no entry"}.`);
|
|
4611
4655
|
return false;
|
|
4612
4656
|
}
|
|
4613
4657
|
}
|
|
@@ -5862,10 +5906,10 @@ var IAMInstanceProfileProvider = class {
|
|
|
5862
5906
|
async import(input) {
|
|
5863
5907
|
const explicit = resolveExplicitPhysicalId(input, "InstanceProfileName");
|
|
5864
5908
|
if (explicit) try {
|
|
5865
|
-
await this.iamClient.send(new GetInstanceProfileCommand({ InstanceProfileName: explicit }));
|
|
5909
|
+
const resp = await this.iamClient.send(new GetInstanceProfileCommand({ InstanceProfileName: explicit }));
|
|
5866
5910
|
return {
|
|
5867
5911
|
physicalId: explicit,
|
|
5868
|
-
attributes: {}
|
|
5912
|
+
attributes: definedAttributes({ Arn: resp.InstanceProfile?.Arn })
|
|
5869
5913
|
};
|
|
5870
5914
|
} catch (err) {
|
|
5871
5915
|
if (err instanceof NoSuchEntityException) return null;
|
|
@@ -7199,10 +7243,10 @@ var IAMUserGroupProvider = class {
|
|
|
7199
7243
|
async importUser(input) {
|
|
7200
7244
|
const explicit = resolveExplicitPhysicalId(input, "UserName");
|
|
7201
7245
|
if (explicit) try {
|
|
7202
|
-
await this.iamClient.send(new GetUserCommand({ UserName: explicit }));
|
|
7246
|
+
const resp = await this.iamClient.send(new GetUserCommand({ UserName: explicit }));
|
|
7203
7247
|
return {
|
|
7204
7248
|
physicalId: explicit,
|
|
7205
|
-
attributes: {}
|
|
7249
|
+
attributes: definedAttributes({ Arn: resp.User?.Arn })
|
|
7206
7250
|
};
|
|
7207
7251
|
} catch (err) {
|
|
7208
7252
|
if (err instanceof NoSuchEntityException) return null;
|
|
@@ -7213,10 +7257,10 @@ var IAMUserGroupProvider = class {
|
|
|
7213
7257
|
async importGroup(input) {
|
|
7214
7258
|
const explicit = resolveExplicitPhysicalId(input, "GroupName");
|
|
7215
7259
|
if (explicit) try {
|
|
7216
|
-
await this.iamClient.send(new GetGroupCommand({ GroupName: explicit }));
|
|
7260
|
+
const resp = await this.iamClient.send(new GetGroupCommand({ GroupName: explicit }));
|
|
7217
7261
|
return {
|
|
7218
7262
|
physicalId: explicit,
|
|
7219
|
-
attributes: {}
|
|
7263
|
+
attributes: definedAttributes({ Arn: resp.Group?.Arn })
|
|
7220
7264
|
};
|
|
7221
7265
|
} catch (err) {
|
|
7222
7266
|
if (err instanceof NoSuchEntityException) return null;
|
|
@@ -13868,6 +13912,29 @@ function isSnsTopicArnList(value) {
|
|
|
13868
13912
|
*/
|
|
13869
13913
|
const LAMBDA_CLEANUP_DELETE_MAX_ATTEMPTS = 3;
|
|
13870
13914
|
/**
|
|
13915
|
+
* Refuse `CodeSigningConfigArn` / `RuntimeManagementConfig` on a
|
|
13916
|
+
* container-image function (`PackageType: Image`), BEFORE any Lambda call.
|
|
13917
|
+
* AWS rejects both there with `InvalidParameterValueException`: the image
|
|
13918
|
+
* carries its own runtime, so there are no runtime-management controls, and
|
|
13919
|
+
* Lambda code signing does not apply to images (issue
|
|
13920
|
+
* [#1894](https://github.com/go-to-k/cdkd/issues/1894)). The READ side skips
|
|
13921
|
+
* the matching `Get*` calls for the same reason (see `readCurrentState`). Without it the create either
|
|
13922
|
+
* fails on `CreateFunction` (code signing) or creates the function, fails the
|
|
13923
|
+
* post-create `PutRuntimeManagementConfig` and deletes it again; the update
|
|
13924
|
+
* fails part-way through on the Put.
|
|
13925
|
+
*
|
|
13926
|
+
* Unconditional, including on a rollback replay (`replayingState`): AWS
|
|
13927
|
+
* rejects the combination every time, so no state record can carry it and a
|
|
13928
|
+
* downgraded warning could only report success over a call that then fails
|
|
13929
|
+
* (the `.claude/rules/provider-replay-and-refusals.md` exception).
|
|
13930
|
+
*/
|
|
13931
|
+
function refuseImageFunctionUnsupported(logicalId, resourceType, properties, physicalId) {
|
|
13932
|
+
if (properties["PackageType"] !== "Image") return;
|
|
13933
|
+
const declared = [properties["CodeSigningConfigArn"] !== void 0 ? "CodeSigningConfigArn" : void 0, properties["RuntimeManagementConfig"] !== void 0 ? "RuntimeManagementConfig" : void 0].filter((key) => key !== void 0);
|
|
13934
|
+
if (declared.length === 0) return;
|
|
13935
|
+
throw markNonRetryable(new ProvisioningError(`Lambda function ${logicalId} is a container-image function (PackageType: Image), and AWS rejects ${declared.join(" and ")} on one: an image carries its own runtime and Lambda code signing does not apply to images. Remove ${declared.length === 1 ? "it" : "them"} from the function's properties.`, resourceType, logicalId, physicalId));
|
|
13936
|
+
}
|
|
13937
|
+
/**
|
|
13871
13938
|
* Pick the inline-code filename for a Lambda runtime.
|
|
13872
13939
|
*
|
|
13873
13940
|
* CloudFormation's `Code.ZipFile` auto-zips inline code into a file named
|
|
@@ -13962,6 +14029,7 @@ var LambdaFunctionProvider = class {
|
|
|
13962
14029
|
const role = properties["Role"];
|
|
13963
14030
|
if (!code) throw new ProvisioningError(`Code is required for Lambda function ${logicalId}`, resourceType, logicalId);
|
|
13964
14031
|
if (!role) throw new ProvisioningError(`Role is required for Lambda function ${logicalId}`, resourceType, logicalId);
|
|
14032
|
+
refuseImageFunctionUnsupported(logicalId, resourceType, properties);
|
|
13965
14033
|
try {
|
|
13966
14034
|
let tags;
|
|
13967
14035
|
if (properties["Tags"]) {
|
|
@@ -14112,6 +14180,7 @@ var LambdaFunctionProvider = class {
|
|
|
14112
14180
|
const mask = maskerOrIdentity(context?.maskSecrets);
|
|
14113
14181
|
const debug = (message) => this.logger.debug(mask(message));
|
|
14114
14182
|
this.logger.debug(`Updating Lambda function ${logicalId}: ${physicalId}`);
|
|
14183
|
+
refuseImageFunctionUnsupported(logicalId, resourceType, properties, physicalId);
|
|
14115
14184
|
try {
|
|
14116
14185
|
const configFields = [
|
|
14117
14186
|
"Role",
|
|
@@ -27953,10 +28022,17 @@ var SSMParameterProvider = class {
|
|
|
27953
28022
|
if (explicit) {
|
|
27954
28023
|
this.refuseUnwritableParameterId(input, explicit);
|
|
27955
28024
|
try {
|
|
27956
|
-
const
|
|
28025
|
+
const resp = await this.ssmClient.send(new GetParameterCommand({ Name: explicit }));
|
|
28026
|
+
const arn = resp.Parameter?.ARN;
|
|
28027
|
+
const declared = input.properties?.["Value"];
|
|
28028
|
+
const literalValue = typeof declared === "string" && !declared.includes("{{resolve:");
|
|
27957
28029
|
return {
|
|
27958
28030
|
physicalId: explicit,
|
|
27959
|
-
attributes: {
|
|
28031
|
+
attributes: definedAttributes({
|
|
28032
|
+
Type: resp.Parameter?.Type,
|
|
28033
|
+
...literalValue && { Value: resp.Parameter?.Value },
|
|
28034
|
+
Arn: arn
|
|
28035
|
+
})
|
|
27960
28036
|
};
|
|
27961
28037
|
} catch (err) {
|
|
27962
28038
|
if (err instanceof ParameterNotFound) return null;
|
|
@@ -28701,6 +28777,39 @@ var EventBridgeBusProvider = class {
|
|
|
28701
28777
|
}
|
|
28702
28778
|
};
|
|
28703
28779
|
|
|
28780
|
+
//#endregion
|
|
28781
|
+
//#region src/utils/ipv4-cidr.ts
|
|
28782
|
+
/**
|
|
28783
|
+
* Return the host-bit-cleared form of an IPv4 CIDR (`100.68.0.18/18` ->
|
|
28784
|
+
* `100.68.0.0/18`), or `undefined` when the input is not an IPv4 CIDR at all
|
|
28785
|
+
* (an IPv6 CIDR, a `pl-…` prefix-list id, or anything malformed).
|
|
28786
|
+
*
|
|
28787
|
+
* AWS rewrites a non-canonical CIDR on `CreateRoute`, so a route id that
|
|
28788
|
+
* spells the template's CIDR can differ from the destination AWS reports
|
|
28789
|
+
* (issue #1771). `EC2Provider`'s import compares through this (issue #3661).
|
|
28790
|
+
* `src/cli/commands/export.ts` still carries a private copy of the same
|
|
28791
|
+
* function; fold it onto this one once the open PR holding that file lands.
|
|
28792
|
+
*/
|
|
28793
|
+
function canonicalizeIpv4Cidr$1(value) {
|
|
28794
|
+
const match = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\/(\d{1,2})$/.exec(value);
|
|
28795
|
+
if (!match) return void 0;
|
|
28796
|
+
const octets = [
|
|
28797
|
+
match[1],
|
|
28798
|
+
match[2],
|
|
28799
|
+
match[3],
|
|
28800
|
+
match[4]
|
|
28801
|
+
].map(Number);
|
|
28802
|
+
const prefixLength = Number(match[5]);
|
|
28803
|
+
if (prefixLength > 32 || octets.some((octet) => octet > 255)) return void 0;
|
|
28804
|
+
const network = ((octets[0] << 24 | octets[1] << 16 | octets[2] << 8 | octets[3]) >>> 0 & (prefixLength === 0 ? 0 : 4294967295 << 32 - prefixLength >>> 0)) >>> 0;
|
|
28805
|
+
return `${[
|
|
28806
|
+
network >>> 24,
|
|
28807
|
+
network >>> 16 & 255,
|
|
28808
|
+
network >>> 8 & 255,
|
|
28809
|
+
network & 255
|
|
28810
|
+
].join(".")}/${prefixLength}`;
|
|
28811
|
+
}
|
|
28812
|
+
|
|
28704
28813
|
//#endregion
|
|
28705
28814
|
//#region src/provisioning/providers/idempotency-token.ts
|
|
28706
28815
|
/**
|
|
@@ -30225,12 +30334,16 @@ var EC2Provider = class {
|
|
|
30225
30334
|
try {
|
|
30226
30335
|
const ingressRules = properties["SecurityGroupIngress"];
|
|
30227
30336
|
const egressRules = properties["SecurityGroupEgress"];
|
|
30228
|
-
|
|
30229
|
-
|
|
30230
|
-
|
|
30231
|
-
|
|
30232
|
-
|
|
30233
|
-
|
|
30337
|
+
let firstRejection;
|
|
30338
|
+
const recordRejection = (branch) => branch.catch((error) => {
|
|
30339
|
+
firstRejection ??= { error };
|
|
30340
|
+
});
|
|
30341
|
+
await Promise.all([
|
|
30342
|
+
recordRejection(this.applyTags(groupId, properties, logicalId)),
|
|
30343
|
+
recordRejection(this.authorizeInlineIngress(groupId, ingressRules)),
|
|
30344
|
+
recordRejection(this.applyInlineEgress(groupId, egressRules))
|
|
30345
|
+
]);
|
|
30346
|
+
if (firstRejection !== void 0) throw firstRejection.error;
|
|
30234
30347
|
} catch (innerError) {
|
|
30235
30348
|
try {
|
|
30236
30349
|
await this.ec2Client.send(new DeleteSecurityGroupCommand({ GroupId: groupId }));
|
|
@@ -31572,12 +31685,14 @@ var EC2Provider = class {
|
|
|
31572
31685
|
* id, and records cdkd's composite `<groupId>|<ipProtocol>|<fromPort>|<toPort>`
|
|
31573
31686
|
* plus the rule id as the `Id` attribute (issue #1761).
|
|
31574
31687
|
*
|
|
31575
|
-
*
|
|
31576
|
-
*
|
|
31577
|
-
*
|
|
31578
|
-
*
|
|
31579
|
-
*
|
|
31580
|
-
*
|
|
31688
|
+
* - RouteTable, Route, InternetGateway, VPCGatewayAttachment, NetworkAcl,
|
|
31689
|
+
* NetworkAclEntry, SubnetRouteTableAssociation, SubnetNetworkAclAssociation,
|
|
31690
|
+
* Instance (issue #3661) — they used to return `null` on the premise that
|
|
31691
|
+
* cdkd reconstructs them at deploy time, which `--migrate-from-cloudformation`
|
|
31692
|
+
* breaks: the CloudFormation stack is retired with them live, and the
|
|
31693
|
+
* re-create duplicates or conflicts. VPCGatewayAttachment and
|
|
31694
|
+
* NetworkAclEntry rebuild cdkd's composite from the template, since
|
|
31695
|
+
* CloudFormation's id for them does not carry it.
|
|
31581
31696
|
*
|
|
31582
31697
|
* There is no `aws:cdk:path` tag lookup: AWS rejects `aws:`-prefixed tag
|
|
31583
31698
|
* writes, so that tag never exists on a real resource and a
|
|
@@ -31587,7 +31702,7 @@ var EC2Provider = class {
|
|
|
31587
31702
|
* physical-name property instead.
|
|
31588
31703
|
*/
|
|
31589
31704
|
async import(input) {
|
|
31590
|
-
if (input.knownPhysicalId) return this.verifyExplicit(input.logicalId, input.resourceType, input.knownPhysicalId);
|
|
31705
|
+
if (input.knownPhysicalId) return this.verifyExplicit(input.logicalId, input.resourceType, input.knownPhysicalId, input.properties ?? {});
|
|
31591
31706
|
return null;
|
|
31592
31707
|
}
|
|
31593
31708
|
/**
|
|
@@ -32150,17 +32265,23 @@ var EC2Provider = class {
|
|
|
32150
32265
|
}
|
|
32151
32266
|
}
|
|
32152
32267
|
}
|
|
32153
|
-
async verifyExplicit(logicalId, resourceType, physicalId) {
|
|
32268
|
+
async verifyExplicit(logicalId, resourceType, physicalId, properties) {
|
|
32154
32269
|
try {
|
|
32155
32270
|
switch (resourceType) {
|
|
32156
32271
|
case "AWS::EC2::VPC": return (await this.ec2Client.send(new DescribeVpcsCommand({ VpcIds: [physicalId] }))).Vpcs?.[0] ? {
|
|
32157
32272
|
physicalId,
|
|
32158
32273
|
attributes: {}
|
|
32159
32274
|
} : null;
|
|
32160
|
-
case "AWS::EC2::Subnet":
|
|
32161
|
-
physicalId
|
|
32162
|
-
|
|
32163
|
-
|
|
32275
|
+
case "AWS::EC2::Subnet": {
|
|
32276
|
+
const subnet = (await this.ec2Client.send(new DescribeSubnetsCommand({ SubnetIds: [physicalId] }))).Subnets?.[0];
|
|
32277
|
+
return subnet ? {
|
|
32278
|
+
physicalId,
|
|
32279
|
+
attributes: definedAttributes({
|
|
32280
|
+
SubnetId: physicalId,
|
|
32281
|
+
AvailabilityZone: subnet.AvailabilityZone
|
|
32282
|
+
})
|
|
32283
|
+
} : null;
|
|
32284
|
+
}
|
|
32164
32285
|
case "AWS::EC2::SecurityGroup": {
|
|
32165
32286
|
const group = (await this.ec2Client.send(new DescribeSecurityGroupsCommand({ GroupIds: [physicalId] }))).SecurityGroups?.[0];
|
|
32166
32287
|
if (!group) return null;
|
|
@@ -32233,6 +32354,125 @@ var EC2Provider = class {
|
|
|
32233
32354
|
}
|
|
32234
32355
|
};
|
|
32235
32356
|
}
|
|
32357
|
+
case "AWS::EC2::RouteTable":
|
|
32358
|
+
if (!/^rtb-[0-9a-f]+$/.test(physicalId)) return null;
|
|
32359
|
+
return (await this.ec2Client.send(new DescribeRouteTablesCommand({ RouteTableIds: [physicalId] }))).RouteTables?.[0] ? {
|
|
32360
|
+
physicalId,
|
|
32361
|
+
attributes: { RouteTableId: physicalId }
|
|
32362
|
+
} : null;
|
|
32363
|
+
case "AWS::EC2::InternetGateway":
|
|
32364
|
+
if (!/^igw-[0-9a-f]+$/.test(physicalId)) return null;
|
|
32365
|
+
return (await this.ec2Client.send(new DescribeInternetGatewaysCommand({ InternetGatewayIds: [physicalId] }))).InternetGateways?.[0] ? {
|
|
32366
|
+
physicalId,
|
|
32367
|
+
attributes: { InternetGatewayId: physicalId }
|
|
32368
|
+
} : null;
|
|
32369
|
+
case "AWS::EC2::NetworkAcl":
|
|
32370
|
+
if (!/^acl-[0-9a-f]+$/.test(physicalId)) return null;
|
|
32371
|
+
return (await this.ec2Client.send(new DescribeNetworkAclsCommand({ NetworkAclIds: [physicalId] }))).NetworkAcls?.[0] ? {
|
|
32372
|
+
physicalId,
|
|
32373
|
+
attributes: { Id: physicalId }
|
|
32374
|
+
} : null;
|
|
32375
|
+
case "AWS::EC2::Route": {
|
|
32376
|
+
const [routeTableId, destination, ...rest] = physicalId.split("|");
|
|
32377
|
+
if (rest.length > 0 || !routeTableId || !destination) return null;
|
|
32378
|
+
if (!/^rtb-[0-9a-f]+$/.test(routeTableId)) return null;
|
|
32379
|
+
const resp = await this.ec2Client.send(new DescribeRouteTablesCommand({ RouteTableIds: [routeTableId] }));
|
|
32380
|
+
const wanted = canonicalizeIpv4Cidr$1(destination) ?? destination;
|
|
32381
|
+
return resp.RouteTables?.[0]?.Routes?.some((r) => r.DestinationCidrBlock !== void 0 && (canonicalizeIpv4Cidr$1(r.DestinationCidrBlock) ?? r.DestinationCidrBlock) === wanted || r.DestinationIpv6CidrBlock === destination || r.DestinationPrefixListId === destination) ? {
|
|
32382
|
+
physicalId,
|
|
32383
|
+
attributes: {}
|
|
32384
|
+
} : null;
|
|
32385
|
+
}
|
|
32386
|
+
case "AWS::EC2::VPCGatewayAttachment": {
|
|
32387
|
+
const segments = physicalId.split("|");
|
|
32388
|
+
if (segments.length !== 2) return null;
|
|
32389
|
+
if (segments.includes("VGW") || properties["VpnGatewayId"] !== void 0) return null;
|
|
32390
|
+
const vpcId = segments.find((seg) => /^vpc-[0-9a-f]+$/.test(seg)) ?? (typeof properties["VpcId"] === "string" ? properties["VpcId"] : void 0);
|
|
32391
|
+
if (!vpcId || !/^vpc-[0-9a-f]+$/.test(vpcId)) return null;
|
|
32392
|
+
const declared = segments.find((seg) => /^igw-[0-9a-f]+$/.test(seg)) ?? (typeof properties["InternetGatewayId"] === "string" ? properties["InternetGatewayId"] : void 0);
|
|
32393
|
+
if (declared !== void 0 && !/^igw-[0-9a-f]+$/.test(declared)) return null;
|
|
32394
|
+
const gateway = (await this.ec2Client.send(new DescribeInternetGatewaysCommand(declared ? { InternetGatewayIds: [declared] } : { Filters: [{
|
|
32395
|
+
Name: "attachment.vpc-id",
|
|
32396
|
+
Values: [vpcId]
|
|
32397
|
+
}] }))).InternetGateways?.find((g) => g.Attachments?.some((a) => a.VpcId === vpcId && ["available", "attached"].includes(String(a.State))));
|
|
32398
|
+
if (!gateway?.InternetGatewayId) return null;
|
|
32399
|
+
const attachmentSegments = [{
|
|
32400
|
+
name: "internetGatewayId",
|
|
32401
|
+
value: gateway.InternetGatewayId
|
|
32402
|
+
}, {
|
|
32403
|
+
name: "vpcId",
|
|
32404
|
+
value: vpcId
|
|
32405
|
+
}];
|
|
32406
|
+
const refusal = compositeIdSeparatorRefusal(resourceType, logicalId, attachmentSegments);
|
|
32407
|
+
if (refusal !== void 0) {
|
|
32408
|
+
this.logger.warn(`${refusal} Skipping import.`);
|
|
32409
|
+
return null;
|
|
32410
|
+
}
|
|
32411
|
+
return {
|
|
32412
|
+
physicalId: packCompositeId(resourceType, logicalId, attachmentSegments),
|
|
32413
|
+
attributes: {}
|
|
32414
|
+
};
|
|
32415
|
+
}
|
|
32416
|
+
case "AWS::EC2::NetworkAclEntry": {
|
|
32417
|
+
const own = /^(acl-[0-9a-f]+)\|(\d+)\|(true|false)$/.exec(physicalId);
|
|
32418
|
+
const networkAclId = own ? own[1] : typeof properties["NetworkAclId"] === "string" ? properties["NetworkAclId"] : void 0;
|
|
32419
|
+
const ruleNumber = own ? Number(own[2]) : Number(properties["RuleNumber"]);
|
|
32420
|
+
const egress = own ? own[3] === "true" : properties["Egress"] === true || properties["Egress"] === "true";
|
|
32421
|
+
if (!networkAclId || !/^acl-[0-9a-f]+$/.test(networkAclId)) return null;
|
|
32422
|
+
if (!Number.isInteger(ruleNumber)) return null;
|
|
32423
|
+
if (!(await this.ec2Client.send(new DescribeNetworkAclsCommand({ NetworkAclIds: [networkAclId] }))).NetworkAcls?.[0]?.Entries?.find((e) => e.RuleNumber === ruleNumber && (e.Egress ?? false) === egress)) return null;
|
|
32424
|
+
const entrySegments = [
|
|
32425
|
+
{
|
|
32426
|
+
name: "networkAclId",
|
|
32427
|
+
value: networkAclId
|
|
32428
|
+
},
|
|
32429
|
+
{
|
|
32430
|
+
name: "ruleNumber",
|
|
32431
|
+
value: ruleNumber
|
|
32432
|
+
},
|
|
32433
|
+
{
|
|
32434
|
+
name: "egress",
|
|
32435
|
+
value: egress
|
|
32436
|
+
}
|
|
32437
|
+
];
|
|
32438
|
+
const refusal = compositeIdSeparatorRefusal(resourceType, logicalId, entrySegments);
|
|
32439
|
+
if (refusal !== void 0) {
|
|
32440
|
+
this.logger.warn(`${refusal} Skipping import.`);
|
|
32441
|
+
return null;
|
|
32442
|
+
}
|
|
32443
|
+
return {
|
|
32444
|
+
physicalId: packCompositeId(resourceType, logicalId, entrySegments),
|
|
32445
|
+
attributes: {}
|
|
32446
|
+
};
|
|
32447
|
+
}
|
|
32448
|
+
case "AWS::EC2::SubnetRouteTableAssociation":
|
|
32449
|
+
if (!/^rtbassoc-[0-9a-f]+$/.test(physicalId)) return null;
|
|
32450
|
+
return (await this.ec2Client.send(new DescribeRouteTablesCommand({ Filters: [{
|
|
32451
|
+
Name: "association.route-table-association-id",
|
|
32452
|
+
Values: [physicalId]
|
|
32453
|
+
}] }))).RouteTables?.[0] ? {
|
|
32454
|
+
physicalId,
|
|
32455
|
+
attributes: {}
|
|
32456
|
+
} : null;
|
|
32457
|
+
case "AWS::EC2::SubnetNetworkAclAssociation":
|
|
32458
|
+
if (!/^aclassoc-[0-9a-f]+$/.test(physicalId)) return null;
|
|
32459
|
+
return (await this.ec2Client.send(new DescribeNetworkAclsCommand({ Filters: [{
|
|
32460
|
+
Name: "association.association-id",
|
|
32461
|
+
Values: [physicalId]
|
|
32462
|
+
}] }))).NetworkAcls?.[0] ? {
|
|
32463
|
+
physicalId,
|
|
32464
|
+
attributes: { AssociationId: physicalId }
|
|
32465
|
+
} : null;
|
|
32466
|
+
case "AWS::EC2::Instance": {
|
|
32467
|
+
if (!/^i-[0-9a-f]+$/.test(physicalId)) return null;
|
|
32468
|
+
const instance = (await this.ec2Client.send(new DescribeInstancesCommand({ InstanceIds: [physicalId] }))).Reservations?.[0]?.Instances?.[0];
|
|
32469
|
+
const state = instance?.State?.Name;
|
|
32470
|
+
if (!instance || state === "terminated" || state === "shutting-down") return null;
|
|
32471
|
+
return {
|
|
32472
|
+
physicalId,
|
|
32473
|
+
attributes: describedInstanceAttributes(physicalId, instance)
|
|
32474
|
+
};
|
|
32475
|
+
}
|
|
32236
32476
|
default: return null;
|
|
32237
32477
|
}
|
|
32238
32478
|
} catch (error) {
|
|
@@ -35799,13 +36039,28 @@ var CloudFrontOAIProvider = class {
|
|
|
35799
36039
|
*
|
|
35800
36040
|
* Users adopting an existing OAI should pass
|
|
35801
36041
|
* `--resource <logicalId>=<oaiId>` (e.g. `E1ABCDEF123456`).
|
|
36042
|
+
*
|
|
36043
|
+
* The override is read back (issue #3627): `S3CanonicalUserId` is the
|
|
36044
|
+
* attribute an S3 bucket policy grants the OAI by, `create()` records it,
|
|
36045
|
+
* and the resolver cannot build it from the id. Returns `null` when no OAI
|
|
36046
|
+
* exists behind the id.
|
|
35802
36047
|
*/
|
|
35803
36048
|
async import(input) {
|
|
35804
|
-
if (input.knownPhysicalId) return
|
|
36049
|
+
if (!input.knownPhysicalId) return null;
|
|
36050
|
+
let resp;
|
|
36051
|
+
try {
|
|
36052
|
+
resp = await this.cloudFrontClient.send(new GetCloudFrontOriginAccessIdentityCommand({ Id: input.knownPhysicalId }));
|
|
36053
|
+
} catch (err) {
|
|
36054
|
+
if (err instanceof NoSuchCloudFrontOriginAccessIdentity) return null;
|
|
36055
|
+
throw err;
|
|
36056
|
+
}
|
|
36057
|
+
return {
|
|
35805
36058
|
physicalId: input.knownPhysicalId,
|
|
35806
|
-
attributes: {
|
|
36059
|
+
attributes: definedAttributes({
|
|
36060
|
+
Id: input.knownPhysicalId,
|
|
36061
|
+
S3CanonicalUserId: resp.CloudFrontOriginAccessIdentity?.S3CanonicalUserId
|
|
36062
|
+
})
|
|
35807
36063
|
};
|
|
35808
|
-
return null;
|
|
35809
36064
|
}
|
|
35810
36065
|
};
|
|
35811
36066
|
|
|
@@ -37933,20 +38188,24 @@ var AgentCoreEvaluatorProvider = class {
|
|
|
37933
38188
|
*/
|
|
37934
38189
|
async import(input) {
|
|
37935
38190
|
if (!input.knownPhysicalId) return null;
|
|
37936
|
-
|
|
37937
|
-
|
|
37938
|
-
|
|
37939
|
-
|
|
37940
|
-
|
|
37941
|
-
|
|
37942
|
-
|
|
37943
|
-
|
|
38191
|
+
const isArn = input.knownPhysicalId.includes(":evaluator/");
|
|
38192
|
+
let response;
|
|
38193
|
+
try {
|
|
38194
|
+
response = await this.client.send(new GetEvaluatorCommand({ evaluatorId: evaluatorIdFromArn(input.knownPhysicalId) }));
|
|
38195
|
+
} catch (err) {
|
|
38196
|
+
if (err instanceof ResourceNotFoundException$6) return null;
|
|
38197
|
+
throw err;
|
|
38198
|
+
}
|
|
38199
|
+
const evaluatorArn = isArn ? input.knownPhysicalId : response.evaluatorArn;
|
|
38200
|
+
if (!evaluatorArn) return null;
|
|
37944
38201
|
return {
|
|
37945
|
-
physicalId:
|
|
37946
|
-
attributes: {
|
|
37947
|
-
EvaluatorArn:
|
|
37948
|
-
EvaluatorId: response.evaluatorId ?? input.knownPhysicalId
|
|
37949
|
-
|
|
38202
|
+
physicalId: evaluatorArn,
|
|
38203
|
+
attributes: definedAttributes({
|
|
38204
|
+
EvaluatorArn: evaluatorArn,
|
|
38205
|
+
EvaluatorId: response.evaluatorId ?? evaluatorIdFromArn(input.knownPhysicalId),
|
|
38206
|
+
Status: response.status,
|
|
38207
|
+
CreatedAt: response.createdAt?.toISOString()
|
|
38208
|
+
})
|
|
37950
38209
|
};
|
|
37951
38210
|
}
|
|
37952
38211
|
};
|
|
@@ -40340,6 +40599,30 @@ const LOAD_BALANCER_ATTRIBUTE_DEFAULTS = {
|
|
|
40340
40599
|
/** @see LOAD_BALANCER_ATTRIBUTE_DEFAULTS — same rule, Listener key table. */
|
|
40341
40600
|
const LISTENER_ATTRIBUTE_DEFAULTS = { "routing.http.response.server.enabled": "true" };
|
|
40342
40601
|
/**
|
|
40602
|
+
* The attribute map a load balancer records, shared by `create()` and
|
|
40603
|
+
* `import()` (issue #3627).
|
|
40604
|
+
*/
|
|
40605
|
+
function loadBalancerAttributes(lb, lbArn) {
|
|
40606
|
+
return definedAttributes({
|
|
40607
|
+
DNSName: lb.DNSName,
|
|
40608
|
+
CanonicalHostedZoneID: lb.CanonicalHostedZoneId,
|
|
40609
|
+
LoadBalancerArn: lbArn,
|
|
40610
|
+
LoadBalancerFullName: lbArn.split("/").slice(1).join("/"),
|
|
40611
|
+
LoadBalancerName: lb.LoadBalancerName
|
|
40612
|
+
});
|
|
40613
|
+
}
|
|
40614
|
+
/**
|
|
40615
|
+
* The attribute map a target group records, shared by `create()`,
|
|
40616
|
+
* `update()` and `import()` (issue #3627).
|
|
40617
|
+
*/
|
|
40618
|
+
function targetGroupAttributes(tg, tgArn) {
|
|
40619
|
+
return definedAttributes({
|
|
40620
|
+
TargetGroupArn: tgArn,
|
|
40621
|
+
TargetGroupFullName: tgArn.split(":").pop(),
|
|
40622
|
+
TargetGroupName: tg.TargetGroupName
|
|
40623
|
+
});
|
|
40624
|
+
}
|
|
40625
|
+
/**
|
|
40343
40626
|
* AWS ELBv2 Provider
|
|
40344
40627
|
*
|
|
40345
40628
|
* Implements resource provisioning for ELBv2 resources:
|
|
@@ -40597,13 +40880,7 @@ var ELBv2Provider = class {
|
|
|
40597
40880
|
}
|
|
40598
40881
|
return {
|
|
40599
40882
|
physicalId: lbArn,
|
|
40600
|
-
attributes:
|
|
40601
|
-
DNSName: lb.DNSName,
|
|
40602
|
-
CanonicalHostedZoneID: lb.CanonicalHostedZoneId,
|
|
40603
|
-
LoadBalancerArn: lbArn,
|
|
40604
|
-
LoadBalancerFullName: lbArn.split("/").slice(1).join("/"),
|
|
40605
|
-
LoadBalancerName: lb.LoadBalancerName
|
|
40606
|
-
}
|
|
40883
|
+
attributes: loadBalancerAttributes(lb, lbArn)
|
|
40607
40884
|
};
|
|
40608
40885
|
} catch (error) {
|
|
40609
40886
|
const cause = error instanceof Error ? error : void 0;
|
|
@@ -40840,11 +41117,7 @@ var ELBv2Provider = class {
|
|
|
40840
41117
|
}
|
|
40841
41118
|
return {
|
|
40842
41119
|
physicalId: tgArn,
|
|
40843
|
-
attributes:
|
|
40844
|
-
TargetGroupArn: tgArn,
|
|
40845
|
-
TargetGroupFullName: tgArn.split(":").pop()?.replace("targetgroup/", ""),
|
|
40846
|
-
TargetGroupName: tg.TargetGroupName
|
|
40847
|
-
}
|
|
41120
|
+
attributes: targetGroupAttributes(tg, tgArn)
|
|
40848
41121
|
};
|
|
40849
41122
|
} catch (error) {
|
|
40850
41123
|
const cause = error instanceof Error ? error : void 0;
|
|
@@ -40922,11 +41195,7 @@ var ELBv2Provider = class {
|
|
|
40922
41195
|
return {
|
|
40923
41196
|
physicalId,
|
|
40924
41197
|
wasReplaced: false,
|
|
40925
|
-
attributes: {
|
|
40926
|
-
TargetGroupArn: physicalId,
|
|
40927
|
-
TargetGroupFullName: physicalId.split(":").pop()?.replace("targetgroup/", ""),
|
|
40928
|
-
TargetGroupName: tg?.TargetGroupName
|
|
40929
|
-
}
|
|
41198
|
+
attributes: targetGroupAttributes(tg ?? {}, physicalId)
|
|
40930
41199
|
};
|
|
40931
41200
|
} catch (error) {
|
|
40932
41201
|
const cause = error instanceof Error ? error : void 0;
|
|
@@ -41587,10 +41856,10 @@ var ELBv2Provider = class {
|
|
|
41587
41856
|
}
|
|
41588
41857
|
async importLoadBalancer(input) {
|
|
41589
41858
|
if (input.knownPhysicalId) try {
|
|
41590
|
-
const
|
|
41591
|
-
return
|
|
41592
|
-
physicalId:
|
|
41593
|
-
attributes:
|
|
41859
|
+
const lb = (await this.getClient().send(new DescribeLoadBalancersCommand({ LoadBalancerArns: [input.knownPhysicalId] }))).LoadBalancers?.[0];
|
|
41860
|
+
return lb?.LoadBalancerArn ? {
|
|
41861
|
+
physicalId: lb.LoadBalancerArn,
|
|
41862
|
+
attributes: loadBalancerAttributes(lb, lb.LoadBalancerArn)
|
|
41594
41863
|
} : null;
|
|
41595
41864
|
} catch (err) {
|
|
41596
41865
|
if (this.isNotFoundError(err)) return null;
|
|
@@ -41600,10 +41869,10 @@ var ELBv2Provider = class {
|
|
|
41600
41869
|
}
|
|
41601
41870
|
async importTargetGroup(input) {
|
|
41602
41871
|
if (input.knownPhysicalId) try {
|
|
41603
|
-
const
|
|
41604
|
-
return
|
|
41605
|
-
physicalId:
|
|
41606
|
-
attributes:
|
|
41872
|
+
const tg = (await this.getClient().send(new DescribeTargetGroupsCommand({ TargetGroupArns: [input.knownPhysicalId] }))).TargetGroups?.[0];
|
|
41873
|
+
return tg?.TargetGroupArn ? {
|
|
41874
|
+
physicalId: tg.TargetGroupArn,
|
|
41875
|
+
attributes: targetGroupAttributes(tg, tg.TargetGroupArn)
|
|
41607
41876
|
} : null;
|
|
41608
41877
|
} catch (err) {
|
|
41609
41878
|
if (this.isNotFoundError(err)) return null;
|
|
@@ -49306,10 +49575,14 @@ var ServiceDiscoveryProvider = class ServiceDiscoveryProvider {
|
|
|
49306
49575
|
}
|
|
49307
49576
|
async importServiceResource(input) {
|
|
49308
49577
|
if (input.knownPhysicalId) try {
|
|
49309
|
-
await this.getClient().send(new GetServiceCommand({ Id: input.knownPhysicalId }));
|
|
49578
|
+
const resp = await this.getClient().send(new GetServiceCommand({ Id: input.knownPhysicalId }));
|
|
49310
49579
|
return {
|
|
49311
49580
|
physicalId: input.knownPhysicalId,
|
|
49312
|
-
attributes: {
|
|
49581
|
+
attributes: definedAttributes({
|
|
49582
|
+
Id: input.knownPhysicalId,
|
|
49583
|
+
Arn: resp.Service?.Arn,
|
|
49584
|
+
Name: resp.Service?.Name
|
|
49585
|
+
})
|
|
49313
49586
|
};
|
|
49314
49587
|
} catch (err) {
|
|
49315
49588
|
if (err instanceof ServiceNotFound) return null;
|
|
@@ -56618,7 +56891,10 @@ var EFSProvider = class {
|
|
|
56618
56891
|
const ap = (await this.getClient().send(new DescribeAccessPointsCommand({ AccessPointId: input.knownPhysicalId }))).AccessPoints?.[0];
|
|
56619
56892
|
return ap?.AccessPointId ? {
|
|
56620
56893
|
physicalId: ap.AccessPointId,
|
|
56621
|
-
attributes: {
|
|
56894
|
+
attributes: definedAttributes({
|
|
56895
|
+
Arn: ap.AccessPointArn,
|
|
56896
|
+
AccessPointId: ap.AccessPointId
|
|
56897
|
+
})
|
|
56622
56898
|
} : null;
|
|
56623
56899
|
} catch (err) {
|
|
56624
56900
|
if (err instanceof AccessPointNotFound) return null;
|
|
@@ -64395,6 +64671,7 @@ async function runDestroyForStack(stackName, state, ctx) {
|
|
|
64395
64671
|
const regionForState = state.region ?? ctx.baseRegion;
|
|
64396
64672
|
refuseMalformedResourcesForDestroy(state, stackName, regionForState);
|
|
64397
64673
|
refuseMalformedOrphansForDestroy(state, stackName, regionForState);
|
|
64674
|
+
refuseMalformedOrphanRecordsForDestroy(state, stackName, regionForState);
|
|
64398
64675
|
refuseDivergentRecordRegionForDestroy(state, stackName, regionForState, ctx.divergentBodyRegion);
|
|
64399
64676
|
const resourceCount = Object.keys(state.resources).length;
|
|
64400
64677
|
const orphanCount = (state.orphans ?? []).length;
|
|
@@ -64448,6 +64725,7 @@ async function runDestroyForStack(stackName, state, ctx) {
|
|
|
64448
64725
|
if (recheck) {
|
|
64449
64726
|
refuseMalformedResourcesForDestroy(recheck.state, stackName, regionForState);
|
|
64450
64727
|
refuseMalformedOrphansForDestroy(recheck.state, stackName, regionForState);
|
|
64728
|
+
refuseMalformedOrphanRecordsForDestroy(recheck.state, stackName, regionForState);
|
|
64451
64729
|
}
|
|
64452
64730
|
const recheckResources = recheck ? Object.keys(recheck.state.resources).length : 0;
|
|
64453
64731
|
const recheckOrphans = recheck ? (recheck.state.orphans ?? []).length : 0;
|
|
@@ -64472,13 +64750,13 @@ async function runDestroyForStack(stackName, state, ctx) {
|
|
|
64472
64750
|
if (consumers.length > 0) throw new StackHasActiveImportsError(stackName, regionForState, consumers);
|
|
64473
64751
|
}
|
|
64474
64752
|
logger.info(`\nResources to be deleted (${resourceCount}):`);
|
|
64475
|
-
for (const [logicalId, resource] of Object.entries(state.resources)) logger.info(` - ${logicalId} (${resource.resourceType})`);
|
|
64753
|
+
for (const [logicalId, resource] of Object.entries(state.resources)) logger.info(` - ${displaySafe(logicalId)} (${displaySafe(resource.resourceType)})`);
|
|
64476
64754
|
const protectedCount = ctx.removeProtection ? countProtectedResources(state) : 0;
|
|
64477
64755
|
const orphansAtDestroy = state.orphans ?? [];
|
|
64478
64756
|
if (orphansAtDestroy.length > 0) {
|
|
64479
64757
|
logger.info(`\n${orphansAtDestroy.length} resource(s) are still in AWS from an earlier failed deploy. cdkd left them there because their DeletionPolicy is Retain (CDK's RemovalPolicy.RETAIN), and has been tracking them so a later deploy of this stack could adopt them back instead of colliding with their names.`);
|
|
64480
64758
|
logger.info("Destroying this stack deletes that record. The resources stay in AWS, may continue to incur charges, and cdkd will no longer know about them:");
|
|
64481
|
-
for (const entry of orphansAtDestroy) logger.info(` - ${entry.logicalId} (${entry.state.resourceType}) ${entry.state.physicalId}`);
|
|
64759
|
+
for (const entry of orphansAtDestroy) logger.info(` - ${displaySafe(entry.logicalId)} (${displaySafe(entry.state.resourceType)}) ${displaySafe(entry.state.physicalId)}`);
|
|
64482
64760
|
}
|
|
64483
64761
|
if (!ctx.skipConfirmation) {
|
|
64484
64762
|
if (process.stdin.isTTY !== true) throw new CdkdError(`The destroy confirmation prompt for stack "${stackName}" cannot run in a non-interactive environment. Pass --yes / -y to confirm the destroy (cdkd destroy also accepts -f / --force), or run the command from a real terminal.`, "NON_INTERACTIVE_CONFIRM");
|
|
@@ -65158,7 +65436,7 @@ var NestedStackProvider = class {
|
|
|
65158
65436
|
const ctx = this.requireContext();
|
|
65159
65437
|
this.requireDeployContext(ctx, "create");
|
|
65160
65438
|
const childTemplatePath = ctx.nestedTemplates[logicalId];
|
|
65161
|
-
if (!childTemplatePath) throw new Error(`Nested template file not found for AWS::CloudFormation::Stack
|
|
65439
|
+
if (!childTemplatePath) throw new Error(`Nested template file not found for AWS::CloudFormation::Stack ${displayIdent(logicalId)} under parent ${displayStackName(ctx.parentStackName)}. Verify the synth output emits Metadata['aws:asset:path'] on this resource (CDK 2.x cdk.NestedStack does so by default).`);
|
|
65162
65440
|
this.refuseMalformedNestedTemplateTree(ctx, logicalId, childTemplatePath);
|
|
65163
65441
|
const { template: childTemplate, grandchildTemplates } = this.readChildTemplate(childTemplatePath, ctx.assetRedirect);
|
|
65164
65442
|
const childStackName = this.deriveChildStackName(ctx.parentStackName, logicalId);
|
|
@@ -65178,7 +65456,7 @@ var NestedStackProvider = class {
|
|
|
65178
65456
|
const ctx = this.requireContext();
|
|
65179
65457
|
this.requireDeployContext(ctx, "update");
|
|
65180
65458
|
const childTemplatePath = ctx.nestedTemplates[logicalId];
|
|
65181
|
-
if (!childTemplatePath) throw new Error(`Nested template file not found for AWS::CloudFormation::Stack
|
|
65459
|
+
if (!childTemplatePath) throw new Error(`Nested template file not found for AWS::CloudFormation::Stack ${displayIdent(logicalId)} on update.`);
|
|
65182
65460
|
this.refuseMalformedNestedTemplateTree(ctx, logicalId, childTemplatePath);
|
|
65183
65461
|
const { template: childTemplate, grandchildTemplates } = this.readChildTemplate(childTemplatePath, ctx.assetRedirect);
|
|
65184
65462
|
const childStackName = this.deriveChildStackName(ctx.parentStackName, logicalId);
|
|
@@ -65250,7 +65528,7 @@ var NestedStackProvider = class {
|
|
|
65250
65528
|
}
|
|
65251
65529
|
}
|
|
65252
65530
|
async getAttribute(_physicalId, _resourceType, attributeName) {
|
|
65253
|
-
throw new Error(`AWS::CloudFormation::Stack: attribute
|
|
65531
|
+
throw new Error(`AWS::CloudFormation::Stack: attribute ${displayIdent(attributeName)} is not in the recorded Outputs map. Only 'Outputs.<Key>' references to declared Output names on the child template are supported.`);
|
|
65254
65532
|
}
|
|
65255
65533
|
async runChildDeploy(parentCtx, logicalId, childStackName, childRegion, childTemplate, childParameters, grandchildTemplates) {
|
|
65256
65534
|
const inheritedSecrets = getCurrentResourceSecrets();
|
|
@@ -65301,7 +65579,7 @@ var NestedStackProvider = class {
|
|
|
65301
65579
|
*/
|
|
65302
65580
|
async readChildOutputsAsAttributes(ctx, childStackName, childRegion) {
|
|
65303
65581
|
const childStateData = await ctx.stateBackend.getState(childStackName, childRegion);
|
|
65304
|
-
if (!childStateData) throw new Error(`Child stack state
|
|
65582
|
+
if (!childStateData) throw new Error(`Child stack state ${displayStackName(childStackName)} not found after deploy — NestedStackProvider invariant violated.`);
|
|
65305
65583
|
refuseMalformedNestedChildOutputs(childStateData.state, childStackName, childRegion);
|
|
65306
65584
|
const attributes = this.buildOutputsAttributes(childStateData.state.outputs ?? {});
|
|
65307
65585
|
const noEchoAttributeNames = [];
|
|
@@ -65404,7 +65682,7 @@ var NestedStackProvider = class {
|
|
|
65404
65682
|
* points at `[2]` rather than at the whole parameter.
|
|
65405
65683
|
*/
|
|
65406
65684
|
refuseNonScalarParameter(k, offender, where) {
|
|
65407
|
-
throw new Error(`NestedStackProvider: child Parameter
|
|
65685
|
+
throw new Error(`NestedStackProvider: child Parameter ${displayIdent(k)}${where} resolved to a non-scalar value (type=${offender === null ? "null" : typeof offender}). Parameters must be scalars (string / number / boolean), or an ARRAY of them from a list-typed parameter, by the time they reach the provider — an unresolved intrinsic here means IntrinsicFunctionResolver upstream did not handle the value, which is a bug. Surface the unresolved input rather than silently coercing to '[object Object]'.`);
|
|
65408
65686
|
}
|
|
65409
65687
|
/**
|
|
65410
65688
|
* The child template as the child engine deploys it, plus the grandchild
|
|
@@ -65447,9 +65725,9 @@ var NestedStackProvider = class {
|
|
|
65447
65725
|
const dir = path.dirname(childTemplatePath);
|
|
65448
65726
|
const result = Object.create(null);
|
|
65449
65727
|
for (const { logicalId: grandLogicalId, assetPath } of listNestedTemplateRows(childTemplate)) {
|
|
65450
|
-
if (isAbsoluteCrossPlatform$1(assetPath)) throw markNonRetryable(/* @__PURE__ */ new Error(`NestedStackProvider: nested-stack
|
|
65728
|
+
if (isAbsoluteCrossPlatform$1(assetPath)) throw markNonRetryable(/* @__PURE__ */ new Error(`NestedStackProvider: nested-stack ${displayIdent(grandLogicalId)} has Metadata['aws:asset:path']=${displayAssemblyPath(assetPath)} which is absolute. CDK emits relative asset paths for nested templates; an absolute path indicates the synth output was hand-modified or generated by a non-CDK toolchain. Refusing to load.`));
|
|
65451
65729
|
const resolved = resolveAssemblyPath(dir, assetPath);
|
|
65452
|
-
if (!resolved.contained) throw markNonRetryable(/* @__PURE__ */ new Error(`NestedStackProvider: nested-stack
|
|
65730
|
+
if (!resolved.contained) throw markNonRetryable(/* @__PURE__ */ new Error(`NestedStackProvider: nested-stack ${displayIdent(grandLogicalId)} has Metadata['aws:asset:path']=${displayAssemblyPath(assetPath)} which ${renderAssemblyPathEscape(resolved, dir)}`));
|
|
65453
65731
|
result[grandLogicalId] = resolved.path;
|
|
65454
65732
|
}
|
|
65455
65733
|
return result;
|
|
@@ -68566,13 +68844,10 @@ async function computeStackDiff(currentState, template, region, stackName, state
|
|
|
68566
68844
|
let stateForDiff = currentState;
|
|
68567
68845
|
const unreadableOrphans = [];
|
|
68568
68846
|
if (currentState.orphans?.length && options.previewOrphanAdoption) {
|
|
68569
|
-
const
|
|
68570
|
-
|
|
68571
|
-
|
|
68572
|
-
|
|
68573
|
-
return false;
|
|
68574
|
-
});
|
|
68575
|
-
if (unreadableOrphans.length > 0) logger.warn(malformedOrphanRecordsWarning(stackName, region, unreadableOrphans));
|
|
68847
|
+
for (const id of unpreviewableOrphanRecords(currentState)) unreadableOrphans.push(id);
|
|
68848
|
+
const readableOrphans = previewableOrphanRecords(currentState);
|
|
68849
|
+
if (unreadableOrphans.length > 0) logger.warn(malformedOrphanRecordsWarning(stackName, region, unreadableOrphans, false));
|
|
68850
|
+
let reportedByTheAdoptedPropertiesArm = [];
|
|
68576
68851
|
const plan = await options.previewOrphanAdoption({
|
|
68577
68852
|
...currentState,
|
|
68578
68853
|
orphans: readableOrphans
|
|
@@ -68589,11 +68864,18 @@ async function computeStackDiff(currentState, template, region, stackName, state
|
|
|
68589
68864
|
}
|
|
68590
68865
|
};
|
|
68591
68866
|
const tornAdopted = repairMalformedResourcePropertiesForReadOnly(stateForDiff);
|
|
68867
|
+
reportedByTheAdoptedPropertiesArm = tornAdopted;
|
|
68592
68868
|
if (tornAdopted.length > 0) {
|
|
68593
68869
|
logger.warn(malformedResourcePropertiesWarning(stackName, region, tornAdopted));
|
|
68594
68870
|
deployRefusals.push(deployRefusesPropertiesReason(tornAdopted));
|
|
68595
68871
|
}
|
|
68596
68872
|
}
|
|
68873
|
+
const alreadyReported = new Set(reportedByTheAdoptedPropertiesArm);
|
|
68874
|
+
const previewedRowsTheDeployRefuses = readableOrphans.filter((record) => !isReadableOrphanRecord(record)).map((record) => record.logicalId).filter((logicalId) => !alreadyReported.has(logicalId));
|
|
68875
|
+
if (previewedRowsTheDeployRefuses.length > 0) {
|
|
68876
|
+
logger.warn(malformedOrphanRowsKeptWarning(stackName, region, previewedRowsTheDeployRefuses));
|
|
68877
|
+
deployRefusals.push(deployRefusesOrphanRowsReason(previewedRowsTheDeployRefuses));
|
|
68878
|
+
}
|
|
68597
68879
|
}
|
|
68598
68880
|
const changes = await diffCalculator.calculateDiff(stateForDiff, effectiveTemplate, resolveFn, canonicalizeProperties);
|
|
68599
68881
|
const changedLogicalIds = new Set([...changes.values()].filter((c) => c.changeType !== "NO_CHANGE").map((c) => c.logicalId));
|
|
@@ -69869,7 +70151,7 @@ async function scrubCommand(stacks, options) {
|
|
|
69869
70151
|
} else if (scrubbed.secretBearingKeys === 0 && scrubbed.unverifiableReads === 0 && scrubbed.unverifiableLeaves === 0 && indexConverged === 0) logger.info(`No plaintext secrets found in ${stack.stackName}`);
|
|
69870
70152
|
if (scrubbed.malformedResources) malformedRecords.push(stack.stackName);
|
|
69871
70153
|
if (scrubbed.malformedOutputs) malformedOutputRecords.push(stack.stackName);
|
|
69872
|
-
if (scrubbed.malformedOrphans) malformedOrphanRecords.push(stack.stackName);
|
|
70154
|
+
if (scrubbed.malformedOrphans || scrubbed.malformedOrphanRows) malformedOrphanRecords.push(stack.stackName);
|
|
69873
70155
|
if (scrubbed.unverifiableLeaves > 0) {
|
|
69874
70156
|
totalStacksWithUnverifiableLeaves++;
|
|
69875
70157
|
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.`);
|
|
@@ -70565,7 +70847,7 @@ function malformedRecordsAuditedError(stackNames, outputStackNames, orphanStackN
|
|
|
70565
70847
|
const parts = [];
|
|
70566
70848
|
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.`);
|
|
70567
70849
|
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.`);
|
|
70568
|
-
if (orphanStackNames.length > 0) parts.push(`${orphanStackNames.length} stack(s) were audited with an
|
|
70850
|
+
if (orphanStackNames.length > 0) parts.push(`${orphanStackNames.length} stack(s) were audited with an INCOMPLETE orphan list because their state record has no readable 'orphans' list, or a record inside it that no reader can use: ${safeNames(orphanStackNames)}. Whichever it was, the warning above names it per stack. Nothing is known about the resources those records describe — resources an earlier failed deploy may have left live in AWS — so this run cannot certify them clean.`);
|
|
70569
70851
|
return new ScrubRefusalError(`${parts.join(" ")} See the warnings above for the record to inspect.`, STATE_RESOURCES_MALFORMED);
|
|
70570
70852
|
}
|
|
70571
70853
|
/**
|
|
@@ -71977,9 +72259,23 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
71977
72259
|
const outputSecrets = /* @__PURE__ */ new Map();
|
|
71978
72260
|
/**
|
|
71979
72261
|
* Needles derived from each rollback-orphan record's OWN recorded bag
|
|
71980
|
-
* (issue go-to-k/cdkd#2943)
|
|
71981
|
-
*
|
|
71982
|
-
*
|
|
72262
|
+
* (issue go-to-k/cdkd#2943) — per-record for the same reason
|
|
72263
|
+
* `perResourceSecrets` is per-resource: one record's secret must not rewrite
|
|
72264
|
+
* another's coinciding literal.
|
|
72265
|
+
*
|
|
72266
|
+
* Keyed by the row's INDEX in `orphans`, never by its `logicalId`
|
|
72267
|
+
* (go-to-k/cdkd#3500 security review). Two rows sharing an id are a MALFORMED
|
|
72268
|
+
* record — no cdkd writer produces one, since `orphansAfterRollback` keeps one
|
|
72269
|
+
* row per id — and both arms of this command meet it before this map is read:
|
|
72270
|
+
* a real run refuses the record and `--dry-run` drops every such row
|
|
72271
|
+
* (go-to-k/cdkd#3643). The index keying stays as defense in depth, because it
|
|
72272
|
+
* is still the only identity that cannot collide: on an id key the second row's
|
|
72273
|
+
* empty map REPLACED the first row's filled one. Both halves broke: the first
|
|
72274
|
+
* row's needles left the union that the rewrite and the error boundary read, and
|
|
72275
|
+
* its own lookup returned the OTHER row's map, so where two rows resolve one
|
|
72276
|
+
* plaintext through different expressions the wrong expression was written. The
|
|
72277
|
+
* index is the only identity the collecting loop and the rewrite can agree on,
|
|
72278
|
+
* since both walk `state.orphans` in order and neither reorders it.
|
|
71983
72279
|
*/
|
|
71984
72280
|
const orphanSecrets = /* @__PURE__ */ new Map();
|
|
71985
72281
|
const prePassFindings = {
|
|
@@ -72069,12 +72365,22 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
72069
72365
|
}
|
|
72070
72366
|
} else if (!hasReadableOutputs(state)) throw new ScrubRefusalError(malformedOutputsRefusalMessage(stack.stackName, region), STATE_RESOURCES_MALFORMED);
|
|
72071
72367
|
let malformedOrphans;
|
|
72368
|
+
let malformedOrphanRows;
|
|
72072
72369
|
if (opts.dryRun) {
|
|
72073
72370
|
if (repairMalformedOrphansForReadOnly(state)) {
|
|
72074
72371
|
malformedOrphans = true;
|
|
72075
72372
|
logger.warn(malformedOrphansWarning(stack.stackName, region));
|
|
72076
72373
|
}
|
|
72374
|
+
const droppedRows = repairMalformedOrphanRecordsForReadOnly(state);
|
|
72375
|
+
if (droppedRows.length > 0) {
|
|
72376
|
+
malformedOrphanRows = true;
|
|
72377
|
+
logger.warn(malformedOrphanRecordsWarning(stack.stackName, region, droppedRows, true));
|
|
72378
|
+
}
|
|
72077
72379
|
} else if (!hasReadableOrphans(state)) throw new ScrubRefusalError(malformedOrphansRefusalMessage(stack.stackName, region), STATE_RESOURCES_MALFORMED);
|
|
72380
|
+
else {
|
|
72381
|
+
const unreadableRows = unreadableOrphanRecords(state);
|
|
72382
|
+
if (unreadableRows.length > 0) throw new ScrubRefusalError(malformedOrphanRecordsRefusalMessage(stack.stackName, region, unreadableRows), STATE_RESOURCES_MALFORMED);
|
|
72383
|
+
}
|
|
72078
72384
|
const perResourceTemplateProps = /* @__PURE__ */ new Map();
|
|
72079
72385
|
const outputsTemplateSource = {};
|
|
72080
72386
|
const resolvers = new ScrubResolvers(region);
|
|
@@ -72157,9 +72463,9 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
72157
72463
|
}
|
|
72158
72464
|
perResourceTemplateProps.set(logicalId, templateResource.Properties);
|
|
72159
72465
|
}
|
|
72160
|
-
for (const record of state.orphans ?? []) {
|
|
72466
|
+
for (const [orphanIndex, record] of (state.orphans ?? []).entries()) {
|
|
72161
72467
|
const recordedSecretValues = /* @__PURE__ */ new Map();
|
|
72162
|
-
orphanSecrets.set(
|
|
72468
|
+
orphanSecrets.set(String(orphanIndex), recordedSecretValues);
|
|
72163
72469
|
const resolveInput = await pinCrossRegionSecrets({
|
|
72164
72470
|
properties: record.state.properties,
|
|
72165
72471
|
attributes: record.state.attributes ?? {},
|
|
@@ -72292,6 +72598,7 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
72292
72598
|
...malformedResources ? { malformedResources } : {},
|
|
72293
72599
|
...malformedOutputs ? { malformedOutputs } : {},
|
|
72294
72600
|
...malformedOrphans ? { malformedOrphans } : {},
|
|
72601
|
+
...malformedOrphanRows ? { malformedOrphanRows } : {},
|
|
72295
72602
|
outputs: state.outputs,
|
|
72296
72603
|
exportNameDisplay: (name) => secretSafeKeyDisplay(name, outputSecrets)
|
|
72297
72604
|
};
|
|
@@ -72310,8 +72617,8 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
72310
72617
|
if (JSON.stringify(scrubbed) !== JSON.stringify(record)) recordsChanged++;
|
|
72311
72618
|
newResources[logicalId] = scrubbed;
|
|
72312
72619
|
}
|
|
72313
|
-
const newOrphans = (state.orphans ?? []).map((record) => {
|
|
72314
|
-
const own = orphanSecrets.get(
|
|
72620
|
+
const newOrphans = (state.orphans ?? []).map((record, orphanIndex) => {
|
|
72621
|
+
const own = orphanSecrets.get(String(orphanIndex));
|
|
72315
72622
|
const needles = new Map(allRecordedSecrets(outputSecrets, perResourceSecrets, orphanSecrets));
|
|
72316
72623
|
for (const [plaintext, expression] of own ?? []) needles.set(plaintext, expression);
|
|
72317
72624
|
if (needles.size === 0) return record;
|
|
@@ -72371,6 +72678,7 @@ async function scrubStack(stack, region, stateBackend, lockManager, opts) {
|
|
|
72371
72678
|
...malformedResources ? { malformedResources } : {},
|
|
72372
72679
|
...malformedOutputs ? { malformedOutputs } : {},
|
|
72373
72680
|
...malformedOrphans ? { malformedOrphans } : {},
|
|
72681
|
+
...malformedOrphanRows ? { malformedOrphanRows } : {},
|
|
72374
72682
|
outputs: newOutputs,
|
|
72375
72683
|
exportNameDisplay: (name) => secretSafeKeyDisplay(name, outputSecrets)
|
|
72376
72684
|
};
|
|
@@ -82939,7 +83247,7 @@ async function stateDestroyCommand(stackArgs, options) {
|
|
|
82939
83247
|
* Create the `state destroy` subcommand.
|
|
82940
83248
|
*/
|
|
82941
83249
|
function createStateDestroyCommand() {
|
|
82942
|
-
const cmd = new Command("destroy").description("Destroy a stack's AWS resources and remove its state record without requiring the CDK app. For removing only the state record (keeping AWS resources intact), use 'cdkd state orphan'.").argument("[stacks...]", "Stack name(s) to destroy (physical CloudFormation names)").option("--all", "Destroy every stack in the state bucket", false).option("--remove-protection",
|
|
83250
|
+
const cmd = new Command("destroy").description("Destroy a stack's AWS resources and remove its state record without requiring the CDK app. For removing only the state record (keeping AWS resources intact), use 'cdkd state orphan'.").argument("[stacks...]", "Stack name(s) to destroy (physical CloudFormation names)").option("--all", "Destroy every stack in the state bucket", false).option("--remove-protection", `Bypass deletion protection on protected resources by flipping the per-resource protection flag off in-place before delete. Covers ${removeProtectionTypeList()}.`, false).addOption(stackRegionOption$1()).addHelpText("after", [
|
|
82943
83251
|
"",
|
|
82944
83252
|
"Examples:",
|
|
82945
83253
|
" cdkd state destroy MyStack",
|
|
@@ -83887,6 +84195,7 @@ async function rollbackCommand(stackArg, options) {
|
|
|
83887
84195
|
const baseState = stateData.state;
|
|
83888
84196
|
refuseMalformedState(baseState, stackName, region);
|
|
83889
84197
|
refuseMalformedOrphans(baseState, stackName, region);
|
|
84198
|
+
refuseMalformedOrphanRecords(baseState, stackName, region);
|
|
83890
84199
|
const stateResources = { ...baseState.resources };
|
|
83891
84200
|
const mintedOrphans = [];
|
|
83892
84201
|
const orphanLogicalIds = new Set(options.orphan ?? []);
|
|
@@ -84546,23 +84855,45 @@ function createEventsPruneCommand() {
|
|
|
84546
84855
|
* The two dual-stack forms carry a FIXED suffix, so their check is that literal
|
|
84547
84856
|
* rather than the region's partition suffix — the TIGHTEST available check for
|
|
84548
84857
|
* them, not a relaxation: `on.aws` is an AWS-owned domain, so unlike a captured
|
|
84549
|
-
* suffix it cannot be substituted by a host someone else owns.
|
|
84550
|
-
*
|
|
84551
|
-
*
|
|
84552
|
-
*
|
|
84553
|
-
*
|
|
84554
|
-
*
|
|
84555
|
-
|
|
84858
|
+
* suffix it cannot be substituted by a host someone else owns.
|
|
84859
|
+
*
|
|
84860
|
+
* The three non-plain forms are accepted only for a region in the `aws` /
|
|
84861
|
+
* `aws-us-gov` partitions (issue #3670):
|
|
84862
|
+
*
|
|
84863
|
+
* - `on.aws` is the dual-stack DNS of those two partitions; the others serve
|
|
84864
|
+
* dual-stack under their own suffixes, which this table does not list.
|
|
84865
|
+
* - AWS's own endpoint data (botocore `endpoints.json`, service `ecr`) carries
|
|
84866
|
+
* the `fips-dkr-<region>` registry endpoints in those two partitions only;
|
|
84867
|
+
* `aws-cn`, the ISO partitions and `aws-eusc` list none. So
|
|
84868
|
+
* `<acct>.dkr.ecr-fips.cn-north-1.amazonaws.com.cn` is not a host AWS serves
|
|
84869
|
+
* either, although its suffix is the region's own.
|
|
84870
|
+
*
|
|
84871
|
+
* Such a host is refused rather than handed a `docker login`. An earlier
|
|
84872
|
+
* revision accepted `on.aws` for any region, reasoning that under-accepting
|
|
84873
|
+
* repeats the issue #1764 failure; that trade stops paying once the pull path
|
|
84874
|
+
* logs in to whatever host the reference names. The partition, not the six
|
|
84875
|
+
* FIPS regions, is the unit, so a new FIPS region in those partitions is not
|
|
84876
|
+
* refused before AWS documents it.
|
|
84877
|
+
*
|
|
84878
|
+
* `cdkd gc` builds its pattern from the LABELS and suffixes only and ignores
|
|
84879
|
+
* `partitions`, deliberately: over-matching there only ever KEEPS an asset.
|
|
84880
|
+
*/
|
|
84881
|
+
const COMMERCIAL_AND_GOVCLOUD = ["aws", "aws-us-gov"];
|
|
84556
84882
|
const ECR_REGISTRY_HOST_FORMS = [
|
|
84557
84883
|
{ labels: "dkr.ecr" },
|
|
84558
|
-
{
|
|
84884
|
+
{
|
|
84885
|
+
labels: "dkr.ecr-fips",
|
|
84886
|
+
partitions: COMMERCIAL_AND_GOVCLOUD
|
|
84887
|
+
},
|
|
84559
84888
|
{
|
|
84560
84889
|
labels: "dkr-ecr",
|
|
84561
|
-
fixedUrlSuffix: "on.aws"
|
|
84890
|
+
fixedUrlSuffix: "on.aws",
|
|
84891
|
+
partitions: COMMERCIAL_AND_GOVCLOUD
|
|
84562
84892
|
},
|
|
84563
84893
|
{
|
|
84564
84894
|
labels: "dkr-ecr-fips",
|
|
84565
|
-
fixedUrlSuffix: "on.aws"
|
|
84895
|
+
fixedUrlSuffix: "on.aws",
|
|
84896
|
+
partitions: COMMERCIAL_AND_GOVCLOUD
|
|
84566
84897
|
}
|
|
84567
84898
|
];
|
|
84568
84899
|
/**
|
|
@@ -84686,6 +85017,17 @@ function ecrRegistryHostPattern(segments) {
|
|
|
84686
85017
|
* MESSAGE was written for the #1764 partition-gap case and now over-claims for a
|
|
84687
85018
|
* form/suffix mispairing (`amazonaws.com` IS `us-east-1`'s partition suffix).
|
|
84688
85019
|
* `src/local/ecs-task-resolver.ts` owns that wording; recorded on issue #1846.
|
|
85020
|
+
*
|
|
85021
|
+
* `<r>` above is a commercial region. Issue #3670 then scoped the three
|
|
85022
|
+
* non-plain forms to the `aws` / `aws-us-gov` partitions, flipping more
|
|
85023
|
+
* verdicts: `<a>.dkr-ecr[-fips].<r>.on.aws` and `<a>.dkr.ecr-fips.<r>.S` for an
|
|
85024
|
+
* `aws-cn`, ISO or `aws-eusc` `<r>` went from `p=ok d=f` to `p=und d=TRUE`, a
|
|
85025
|
+
* form / partition mispairing reported like the form / suffix ones. The same
|
|
85026
|
+
* issue added the region-SHAPE guard ({@link AWS_REGION_ID}), which refuses a
|
|
85027
|
+
* service-name "region" such as `s3` at both entry points. That guard also
|
|
85028
|
+
* flips the diagnostic the other way for such a label: `<a>.dkr.ecr.s3.F` went
|
|
85029
|
+
* from `p=und d=TRUE` to `p=und d=f`. A region-shaped label no partition knows
|
|
85030
|
+
* (`nz-north-1`) went from `p=ok d=f` to `p=und d=TRUE`.
|
|
84689
85031
|
*/
|
|
84690
85032
|
const ECR_URI_HOST_REGEX = new RegExp(`^(\\d{12})\\.(${ECR_HOST_FORMS_LONGEST_FIRST.map((form) => escapeRegExp(form.labels)).join("|")})\\.([^.]+)\\.([^/]+)/`, "i");
|
|
84691
85033
|
/**
|
|
@@ -84746,6 +85088,54 @@ const CANONICAL_REGION_SEGMENT = /^[A-Za-z0-9][A-Za-z0-9-]*$/;
|
|
|
84746
85088
|
*/
|
|
84747
85089
|
const CANONICAL_URL_SUFFIX = /^[A-Za-z0-9][A-Za-z0-9.-]*$/;
|
|
84748
85090
|
/**
|
|
85091
|
+
* `<letters>(-<letters or digits>)+-<number>`: the generic shape every AWS
|
|
85092
|
+
* region id has had. A label matching it but not {@link AWS_REGION_ID} is a
|
|
85093
|
+
* region cdkd does not know yet, reported by the diagnostic rather than
|
|
85094
|
+
* silenced; `s3`, `lambda-url` and `s3-external-1` do not match it (the first
|
|
85095
|
+
* segment must be letters only).
|
|
85096
|
+
*/
|
|
85097
|
+
const GENERIC_REGION_SHAPE = /^[a-z]+(?:-[a-z0-9]+)+-\d+$/;
|
|
85098
|
+
/**
|
|
85099
|
+
* The SHAPE of an AWS region id, tested on the folded region AFTER the charset
|
|
85100
|
+
* guard above (issue #3670).
|
|
85101
|
+
*
|
|
85102
|
+
* The charset guard admits any `[A-Za-z0-9-]` label, so a SERVICE-name label
|
|
85103
|
+
* parsed as a region: `<acct>.dkr.ecr.s3.amazonaws.com` yielded the region
|
|
85104
|
+
* `s3`, whose partition falls back to commercial, so the suffix matched and the
|
|
85105
|
+
* host became a `docker login` target. Only TLS stopped the token there. A
|
|
85106
|
+
* region id is one of the partitions' region patterns, so anything else is not
|
|
85107
|
+
* a registry host this module recognizes.
|
|
85108
|
+
*
|
|
85109
|
+
* One alternative per partition, transcribed from each partition's
|
|
85110
|
+
* `regionRegex` in AWS's own endpoint data (botocore `partitions.json`, which
|
|
85111
|
+
* `@aws-sdk/util-endpoints` vendors), with `\w+` spelled `[a-z0-9]+`. That is
|
|
85112
|
+
* the same set once the charset guard has refused `_` and the fold has
|
|
85113
|
+
* lower-cased the segment:
|
|
85114
|
+
*
|
|
85115
|
+
* - `aws`: `^(us|eu|ap|sa|ca|me|af|il|mx)-\w+-\d+$`
|
|
85116
|
+
* - `aws-cn`: `^cn-\w+-\d+$`
|
|
85117
|
+
* - `aws-us-gov`: `^us-gov-\w+-\d+$`
|
|
85118
|
+
* - `aws-iso` / `-iso-b` / `-iso-e` / `-iso-f`: `^us-iso-`, `^us-isob-`,
|
|
85119
|
+
* `^eu-isoe-`, `^us-isof-`, each followed by `\w+-\d+`
|
|
85120
|
+
* - `aws-eusc`: `^eusc-(de)-\w+-\d+$`, widened here to any `eusc-<cc>-` country
|
|
85121
|
+
* code for the reason `PARTITION_TABLE` (`src/utils/aws-partition.ts`) gives
|
|
85122
|
+
* for its own broader `eusc-` prefix: a future sovereign-cloud country falling
|
|
85123
|
+
* through is the failure, and no other partition's regions begin `eusc-`.
|
|
85124
|
+
*
|
|
85125
|
+
* A future partition with a new prefix is refused until it is added here, the
|
|
85126
|
+
* same way `derivePartitionAndUrlSuffix` has to learn its suffix.
|
|
85127
|
+
*/
|
|
85128
|
+
const AWS_REGION_ID = new RegExp("^(?:" + [
|
|
85129
|
+
"(?:us|eu|ap|sa|ca|me|af|il|mx)-[a-z0-9]+-\\d+",
|
|
85130
|
+
"cn-[a-z0-9]+-\\d+",
|
|
85131
|
+
"us-gov-[a-z0-9]+-\\d+",
|
|
85132
|
+
"us-iso-[a-z0-9]+-\\d+",
|
|
85133
|
+
"us-isob-[a-z0-9]+-\\d+",
|
|
85134
|
+
"eu-isoe-[a-z0-9]+-\\d+",
|
|
85135
|
+
"us-isof-[a-z0-9]+-\\d+",
|
|
85136
|
+
"eusc-[a-z]+-[a-z0-9]+-\\d+"
|
|
85137
|
+
].join("|") + ")$");
|
|
85138
|
+
/**
|
|
84749
85139
|
* The ONE case-normalization boundary of this module (issue #1786).
|
|
84750
85140
|
*
|
|
84751
85141
|
* DNS is case-INSENSITIVE, so `US-ISO-EAST-1.amazonaws.com` and
|
|
@@ -84790,11 +85180,21 @@ function matchEcrRegistryHost(imageUri) {
|
|
|
84790
85180
|
const form = ECR_HOST_FORM_BY_LABELS.get(m[2].toLowerCase());
|
|
84791
85181
|
if (!form) return void 0;
|
|
84792
85182
|
const region = m[3].toLowerCase();
|
|
85183
|
+
if (!AWS_REGION_ID.test(region)) {
|
|
85184
|
+
if (!GENERIC_REGION_SHAPE.test(region)) return void 0;
|
|
85185
|
+
return {
|
|
85186
|
+
accountId: m[1],
|
|
85187
|
+
region,
|
|
85188
|
+
suffix: m[4].toLowerCase(),
|
|
85189
|
+
expectedSuffix: void 0
|
|
85190
|
+
};
|
|
85191
|
+
}
|
|
85192
|
+
const partition = derivePartitionAndUrlSuffix(region);
|
|
84793
85193
|
return {
|
|
84794
85194
|
accountId: m[1],
|
|
84795
85195
|
region,
|
|
84796
85196
|
suffix: m[4].toLowerCase(),
|
|
84797
|
-
expectedSuffix: (form.fixedUrlSuffix ??
|
|
85197
|
+
expectedSuffix: form.partitions && !form.partitions.includes(partition.partition) ? void 0 : (form.fixedUrlSuffix ?? partition.urlSuffix).toLowerCase()
|
|
84798
85198
|
};
|
|
84799
85199
|
}
|
|
84800
85200
|
/**
|
|
@@ -84824,7 +85224,7 @@ function matchEcrRegistryHost(imageUri) {
|
|
|
84824
85224
|
function parseEcrRegistryHost(imageUri) {
|
|
84825
85225
|
const m = matchEcrRegistryHost(imageUri);
|
|
84826
85226
|
if (!m) return void 0;
|
|
84827
|
-
if (m.suffix !== m.expectedSuffix) return void 0;
|
|
85227
|
+
if (m.expectedSuffix === void 0 || m.suffix !== m.expectedSuffix) return void 0;
|
|
84828
85228
|
return {
|
|
84829
85229
|
accountId: m.accountId,
|
|
84830
85230
|
region: m.region
|
|
@@ -86504,7 +86904,7 @@ async function orphanCommand(pathArgs, options) {
|
|
|
86504
86904
|
const stackInfo = resolved.stack;
|
|
86505
86905
|
const orphanLogicalIds = resolved.logicalIds;
|
|
86506
86906
|
const { region: targetRegion, recordRegion } = await pickStackRegion(stateBackend, stackInfo.stackName, stackInfo.region, options.stackRegion);
|
|
86507
|
-
logger.info(`Target: ${
|
|
86907
|
+
logger.info(`Target: ${displayStackName(stackInfo.stackName)} (${displayIdent(targetRegion)}); orphaning ${orphanLogicalIds.length} resource(s): ${displaySafeList(orphanLogicalIds)}`);
|
|
86508
86908
|
const owner = `${process.env["USER"] || "unknown"}@${process.env["HOSTNAME"] || "host"}:${process.pid}`;
|
|
86509
86909
|
const recovery = {
|
|
86510
86910
|
profile: options.profile,
|
|
@@ -86521,7 +86921,7 @@ async function orphanCommand(pathArgs, options) {
|
|
|
86521
86921
|
}
|
|
86522
86922
|
try {
|
|
86523
86923
|
const stateData = await stateBackend.getState(stackInfo.stackName, targetRegion);
|
|
86524
|
-
if (!stateData) throw new Error(`No state found for stack
|
|
86924
|
+
if (!stateData) throw new Error(`No state found for stack ${displayStackName(stackInfo.stackName)} (${displaySafe(targetRegion, { asciiOnly: true })}). Nothing to orphan. (Did the stack get deployed?)`);
|
|
86525
86925
|
const { state, etag, migrationPending } = stateData;
|
|
86526
86926
|
refuseMalformedState(state, stackInfo.stackName, recordRegion, recovery);
|
|
86527
86927
|
refuseMalformedOutputs(state, stackInfo.stackName, recordRegion, recovery);
|
|
@@ -86532,7 +86932,7 @@ async function orphanCommand(pathArgs, options) {
|
|
|
86532
86932
|
const missing = orphanLogicalIds.filter((id) => !Object.hasOwn(state.resources, id));
|
|
86533
86933
|
if (missing.length > 0) {
|
|
86534
86934
|
const have = displayIdentList(Object.keys(state.resources), ", ");
|
|
86535
|
-
throw new Error(`Resource(s) not in state for stack
|
|
86935
|
+
throw new Error(`Resource(s) not in state for stack ${displayStackName(stackInfo.stackName)} (${displaySafe(targetRegion, { asciiOnly: true })}): ${displayIdentList(missing, ", ")}.\nAvailable logical IDs: ${have}`);
|
|
86536
86936
|
}
|
|
86537
86937
|
const providerRegistry = new ProviderRegistry();
|
|
86538
86938
|
registerAllProviders(providerRegistry);
|
|
@@ -86551,7 +86951,7 @@ async function orphanCommand(pathArgs, options) {
|
|
|
86551
86951
|
return;
|
|
86552
86952
|
}
|
|
86553
86953
|
if (!options.yes && !options.force) {
|
|
86554
|
-
if (!await confirmPrompt$1(`Orphan ${orphanLogicalIds.length} resource(s) from cdkd state for ${
|
|
86954
|
+
if (!await confirmPrompt$1(`Orphan ${orphanLogicalIds.length} resource(s) from cdkd state for ${displayStackName(stackInfo.stackName)} (${displayIdent(targetRegion)})? AWS resources will NOT be deleted.`)) {
|
|
86555
86955
|
logger.info("Orphan cancelled.");
|
|
86556
86956
|
return;
|
|
86557
86957
|
}
|
|
@@ -86560,7 +86960,7 @@ async function orphanCommand(pathArgs, options) {
|
|
|
86560
86960
|
expectedEtag: etag,
|
|
86561
86961
|
...migrationPending && { migrateLegacy: true }
|
|
86562
86962
|
});
|
|
86563
|
-
logger.info(`Orphaned ${orphanLogicalIds.length} resource(s) from state: ${
|
|
86963
|
+
logger.info(`Orphaned ${orphanLogicalIds.length} resource(s) from state: ${displayStackName(stackInfo.stackName)} (${displayIdent(targetRegion)}). AWS resources are still in AWS; cdkd will no longer manage them.`);
|
|
86564
86964
|
} finally {
|
|
86565
86965
|
if (!options.dryRun) await lockManager.releaseLock(stackInfo.stackName, targetRegion).catch((err) => {
|
|
86566
86966
|
logger.warn(`Failed to release lock: ${displayAwsMessage(err instanceof Error ? err.message : String(err))}`);
|
|
@@ -86599,12 +86999,12 @@ function resolveConstructPaths(paths, stacks) {
|
|
|
86599
86999
|
throw new Error(`Construct path '${p}': stack '${head}' not found in synthesized app. Available: ${available}`);
|
|
86600
87000
|
}
|
|
86601
87001
|
if (stack === void 0) stack = candidate;
|
|
86602
|
-
else if (stack.stackName !== candidate.stackName) throw new Error(`All construct paths must reference the same stack. Got
|
|
87002
|
+
else if (stack.stackName !== candidate.stackName) throw new Error(`All construct paths must reference the same stack. Got ${displayStackName(stack.stackName)} and ${displayStackName(candidate.stackName)}. Run 'cdkd orphan' once per stack.`);
|
|
86603
87003
|
const index = buildCdkPathIndex(candidate.template);
|
|
86604
87004
|
const matches = resolveCdkPathToLogicalIds(p, index);
|
|
86605
87005
|
if (matches.length === 0) {
|
|
86606
87006
|
const available = displayIdentList([...index.keys()].sort(), "\n ");
|
|
86607
|
-
throw new Error(`Construct path '${p}' not found in template for stack
|
|
87007
|
+
throw new Error(`Construct path '${p}' not found in template for stack ${displayStackName(candidate.stackName)}.\nAvailable paths:\n ${available}`);
|
|
86608
87008
|
}
|
|
86609
87009
|
for (const { logicalId } of matches) if (!logicalIds.includes(logicalId)) logicalIds.push(logicalId);
|
|
86610
87010
|
}
|
|
@@ -86631,12 +87031,12 @@ async function pickStackRegion(stateBackend, stackName, synthRegion, flag) {
|
|
|
86631
87031
|
region: synthRegion,
|
|
86632
87032
|
recordRegion: synthRegion
|
|
86633
87033
|
};
|
|
86634
|
-
throw new Error(`No state found for stack
|
|
87034
|
+
throw new Error(`No state found for stack ${displayStackName(stackName)}. Run 'cdkd state list' to see available stacks.`);
|
|
86635
87035
|
}
|
|
86636
87036
|
if (flag) {
|
|
86637
87037
|
if (!refs.find((r) => r.region === flag)) {
|
|
86638
87038
|
const seen = displayRegionList(refs);
|
|
86639
|
-
throw new Error(`No state found for stack
|
|
87039
|
+
throw new Error(`No state found for stack ${displayStackName(stackName)} in region ${displayIdent(flag)}. Available regions: ${seen}.`);
|
|
86640
87040
|
}
|
|
86641
87041
|
return {
|
|
86642
87042
|
region: flag,
|
|
@@ -86657,7 +87057,7 @@ async function pickStackRegion(stateBackend, stackName, synthRegion, flag) {
|
|
|
86657
87057
|
};
|
|
86658
87058
|
}
|
|
86659
87059
|
const regions = displayRegionList(refs);
|
|
86660
|
-
throw new Error(`Stack
|
|
87060
|
+
throw new Error(`Stack ${displayStackName(stackName)} has state in multiple regions: ${regions}. Re-run with --stack-region <region> to disambiguate.`);
|
|
86661
87061
|
}
|
|
86662
87062
|
function printRewriteSummary(rewrites, orphanLogicalIds) {
|
|
86663
87063
|
const logger = getLogger();
|
|
@@ -87303,7 +87703,10 @@ async function importCommand(stackArg, options) {
|
|
|
87303
87703
|
const existingState = existingResult?.state ?? null;
|
|
87304
87704
|
if (existingState) refuseMalformedState(existingState, stackInfo.stackName, targetRegion);
|
|
87305
87705
|
if (existingState) refuseMalformedOutputs(existingState, stackInfo.stackName, targetRegion);
|
|
87306
|
-
if (existingState)
|
|
87706
|
+
if (existingState) {
|
|
87707
|
+
refuseMalformedOrphans(existingState, stackInfo.stackName, targetRegion);
|
|
87708
|
+
refuseMalformedOrphanRecords(existingState, stackInfo.stackName, targetRegion);
|
|
87709
|
+
}
|
|
87307
87710
|
const existingEtag = existingResult?.etag;
|
|
87308
87711
|
const migrationPending = existingResult?.migrationPending ?? false;
|
|
87309
87712
|
if (existingState) {
|
|
@@ -89657,12 +90060,12 @@ function resolveAssetCodeDirectory(opts) {
|
|
|
89657
90060
|
if (isAbsolute(assetPath)) {
|
|
89658
90061
|
const absolute = resolve(assetPath);
|
|
89659
90062
|
const escape = absoluteAssemblyPathEscape(assetOutdir, absolute);
|
|
89660
|
-
if (escape !== void 0) getLogger().warn(`Lambda
|
|
90063
|
+
if (escape !== void 0) getLogger().warn(`Lambda ${displayIdent(logicalId)} has an absolute Metadata['aws:asset:path'] pointing outside the assembly: ${displayAssemblyPath(absolute)}` + (escape.escape === "symlink" ? ` (through a symbolic link to ${displayAssemblyPath(escape.realPath)})` : "") + ". cdkd will bind-mount that directory into the container read-only, where the code in this assembly can read it. This is what cdk synth --no-staging emits, and is expected for it; if you did not synthesize with that flag, treat this assembly as untrusted.");
|
|
89661
90064
|
return absolute;
|
|
89662
90065
|
}
|
|
89663
90066
|
const resolved = resolveAssemblyPath(manifestDir, assetPath, { containWithin: assetOutdir });
|
|
89664
90067
|
if (!resolved.contained && resolved.escape === "lexical" && resolved.path === resolve(assetOutdir)) return resolved.path;
|
|
89665
|
-
if (!resolved.contained) throw wrapError(`Lambda
|
|
90068
|
+
if (!resolved.contained) throw wrapError(`Lambda ${displayIdent(logicalId)} has Metadata['aws:asset:path']=${displayAssemblyPath(assetPath)} which ${renderAssemblyPathEscape(resolved, assetOutdir, "mount it")}`);
|
|
89666
90069
|
return resolved.path;
|
|
89667
90070
|
}
|
|
89668
90071
|
/**
|
|
@@ -89691,9 +90094,8 @@ function resolveAssetCodeDirectory(opts) {
|
|
|
89691
90094
|
* `process.cwd()` survives only for a `StackInfo` carrying NEITHER field, where
|
|
89692
90095
|
* base and bound coincide again.
|
|
89693
90096
|
*
|
|
89694
|
-
* Exported for `local-start-api.ts`'s copy of the caller, for
|
|
89695
|
-
*
|
|
89696
|
-
* (which is why it takes only the two fields it reads), and for unit testing.
|
|
90097
|
+
* Exported for `local-start-api.ts`'s copy of the caller, and for unit
|
|
90098
|
+
* testing.
|
|
89697
90099
|
*/
|
|
89698
90100
|
function assetPathDirs(stack) {
|
|
89699
90101
|
const manifestDir = stack.assetManifestPath ? dirname(stack.assetManifestPath) : stack.assetOutdir ?? process.cwd();
|
|
@@ -89719,7 +90121,7 @@ function assetPathDirs(stack) {
|
|
|
89719
90121
|
*/
|
|
89720
90122
|
function resolveAssetCodePath$1(stack, logicalId, resource) {
|
|
89721
90123
|
const assetPath = resource.Metadata?.["aws:asset:path"];
|
|
89722
|
-
if (typeof assetPath !== "string" || assetPath.length === 0) throw new LocalInvokeResolutionError(`Lambda
|
|
90124
|
+
if (typeof assetPath !== "string" || assetPath.length === 0) throw new LocalInvokeResolutionError(`Lambda ${displayIdent(logicalId)} has no Metadata['aws:asset:path']. cdkd local invoke needs this hint to find the local asset directory. Re-synthesize the app (without \`--output <stale-dir>\`) and retry.`);
|
|
89723
90125
|
const { manifestDir, assetOutdir } = assetPathDirs(stack);
|
|
89724
90126
|
const abs = resolveAssetCodeDirectory({
|
|
89725
90127
|
manifestDir,
|
|
@@ -89728,7 +90130,7 @@ function resolveAssetCodePath$1(stack, logicalId, resource) {
|
|
|
89728
90130
|
assetOutdir,
|
|
89729
90131
|
logicalId
|
|
89730
90132
|
});
|
|
89731
|
-
if (!existsSync(abs) || !statSync(abs).isDirectory()) throw new LocalInvokeResolutionError(`Lambda
|
|
90133
|
+
if (!existsSync(abs) || !statSync(abs).isDirectory()) throw new LocalInvokeResolutionError(`Lambda ${displayIdent(logicalId)} asset directory ${displayAssemblyPath(abs)} does not exist or is not a directory. Re-synthesize the app and retry.`);
|
|
89732
90134
|
return abs;
|
|
89733
90135
|
}
|
|
89734
90136
|
/**
|
|
@@ -90751,7 +91153,7 @@ function parseContainerImage(raw, containerName, taskLogicalId, resources, _stac
|
|
|
90751
91153
|
account: ecrHost.accountId,
|
|
90752
91154
|
region: ecrHost.region
|
|
90753
91155
|
};
|
|
90754
|
-
if (looksLikeEcrHostWithForeignSuffix(substituted)) getLogger().child("ecs-task-resolver").debug(`Image '${substituted}' has an ECR host shape but
|
|
91156
|
+
if (looksLikeEcrHostWithForeignSuffix(substituted)) getLogger().child("ecs-task-resolver").debug(`Image '${substituted}' has an ECR host shape, but that host form and suffix are not an ECR registry endpoint for its region; treating it as a public image (no docker login).`);
|
|
90755
91157
|
return {
|
|
90756
91158
|
kind: "public",
|
|
90757
91159
|
uri: substituted
|
|
@@ -91334,24 +91736,17 @@ const SENSITIVE_ENV_KEYS = /* @__PURE__ */ new Set([
|
|
|
91334
91736
|
* boundary, so a local-invoke build failure still surfaces with cdkd's exit code
|
|
91335
91737
|
* / branding. `architectureToPlatform` is a pure helper (re-exported directly).
|
|
91336
91738
|
*
|
|
91337
|
-
* The build context is CONTAINED
|
|
91338
|
-
* bound
|
|
91339
|
-
*
|
|
91340
|
-
*
|
|
91341
|
-
* manifest directory and refuses a `cdk.Stage` image's
|
|
91342
|
-
*
|
|
91343
|
-
*
|
|
91344
|
-
*
|
|
91345
|
-
* ships, go-to-k/cdkd#3652 drops cdkd's copy.
|
|
91739
|
+
* The build context is CONTAINED by the engine, against the REQUIRED
|
|
91740
|
+
* `assetOutdir` bound this shim forwards (issues
|
|
91741
|
+
* [#3503](https://github.com/go-to-k/cdkd/issues/3503),
|
|
91742
|
+
* [#3597](https://github.com/go-to-k/cdkd/issues/3597)): without one the
|
|
91743
|
+
* engine narrows to the manifest directory and refuses a `cdk.Stage` image's
|
|
91744
|
+
* `../asset.<hash>`. The engine refuses an escaping `source.directory` before
|
|
91745
|
+
* it spawns anything, and renders the value display-safe since cdk-local
|
|
91746
|
+
* 0.149.4, so cdkd carries no copy of the check (go-to-k/cdkd#3652).
|
|
91346
91747
|
* See cdk-local's `src/local/docker-image-builder.ts`.
|
|
91347
91748
|
*/
|
|
91348
91749
|
async function buildContainerImage$1(asset, cdkOutDir, options) {
|
|
91349
|
-
assertCdkLocalDockerContextContained({
|
|
91350
|
-
manifestDir: cdkOutDir,
|
|
91351
|
-
source: asset.source,
|
|
91352
|
-
assetOutdir: options.assetOutdir,
|
|
91353
|
-
wrapError: (message) => new LocalInvokeBuildError$1(`Refusing to build the container image: ${message}`)
|
|
91354
|
-
});
|
|
91355
91750
|
try {
|
|
91356
91751
|
return await buildContainerImage(asset, cdkOutDir, options);
|
|
91357
91752
|
} catch (e) {
|
|
@@ -91362,10 +91757,6 @@ async function buildContainerImage$1(asset, cdkOutDir, options) {
|
|
|
91362
91757
|
|
|
91363
91758
|
//#endregion
|
|
91364
91759
|
//#region src/local/ecr-puller.ts
|
|
91365
|
-
/** The URL suffix an ECR registry host uses in `region`'s partition (issue #1758). */
|
|
91366
|
-
function ecrUrlSuffix(region) {
|
|
91367
|
-
return derivePartitionAndUrlSuffix(region).urlSuffix;
|
|
91368
|
-
}
|
|
91369
91760
|
/**
|
|
91370
91761
|
* Lower-case the REGISTRY HOST of an image reference and leave the repository
|
|
91371
91762
|
* path and tag byte-identical.
|
|
@@ -91485,12 +91876,8 @@ function isCredentialFresh(creds) {
|
|
|
91485
91876
|
* pass to `docker run`: the input with its registry HOST lower-cased and
|
|
91486
91877
|
* its repository path + tag untouched (issue #1801). That is the SAME
|
|
91487
91878
|
* spelling `docker pull` / `docker image inspect` were handed here, and
|
|
91488
|
-
* the same one the
|
|
91489
|
-
*
|
|
91490
|
-
* a VPC-endpoint host), which is correct: AWS names the endpoint its own
|
|
91491
|
-
* token authenticates, and it reports it lower-cased. That precedence holds
|
|
91492
|
-
* only for the PLAIN host form: a FIPS or dual-stack pull logs in to its own
|
|
91493
|
-
* host, since `proxyEndpoint` always names the plain one (issue #1855).
|
|
91879
|
+
* the same one the `docker login` endpoint names, on every host form
|
|
91880
|
+
* (issues #1855 / #3670).
|
|
91494
91881
|
*/
|
|
91495
91882
|
async function pullEcrImage(imageUri, options) {
|
|
91496
91883
|
const logger = getLogger().child("ecr-puller");
|
|
@@ -91594,18 +91981,21 @@ async function assumeRoleForEcr(roleArn, callerRegion, logger) {
|
|
|
91594
91981
|
}
|
|
91595
91982
|
/**
|
|
91596
91983
|
* Authenticate the local docker daemon against the target ECR registry.
|
|
91597
|
-
*
|
|
91598
|
-
*
|
|
91599
|
-
*
|
|
91600
|
-
*
|
|
91601
|
-
*
|
|
91602
|
-
*
|
|
91603
|
-
*
|
|
91604
|
-
*
|
|
91605
|
-
*
|
|
91606
|
-
*
|
|
91607
|
-
* host
|
|
91608
|
-
*
|
|
91984
|
+
* Kept apart from `DockerAssetPublisher.ecrLogin`, and it no longer mirrors it:
|
|
91985
|
+
* the publisher still prefers `proxyEndpoint`, which is right only because it
|
|
91986
|
+
* pushes to the CALLER's own registry, while a pull here can name any account
|
|
91987
|
+
* and any host form, so this one always logs in to the pull host.
|
|
91988
|
+
*
|
|
91989
|
+
* The login endpoint is ALWAYS the host the PULL targets (issues #1855 /
|
|
91990
|
+
* #3670): docker's credential store is keyed on the hostname verbatim, so a
|
|
91991
|
+
* login to any other host leaves the pull with no credentials (`no basic auth
|
|
91992
|
+
* credentials`). `GetAuthorizationToken`'s `proxyEndpoint` is therefore NOT
|
|
91993
|
+
* used. The request carries no `registryIds`, so it names the CALLER's default
|
|
91994
|
+
* registry on the plain host: the wrong host for a FIPS or dual-stack pull, and
|
|
91995
|
+
* the wrong ACCOUNT for a cross-account plain pull made on the caller's own
|
|
91996
|
+
* credentials (a repository-policy grant, no `--ecr-role-arn`). The token is
|
|
91997
|
+
* principal-scoped, not host-scoped: measured against real ECR, one token
|
|
91998
|
+
* authenticated `/v2/` on all four host forms `ECR_REGISTRY_HOST_FORMS` lists.
|
|
91609
91999
|
*/
|
|
91610
92000
|
async function ecrLogin(client, target) {
|
|
91611
92001
|
const { accountId, region, registryHost } = target;
|
|
@@ -91614,8 +92004,7 @@ async function ecrLogin(client, target) {
|
|
|
91614
92004
|
if (!authData?.authorizationToken) throw new LocalInvokeBuildError$1("Failed to get ECR authorization token");
|
|
91615
92005
|
const [username, password] = Buffer.from(authData.authorizationToken, "base64").toString().split(":");
|
|
91616
92006
|
if (!username || password === void 0) throw new LocalInvokeBuildError$1("ECR authorization token has unexpected shape (missing username/password)");
|
|
91617
|
-
const
|
|
91618
|
-
const endpoint = registryHost === plainHost ? authData.proxyEndpoint || `https://${plainHost}` : `https://${registryHost}`;
|
|
92007
|
+
const endpoint = `https://${registryHost}`;
|
|
91619
92008
|
const loginArgs = [
|
|
91620
92009
|
"login",
|
|
91621
92010
|
"--username",
|
|
@@ -93864,7 +94253,7 @@ function resolveImageLambda(args) {
|
|
|
93864
94253
|
*/
|
|
93865
94254
|
function resolveAssetCodePath(stack, logicalId, resource) {
|
|
93866
94255
|
const assetPath = resource.Metadata?.["aws:asset:path"];
|
|
93867
|
-
if (typeof assetPath !== "string" || assetPath.length === 0) throw new Error(`Lambda
|
|
94256
|
+
if (typeof assetPath !== "string" || assetPath.length === 0) throw new Error(`Lambda ${displayIdent(logicalId)} has no Metadata['aws:asset:path']. cdkd local start-api needs this hint to find the local asset directory. Re-synthesize the app and retry.`);
|
|
93868
94257
|
const { manifestDir, assetOutdir } = assetPathDirs(stack);
|
|
93869
94258
|
return resolveAssetCodeDirectory({
|
|
93870
94259
|
manifestDir,
|
|
@@ -95793,134 +96182,6 @@ function createLocalRunTaskCommand() {
|
|
|
95793
96182
|
return cmd;
|
|
95794
96183
|
}
|
|
95795
96184
|
|
|
95796
|
-
//#endregion
|
|
95797
|
-
//#region src/cli/commands/emulator-docker-context.ts
|
|
95798
|
-
/**
|
|
95799
|
-
* Decorate an `EmulatorStrategy` so every Docker image asset the bundled
|
|
95800
|
-
* engine could build for this run is containment-checked BEFORE it builds one
|
|
95801
|
-
* (issue [#3503](https://github.com/go-to-k/cdkd/issues/3503)).
|
|
95802
|
-
*
|
|
95803
|
-
* `cdkd local start-service` / `start-alb` hand the whole run to cdk-local's
|
|
95804
|
-
* `runEcsServiceEmulator`, which reads each stack's asset manifest itself —
|
|
95805
|
-
* for an ECS container image and for an ALB Lambda target's container image
|
|
95806
|
-
* alike. Since cdk-local 0.149.3 the engine refuses an escaping
|
|
95807
|
-
* `source.directory` at each build and each `--watch` soft reload
|
|
95808
|
-
* (go-to-k/cdkd#3597). This check stays in front of it, for the whole
|
|
95809
|
-
* assembly at once, because the engine's refusal quotes the assembly-chosen
|
|
95810
|
-
* value in a boundary the value can close (go-to-k/cdk-local#758);
|
|
95811
|
-
* go-to-k/cdkd#3652 removes it once that ships.
|
|
95812
|
-
*
|
|
95813
|
-
* `resolveBoots` is the seam because the engine calls it after every synth —
|
|
95814
|
-
* at boot, and again on every `--watch` reload — and before any image is
|
|
95815
|
-
* built on either path. A refusal at boot fails the command; on a reload the
|
|
95816
|
-
* engine logs it and keeps the previous replicas serving, which is the
|
|
95817
|
-
* fail-closed outcome.
|
|
95818
|
-
*
|
|
95819
|
-
* Every stack with a manifest is checked, not only the booted targets' stacks:
|
|
95820
|
-
* which stack a target resolves to is decided inside the engine, and the ALB
|
|
95821
|
-
* front door builds Lambda images from stacks no ECS boot names. An escaping
|
|
95822
|
-
* `source.directory` is never something a real `cdk synth` writes, so
|
|
95823
|
-
* refusing one anywhere in the assembly costs a legitimate run nothing, and
|
|
95824
|
-
* `cdkd deploy` refuses the same assembly.
|
|
95825
|
-
*/
|
|
95826
|
-
function containEmulatorDockerContexts(strategy) {
|
|
95827
|
-
return {
|
|
95828
|
-
...strategy,
|
|
95829
|
-
resolveBoots: (stacks, chosenTargets) => {
|
|
95830
|
-
assertEmulatorDockerContextsContained(stacks);
|
|
95831
|
-
return strategy.resolveBoots(stacks, chosenTargets);
|
|
95832
|
-
}
|
|
95833
|
-
};
|
|
95834
|
-
}
|
|
95835
|
-
/**
|
|
95836
|
-
* The check itself, over the manifests the engine will read. Exported for
|
|
95837
|
-
* unit testing.
|
|
95838
|
-
*
|
|
95839
|
-
* It reads the SAME file the engine does — `<manifest dir>/<stackName>.assets.json`,
|
|
95840
|
-
* not `assetManifestPath` verbatim — and refuses a `stackName` that would
|
|
95841
|
-
* carry that filename out of the manifest directory, as cdkd's own
|
|
95842
|
-
* `AssetManifestLoader.loadManifest` does.
|
|
95843
|
-
*
|
|
95844
|
-
* A manifest that is absent, unreadable or not JSON is skipped: the engine
|
|
95845
|
-
* reads it again and reports that failure itself, before building anything.
|
|
95846
|
-
*/
|
|
95847
|
-
function assertEmulatorDockerContextsContained(stacks) {
|
|
95848
|
-
for (const stack of stacks) {
|
|
95849
|
-
if (!stack.assetManifestPath) continue;
|
|
95850
|
-
const dirs = assetPathDirs(stack);
|
|
95851
|
-
const { manifestDir } = dirs;
|
|
95852
|
-
const assetOutdir = stack.assetOutdir === void 0 || stack.assetOutdir === "" ? dirs.assetOutdir : engineAssemblyRoot(stack.assetOutdir);
|
|
95853
|
-
const manifestFile = resolveAssemblyPath(manifestDir, `${stack.stackName}.assets.json`);
|
|
95854
|
-
if (!manifestFile.contained) throw new LocalInvokeBuildError$1(`Refusing to build container images: the asset manifest for stack '${displaySafe(stack.stackName)}' ${renderAssemblyPathEscape(manifestFile, manifestDir)}`);
|
|
95855
|
-
const dockerImages = readDockerImages(manifestFile.path);
|
|
95856
|
-
for (const [assetId, asset] of Object.entries(dockerImages)) {
|
|
95857
|
-
const source = asset?.source;
|
|
95858
|
-
if (source === null || typeof source !== "object") continue;
|
|
95859
|
-
const { directory } = source;
|
|
95860
|
-
if (typeof directory !== "string") continue;
|
|
95861
|
-
assertCdkLocalDockerContextContained({
|
|
95862
|
-
manifestDir,
|
|
95863
|
-
source,
|
|
95864
|
-
assetOutdir,
|
|
95865
|
-
wrapError: (message) => new LocalInvokeBuildError$1(`Refusing to build container image asset '${displaySafe(assetId)}' of stack '${displaySafe(stack.stackName)}': ${message}`)
|
|
95866
|
-
});
|
|
95867
|
-
}
|
|
95868
|
-
}
|
|
95869
|
-
}
|
|
95870
|
-
/**
|
|
95871
|
-
* The containment bound the ENGINE itself uses for a stack it synthesized: its
|
|
95872
|
-
* `assetOutdir`, climbed to the parent assembly when `--app` names a
|
|
95873
|
-
* `cdk.Stage` sub-assembly. cdk-local enumerates no Stage stacks from an app
|
|
95874
|
-
* root, so `--app cdk.out/assembly-<Stage>` is the only way these commands run
|
|
95875
|
-
* a Stage, and its assets are staged one level up as `../asset.<hash>`.
|
|
95876
|
-
*
|
|
95877
|
-
* A copy of cdk-local's `assemblyRootOf` (not exported by the package): climb
|
|
95878
|
-
* only while the directory is named `assembly-*` AND its parent's
|
|
95879
|
-
* `manifest.json` declares it as a `cdk:cloud-assembly` artifact, and WARN
|
|
95880
|
-
* whenever a climb happens, since the predicate is read from the tree being
|
|
95881
|
-
* judged. Deleted with this module by go-to-k/cdkd#3652.
|
|
95882
|
-
*/
|
|
95883
|
-
function engineAssemblyRoot(outdir) {
|
|
95884
|
-
let dir = resolve(outdir);
|
|
95885
|
-
let climbed = false;
|
|
95886
|
-
for (;;) {
|
|
95887
|
-
if (!basename(dir).startsWith("assembly-")) break;
|
|
95888
|
-
const parent = dirname(dir);
|
|
95889
|
-
if (parent === dir || !parentDeclaresNestedAssembly(parent, basename(dir))) break;
|
|
95890
|
-
dir = parent;
|
|
95891
|
-
climbed = true;
|
|
95892
|
-
}
|
|
95893
|
-
if (!climbed) return outdir;
|
|
95894
|
-
if (!warnedDerivedRoots.has(dir)) {
|
|
95895
|
-
warnedDerivedRoots.add(dir);
|
|
95896
|
-
getLogger().warn(`${displayAssemblyPath(outdir)} is a cdk.Stage sub-assembly, so cdkd is treating its parent ${displayAssemblyPath(dir)} as the assembly root when it checks Docker build contexts — that is where cdk synth stages a Stage's assets. Everything under that parent is now inside the containment bound, including siblings of the directory you named.`);
|
|
95897
|
-
}
|
|
95898
|
-
return dir;
|
|
95899
|
-
}
|
|
95900
|
-
const warnedDerivedRoots = /* @__PURE__ */ new Set();
|
|
95901
|
-
function parentDeclaresNestedAssembly(parent, child) {
|
|
95902
|
-
try {
|
|
95903
|
-
const artifacts = JSON.parse(readFileSync(join(parent, "manifest.json"), "utf-8")).artifacts;
|
|
95904
|
-
if (artifacts === null || typeof artifacts !== "object") return false;
|
|
95905
|
-
return Object.values(artifacts).some((a) => {
|
|
95906
|
-
const art = a;
|
|
95907
|
-
return art?.type === "cdk:cloud-assembly" && art.properties?.directoryName === child;
|
|
95908
|
-
});
|
|
95909
|
-
} catch {
|
|
95910
|
-
return false;
|
|
95911
|
-
}
|
|
95912
|
-
}
|
|
95913
|
-
function readDockerImages(manifestPath) {
|
|
95914
|
-
let parsed;
|
|
95915
|
-
try {
|
|
95916
|
-
parsed = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
95917
|
-
} catch {
|
|
95918
|
-
return {};
|
|
95919
|
-
}
|
|
95920
|
-
const dockerImages = parsed?.dockerImages;
|
|
95921
|
-
return dockerImages !== null && typeof dockerImages === "object" ? dockerImages : {};
|
|
95922
|
-
}
|
|
95923
|
-
|
|
95924
96185
|
//#endregion
|
|
95925
96186
|
//#region src/cli/commands/local-start-service.ts
|
|
95926
96187
|
/**
|
|
@@ -95948,17 +96209,6 @@ function serviceStrategy() {
|
|
|
95948
96209
|
};
|
|
95949
96210
|
}
|
|
95950
96211
|
/**
|
|
95951
|
-
* The `EmulatorStrategy` `cdkd local start-service` runs with:
|
|
95952
|
-
* {@link serviceStrategy}, decorated by `containEmulatorDockerContexts` so the
|
|
95953
|
-
* engine's own Docker builds are containment-checked (issue
|
|
95954
|
-
* [#3503](https://github.com/go-to-k/cdkd/issues/3503)). A NAMED seam for the
|
|
95955
|
-
* same reason `buildAlbEmulatorStrategy` is one: inline in the action, the
|
|
95956
|
-
* decorator was deletable at its only call site.
|
|
95957
|
-
*/
|
|
95958
|
-
function buildServiceEmulatorStrategy() {
|
|
95959
|
-
return containEmulatorDockerContexts(serviceStrategy());
|
|
95960
|
-
}
|
|
95961
|
-
/**
|
|
95962
96212
|
* `cdkl start-service <Stack/Service>...` — run one or more `AWS::ECS::Service`
|
|
95963
96213
|
* resources locally as a long-running emulator. Spins up DesiredCount task
|
|
95964
96214
|
* replicas per service (clamped by --max-tasks) using the same per-task
|
|
@@ -95971,7 +96221,7 @@ function buildServiceEmulatorStrategy() {
|
|
|
95971
96221
|
*/
|
|
95972
96222
|
function createLocalStartServiceCommand() {
|
|
95973
96223
|
const cmd = new Command("start-service").description("Run one or more AWS::ECS::Service resources locally as a long-running emulator. Spins up DesiredCount task replicas per service (clamped by --max-tasks) using the same per-task docker network + metadata sidecar pattern as `cdkd local run-task`, then keeps each replica running and restarts it on exit per --restart-policy. ^C tears every replica + sidecar + network down. Each <target> accepts a CDK display path (MyStack/MyService) or stack-qualified logical ID (MyStack:MyServiceXYZ); single-stack apps may omit the stack prefix. When two or more <target>s are supplied, every service is booted into a shared Cloud Map / Service Connect registry so peer services discover each other via docker --add-host overlay (Issue #460). Omit <targets> in an interactive terminal to multi-select the ECS services from a list.").argument("[targets...]", "One or more CDK display paths or stack-qualified logical IDs of the AWS::ECS::Service resources to run (omit to multi-select interactively in a TTY)").addOption(new Option("--from-state", "Read cdkd's S3 state for the target stack and substitute Ref / Fn::GetAtt / Fn::Sub / Fn::ImportValue / Fn::GetStackOutput intrinsics in container images, environment variables, secrets, role ARNs, and volumes. Mutually exclusive with --from-cfn-stack.").default(false)).addOption(new Option("--state-bucket <bucket>", "S3 bucket for --from-state. Falls back to CDKD_STATE_BUCKET env or cdk.json context.cdkd.stateBucket.")).addOption(new Option("--state-prefix <prefix>", "S3 key prefix for --from-state state files.").default("cdkd")).action(withErrorHandling(async (targets, options) => {
|
|
95974
|
-
await runEcsServiceEmulator(targets, options,
|
|
96224
|
+
await runEcsServiceEmulator(targets, options, serviceStrategy(), cdkdExtraStateProviders);
|
|
95975
96225
|
}));
|
|
95976
96226
|
addStartServiceSpecificOptions(cmd);
|
|
95977
96227
|
return adoptDeprecatedRegionFlag(addCommonEcsServiceOptions(cmd));
|
|
@@ -96903,12 +97153,12 @@ async function resolveAgentCoreCodeImage(resolved, code, options, architecture,
|
|
|
96903
97153
|
const manifest = await loader.loadManifest(cdkOutDir, resolved.stack.stackName);
|
|
96904
97154
|
const fileAssets = manifest ? loader.getFileAssets(manifest) : void 0;
|
|
96905
97155
|
const asset = fileAssets ? fileAssets.get(code.codeAssetHash) ?? findFileAssetByObjectKey(fileAssets, code.codeAssetHash) : void 0;
|
|
96906
|
-
if (!asset) throw new CdkdError(`AgentCore Runtime
|
|
97156
|
+
if (!asset) throw new CdkdError(`AgentCore Runtime ${displayIdent(resolved.logicalId)} code bundle (asset ${displaySafe(code.codeAssetHash)}) was not found in the cdk.out asset manifest. ${getEmbedConfig().cliName} invoke-agentcore runs a local from-source build of a fromCodeAsset bundle — re-synthesize the app so the asset is staged in cdk.out and retry. (A fromS3 bundle is downloaded from S3 instead; this runtime has no literal Code.S3.Bucket.)`, "LOCAL_INVOKE_AGENTCORE_CODE_ASSET_NOT_FOUND");
|
|
96907
97157
|
const sourceDir = loader.getAssetSourcePath(cdkOutDir, asset, {
|
|
96908
97158
|
assetOutdir: assemblyDir,
|
|
96909
97159
|
sink: "read that directory and build a local image from it"
|
|
96910
97160
|
});
|
|
96911
|
-
if (!existsSync(sourceDir) || !statSync(sourceDir).isDirectory()) throw new CdkdError(`AgentCore Runtime
|
|
97161
|
+
if (!existsSync(sourceDir) || !statSync(sourceDir).isDirectory()) throw new CdkdError(`AgentCore Runtime ${displayIdent(resolved.logicalId)} code bundle source ${displayAssemblyPath(sourceDir)} does not exist or is not a directory. Re-synthesize the app and retry.`, "LOCAL_INVOKE_AGENTCORE_CODE_SOURCE_MISSING");
|
|
96912
97162
|
return buildAgentCoreCodeImage({
|
|
96913
97163
|
sourceDir,
|
|
96914
97164
|
runtime: code.runtime,
|
|
@@ -97660,8 +97910,7 @@ function warnUnresolvedLambdaTargetEnv(strategy, options) {
|
|
|
97660
97910
|
}
|
|
97661
97911
|
/**
|
|
97662
97912
|
* The `EmulatorStrategy` `cdkd local start-alb` runs with: cdk-local's ALB
|
|
97663
|
-
* strategy, decorated by {@link warnUnresolvedLambdaTargetEnv}
|
|
97664
|
-
* `containEmulatorDockerContexts` (issue go-to-k/cdkd#3503).
|
|
97913
|
+
* strategy, decorated by {@link warnUnresolvedLambdaTargetEnv}.
|
|
97665
97914
|
*
|
|
97666
97915
|
* Extracted from the command's action for ONE reason, and it is the finding
|
|
97667
97916
|
* that produced it: with the composition written inline in the `.action(...)`
|
|
@@ -97681,7 +97930,7 @@ function warnUnresolvedLambdaTargetEnv(strategy, options) {
|
|
|
97681
97930
|
* can satisfy reads as coverage while providing none.
|
|
97682
97931
|
*/
|
|
97683
97932
|
function buildAlbEmulatorStrategy(options) {
|
|
97684
|
-
return
|
|
97933
|
+
return warnUnresolvedLambdaTargetEnv(albStrategy(options), options);
|
|
97685
97934
|
}
|
|
97686
97935
|
/**
|
|
97687
97936
|
* `cdkl start-alb <Stack/Alb>` — Issue #86 v1. Names an
|
|
@@ -98819,4 +99068,4 @@ function buildProgram() {
|
|
|
98819
99068
|
|
|
98820
99069
|
//#endregion
|
|
98821
99070
|
export { buildProgram };
|
|
98822
|
-
//# sourceMappingURL=program-
|
|
99071
|
+
//# sourceMappingURL=program-DxyHPT8E.js.map
|