@go-to-k/cdkd 0.311.0 → 0.312.0

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.
Files changed (29) hide show
  1. package/README.md +2 -2
  2. package/dist/{asg-provider-CIg_guZ-.js → asg-provider-CVLTQtQr.js} +3 -3
  3. package/dist/{asg-provider-CIg_guZ-.js.map → asg-provider-CVLTQtQr.js.map} +1 -1
  4. package/dist/cli.js +2 -2
  5. package/dist/{created-resource-sink-DlzoIY-1.js → created-resource-sink-BT2Dfnpt.js} +2 -2
  6. package/dist/{created-resource-sink-DlzoIY-1.js.map → created-resource-sink-BT2Dfnpt.js.map} +1 -1
  7. package/dist/{db-instance-modify-retry-1y0kIPCO.js → db-instance-modify-retry-D7wXWxVo.js} +2 -2
  8. package/dist/{db-instance-modify-retry-1y0kIPCO.js.map → db-instance-modify-retry-D7wXWxVo.js.map} +1 -1
  9. package/dist/{deploy-engine-BF5exXUb.js → deploy-engine-CVNzK__j.js} +303 -78
  10. package/dist/deploy-engine-CVNzK__j.js.map +1 -0
  11. package/dist/{iam-role-provider-qvhlVnrn.js → iam-role-provider-DM7bN9m1.js} +3 -3
  12. package/dist/{iam-role-provider-qvhlVnrn.js.map → iam-role-provider-DM7bN9m1.js.map} +1 -1
  13. package/dist/index.js +3 -3
  14. package/dist/{neptune-provider-D9ac71Ca.js → neptune-provider-qdoLunCh.js} +53 -6
  15. package/dist/neptune-provider-qdoLunCh.js.map +1 -0
  16. package/dist/{program-DbnTHlwR.js → program-Nk_95KKk.js} +16 -10
  17. package/dist/program-Nk_95KKk.js.map +1 -0
  18. package/dist/{provider-classes-DktsDsTf.js → provider-classes-Dz0pYmlJ.js} +1045 -80
  19. package/dist/provider-classes-Dz0pYmlJ.js.map +1 -0
  20. package/dist/{rds-provider-0LUsn9Wl.js → rds-provider-CXSZq1c8.js} +25 -14
  21. package/dist/rds-provider-CXSZq1c8.js.map +1 -0
  22. package/dist/{version-BA4rBBLp.js → version-BqCEt5Wu.js} +2 -2
  23. package/dist/{version-BA4rBBLp.js.map → version-BqCEt5Wu.js.map} +1 -1
  24. package/package.json +1 -1
  25. package/dist/deploy-engine-BF5exXUb.js.map +0 -1
  26. package/dist/neptune-provider-D9ac71Ca.js.map +0 -1
  27. package/dist/program-DbnTHlwR.js.map +0 -1
  28. package/dist/provider-classes-DktsDsTf.js.map +0 -1
  29. package/dist/rds-provider-0LUsn9Wl.js.map +0 -1
@@ -1,14 +1,14 @@
1
1
  import { r as getAwsClients, s as withApiGatewayPacing } from "./aws-clients-Bu9EMILF.js";
2
2
  import { B as SECRET_REF_MAX_CODE_POINTS, C as generateResourceName, D as getCurrentStackInstanceId, J as displayStackName, K as displayIdent, M as recordedGeneratedNameKept, Q as safeMsg, T as generatedNameFor, Y as isPasteableIdent, Z as plainIdentOr, a as safeStringify, i as isAwsAuthoredFailure, k as isBeforeStateRead, n as describeAwsFailure, q as displaySafe, r as describeAwsStatusReason, s as getLogger, t as VERBOSE_POINTER, w as generateResourceNameWithFallback } from "./aws-failure-text-NSBdKPYK.js";
3
- import { $ as observeThenDisableProtection, A as RESOURCE_NOT_FOUND, An as ProvisioningError, Ar as wrapMaskedAwsError, At as isSecretDerivedValue, B as refusalTypeShown, Bt as isAuxiliaryFailure, C as ambiguousAttemptLead, Cr as isTransientServerError, Ct as logicalIdShown, D as replayedSendWindow, Dr as isThrottlingError, Dt as stateOrphanRecordRemedy, E as replayFollowedAmbiguousAttempt, Er as isMarkedNonRetryable, Et as segmentAfterAnchor, F as isPlainImportJson, H as resolveExplicitPhysicalId, Ht as markAuxiliaryFailure, I as isPlainImportValue, It as clearCreatedBeforeFailure, Jn as isInertUnquoted, K as deleteAfterProtectionFlipWithFinalSnapshot, Kn as commandHole, L as isQuotableImportValue, M as markNotGone, Mn as ResourceUpdateNotSupportedError, Mt as maskerOrIdentity, N as assertRegionMatch, Nt as withDerivedNameMasks, O as setBounded, Or as markNonRetryable, Ot as createMaskedLogSinks, P as VALUE_NOT_SHOWN, Q as logGroupProtectionSite, R as normalizeAwsTagsToCfn, S as RecentIdSet, Sr as isRetryableTransientError, St as compositeIdSkipResult, T as isInsideWindow, Tr as THROTTLING_ERROR_NAMES, Ut as markCreatedBeforeFailure, V as remedyLogicalId, W as ProtectionFlipRegistry, Wt as markSupersedesEarlierCreate, X as isTerminalDbWaitStatus, Yn as pasteableCommand, Z as isTerminalDeleteFailure, Zn as plainOrDescribed, _t as isInterruptedWaitError, a as retractCreatedResource, b as AMBIGUOUS_LATCH_TTL_MS, br as isExplicitDenyError, bt as compositeIdFormatMessage, c as SECRET_DERIVED_READ_LIVE, cn as withPasteableAwsProfile, ct as isAwsCliLiteral, d as readPrincipalLists, dn as clientDefaultsFor, dr as markReplayMayCollide, dt as renderDisableCommand, er as shellQuote, et as protectionFlipKey, fn as credentialFingerprint, fr as relayedNameCollision, ft as ElapsedBudgetRegistry, gr as explicitDenyPolicyKind, h as clearOnUpdateRemoval, hn as CdkdError, i as reportCreatedResource, in as injectiveKeyPrefix, it as userPoolProtectionSite, jt as maskDeep, k as withoutServerErrorRetries, kr as markRedactedCause, kt as createMaskedRetryLogger, l as holdsSecretDerivedEntry, ln as ambientClientDefaults, lt as pasteableAwsCommand, ot as UNNAMEABLE_ID_CLAUSE, p as recordedPrincipalsRepair, pn as AccountIdUnavailableError, q as deleteWithProtectionCompensation, qn as hasClauseBreak, rn as injectiveKey, st as WITHHELD_AWS_COMMAND, tr as withheldTargetClause, tt as rdsFamilyProtectionSite, u as onlySecretDerived, un as ambientCredentialConfig, ur as markNameCollision, ut as protectedReplacementAdvice, v as withRemovalDefaults, vt as startInterruptWatch, w as createAttemptKey, wt as packCompositeId, x as AmbiguousCreateLatch, xt as compositeIdSeparatorRefusal, yr as isAmbiguousOutcomeError, yt as canonicalizeRoute53QueryName, z as quotedRemedyLogicalId } from "./created-resource-sink-DlzoIY-1.js";
3
+ import { $ as logGroupProtectionSite, $n as plainOrDescribed, A as withoutServerErrorRetries, Ar as markNonRetryable, At as createMaskedLogSinks, B as quotedRemedyLogicalId, C as RecentIdSet, Ct as compositeIdSeparatorRefusal, D as replayFollowedAmbiguousAttempt, Dr as THROTTLING_ERROR_NAMES, E as isInsideWindow, Et as packCompositeId, F as VALUE_NOT_SHOWN, Ft as withDerivedNameMasks, G as ProtectionFlipRegistry, Gt as markCreatedBeforeFailure, H as remedyLogicalId, Ht as isAuxiliaryFailure, I as isPlainImportJson, J as deleteWithProtectionCompensation, Jn as commandHole, Kt as markSupersedesEarlierCreate, L as isPlainImportValue, Mn as ProvisioningError, Mr as wrapMaskedAwsError, Mt as isSecretDerivedValue, N as markNotGone, Nt as maskDeep, O as replayedSendWindow, Or as isMarkedNonRetryable, Ot as segmentAfterAnchor, P as assertRegionMatch, Pn as ResourceUpdateNotSupportedError, Pt as maskerOrIdentity, Q as isTerminalDeleteFailure, R as isQuotableImportValue, Rt as clearCreatedBeforeFailure, S as AmbiguousCreateLatch, Sr as isExplicitDenyError, St as compositeIdFormatMessage, T as createAttemptKey, Tr as isTransientServerError, Tt as logicalIdShown, U as resolveExplicitPhysicalId, V as refusalTypeShown, Wt as markAuxiliaryFailure, Xn as isInertUnquoted, Yn as hasClauseBreak, Z as isTerminalDbWaitStatus, Zn as pasteableCommand, _n as CdkdError, a as retractCreatedResource, an as injectiveKey, at as userPoolProtectionSite, bt as startInterruptWatch, c as SECRET_DERIVED_READ_LIVE, ct as WITHHELD_AWS_COMMAND, d as readPrincipalLists, dn as ambientClientDefaults, dt as protectedReplacementAdvice, et as observeThenDisableProtection, fn as ambientCredentialConfig, fr as markNameCollision, ft as renderDisableCommand, h as clearOnUpdateRemoval, hn as AccountIdUnavailableError, i as reportCreatedResource, j as RESOURCE_NOT_FOUND, jr as markRedactedCause, jt as createMaskedRetryLogger, k as setBounded, kr as isThrottlingError, kt as stateOrphanRecordRemedy, l as holdsSecretDerivedEntry, lt as isAwsCliLiteral, mn as credentialFingerprint, mr as relayedNameCollision, mt as ElapsedBudgetRegistry, nr as shellQuote, nt as rdsFamilyProtectionSite, on as injectiveKeyPrefix, p as recordedPrincipalsRepair, pn as clientDefaultsFor, pr as markReplayMayCollide, pt as ElapsedBudget, q as deleteAfterProtectionFlipWithFinalSnapshot, rr as withheldTargetClause, st as UNNAMEABLE_ID_CLAUSE, tt as protectionFlipKey, u as onlySecretDerived, un as withPasteableAwsProfile, ut as pasteableAwsCommand, v as removedTemplateKeys, vr as explicitDenyPolicyKind, w as ambiguousAttemptLead, wr as isRetryableTransientError, wt as compositeIdSkipResult, x as AMBIGUOUS_LATCH_TTL_MS, xr as isAmbiguousOutcomeError, xt as canonicalizeRoute53QueryName, y as withRemovalDefaults, yt as isInterruptedWaitError, z as normalizeAwsTagsToCfn } from "./created-resource-sink-BT2Dfnpt.js";
4
4
  import { c as ambientRegion } from "./aws-client-defaults-BX9Y_fKp.js";
5
- import { $s as coerceCfnBoolean, $t as isAccessDeniedError, A as DYNAMODB_DELETE_POLL_COST_MS, B as relayedIndexBusyDelete, Bc as snapshotPassProvenance, Bi as tagPlanWarning, Bn as redactedDeleteAddressSkip, C as planContributorInsightsOp, Ca as isUsableAttemptedName, Cs as refuseMalformedResourcesForDestroy, D as reverseMapTableContributorInsights, Dd as renderAssemblyPathEscape, E as reverseMapIndexContributorInsights, Ed as displayAssemblyPath, Ei as reserveStackCreateToken, F as resolveDynamoDbDeleteBudgetMs, Fa as s3BucketRegionalDomainName, Fi as DBPROXY_TAG_OPTIONS, Fn as getCurrentProducerRegions, Fr as replacedDeleteFailureVerdict, Fs as withheldAccountClause, G as readTtlSpec, H as isTtlAlreadyDisabled, Hi as stringifyIfAssigned, Ht as withNestedStackContext, I as DELETE_INDEX_WAIT_PROCEED_NOTE, Ia as s3BucketWebsiteUrl, Ii as planTagDiff, J as S3_AUTO_DELETE_OBJECTS_TAG, Ji as waitForLambdaFunctionActive, Js as WARM_THROUGHPUT_MEMBERS, K as sendTtlWaitingOutRateLimit, L as INDEX_SETTLE_POLL_INTERVAL_MS, Lc as markSameGenerationBag, Li as readTagList, Ln as REDACTED_DELETE_ADDRESS_SKIP_REASON, Ls as findSilentDropProperties, Lt as revertNestedChildFromJournal, M as compensateRemovedDeletionProtection, Ma as s3BucketArn, Mi as isRefusedByName, N as deleteBudgetKey, Na as s3BucketDomainName, Ni as markDeleteStarted, Nr as getStackRecords, O as stripIndexContributorInsights, Od as resolveAssemblyPath, Oi as acquireIdempotencyToken, Oo as accountArgs, P as resolveDynamoDbDeleteBudgetClock, Pa as s3BucketDualStackDomainName, Pi as DBPROXY_TAGS_WHAT, Pt as getNestedRevertRun, Q as markRefusedBeforeApplying, Qi as getCurrentResourceSecrets, Qs as toFiniteNumber, Qt as chunks, R as deleteTableWithIndexBusyRetry, Rc as redactForState, Ri as refuseMalformedDesiredTags, Rn as isRedactedRecordedValue, S as indexDeclaresContributorInsights, T as readContributorInsightsSpec, Td as describeFileReadFailure, U as isTtlRateLimited, Uc as hasMaskableValues, V as waitForIndexesSettled, Va as outputReferenceProvenanceOf, Vi as definedAttributes, Vt as getCurrentNestedStackContext, W as planTimeToLive, X as isTruthyCfnBoolean, Xs as isWarmThroughputDecrease, Y as hasCdkAutoDeleteTag, Ys as coerceWarmThroughput$1, Z as getPriorAttempts, Zs as toCfnInteger, _ as streamMemberRefusals, _a as isTerminationProtectionPropagationError, _c as canonicalLambdaFunctionName, _l as carriesSecretMask, _t as enclosingDeadlineRemainingMs, aa as onlySecretReferencesDiffer, ac as replayWarn, al as dynamicReferenceTokens, b as CONTRIBUTOR_INSIGHTS_KEY, ba as reEnableInstanceApiTermination, c as DynamoDBGlobalTableProvider, cc as requireConfigString, cd as decodeListingKey, ct as isAbsoluteAssetPath, d as declaredStreamPolicyMember, da as deleteSkipReason, dd as canonicalizeRegion, di as secretNamedAttributeNamesOf, ec as coerceCfnInteger, en as lookupEachName, f as declaredStreamTagsMember, fa as withIndeterminateGuard, fc as withRetry, fd as derivePartitionAndUrlSuffix, fl as recoverMaskedOutput, g as streamDeclaresTags, ga as ec2InstanceProtectionSite, gc as emrClusterInstancesReplaced, gt as enclosingDeadlineExpired, h as streamDeclaresPolicy, hc as ecsServiceLaunchTypeSetOrChanged, ia as slowCcOperationTimeoutMs, ic as readConfigString, iu as stringifyValue, j as beginDeleteWait, ja as isSettledInstanceState, jc as passedNoEchoParametersOf, jr as awaitInFlightSibling, k as DYNAMODB_DELETE_MIN_RESOURCE_TIMEOUT_MS, l as STREAM_POLICY_KEY, lt as listNestedTemplateRows, lu as rewriteTemplateAssetReferences, m as reverseMapStreamPolicy, ma as markWaitAbandoned, ml as recordAttributeIdCopy, nc as configIntegerRefusal, oa as unchangedBehindSecretReference, oc as requireConfigArray, p as planStreamMemberOps, pa as isWaitAbandonedError, pc as blockDeviceMappingsDifferOnlyInDeleteOnTermination, pl as physicalNameCopiesOf, q as ECR_AUTO_DELETE_IMAGES_TAG, rc as configStringRefusal, rl as withoutPhysicalNameCopies, rs as refuseMalformedNestedChildOutputs, sc as requireConfigObject, so as getAccountInfo, st as findNestedTemplateTreeDefect, t as DeployEngine, tc as configBooleanRefusal, tn as withApiLimit, tu as timePhase, u as STREAM_TAGS_KEY, ut as renderNestedTemplateTreeDefect, v as streamPolicyMatchesDeclared, va as observeThenDisableInstanceApiTermination, vc as lambdaFunctionNameForMask, vo as parseWebACLArn, w as planIndexContributorInsightsOps, wi as earliestDefined, x as contributorInsightsRefusals, xo as passedParameterClassesOf, y as streamTagsMatchDeclared, ya as reDisableInstanceApiTermination, yc as sameLambdaFunctionAddress, z as maskedLogger, zc as recordReferenceProvenanceEntry, zi as tagMapAsList, zn as redactedDeleteAddressFields, zs as withoutSilentDropProperties } from "./deploy-engine-BF5exXUb.js";
6
- import { n as collectInlinePolicyNamesManagedBySiblings, r as IamCreateClientCache, t as IAMRoleProvider } from "./iam-role-provider-qvhlVnrn.js";
7
- import { a as resolveSecretDerivedPrincipals, i as isResolvableSecretPrincipalList, n as runDestroyForStack, o as canonicalizeIpProtocolValue, r as holdsUnprovenSecretPrincipalToken, s as resolvedResourceTimeoutMs, t as canonicalizeIpv4Cidr } from "./program-DbnTHlwR.js";
8
- import { t as modifyDbInstanceWhenAvailable } from "./db-instance-modify-retry-1y0kIPCO.js";
9
- import { RDSProvider } from "./rds-provider-0LUsn9Wl.js";
10
- import { NeptuneProvider } from "./neptune-provider-D9ac71Ca.js";
11
- import { ASGProvider } from "./asg-provider-CIg_guZ-.js";
5
+ import { $ as getPriorAttempts, $s as isWarmThroughputDecrease, A as DYNAMODB_DELETE_MIN_RESOURCE_TIMEOUT_MS, Ad as renderAssemblyPathEscape, Ai as acquireIdempotencyToken, Ao as accountArgs, B as deleteTableWithIndexBusyRetry, Bc as markSameGenerationBag, Bi as refuseMalformedDesiredTags, Bn as isRedactedRecordedValue, Bs as findSilentDropProperties, C as planContributorInsightsOp, Co as passedParameterClassesOf, D as reverseMapTableContributorInsights, E as reverseMapIndexContributorInsights, Ei as earliestDefined, F as resolveDynamoDbDeleteBudgetClock, Fa as s3BucketDomainName, Fi as markDeleteStarted, Fr as getStackRecords, G as isTtlRateLimited, H as relayedIndexBusyDelete, Hc as recordReferenceProvenanceEntry, Hi as tagPlanWarning, Hn as redactedDeleteAddressSkip, Hs as withoutSilentDropProperties, I as resolveDynamoDbDeleteBudgetMs, Ia as s3BucketDualStackDomainName, Ii as DBPROXY_TAGS_WHAT, It as getNestedRevertRun, J as sendTtlWaitingOutRateLimit, K as planTimeToLive, Kc as hasMaskableValues, L as DELETE_INDEX_WAIT_PROCEED_NOTE, La as s3BucketRegionalDomainName, Li as DBPROXY_TAG_OPTIONS, Ln as getCurrentProducerRegions, Lr as replacedDeleteFailureVerdict, Ls as withheldAccountClause, M as beginDeleteWait, N as compensateRemovedDeletionProtection, Na as isSettledInstanceState, Nr as awaitInFlightSibling, O as stripIndexContributorInsights, Od as describeFileReadFailure, Oi as reserveStackCreateToken, P as deleteBudgetKey, Pa as s3BucketArn, Pc as passedNoEchoParametersOf, Pi as isRefusedByName, Q as isTruthyCfnBoolean, Qs as coerceWarmThroughput$1, R as INDEX_SETTLE_POLL_INTERVAL_MS, Ra as s3BucketWebsiteUrl, Ri as planTagDiff, S as indexDeclaresContributorInsights, Sa as reEnableInstanceApiTermination, Sc as sameLambdaFunctionAddress, T as readContributorInsightsSpec, Ta as isUsableAttemptedName, Ts as refuseMalformedResourcesForDestroy, U as waitForIndexesSettled, Ua as outputReferenceProvenanceOf, Uc as snapshotPassProvenance, Ui as definedAttributes, Ut as getCurrentNestedStackContext, V as maskedLogger, Vc as redactForState, Vi as tagMapAsList, Vn as redactedDeleteAddressFields, W as isTtlAlreadyDisabled, Wi as stringifyIfAssigned, Wt as withNestedStackContext, X as S3_AUTO_DELETE_OBJECTS_TAG, Xi as waitForLambdaFunctionActive, Y as ECR_AUTO_DELETE_IMAGES_TAG, Z as hasCdkAutoDeleteTag, Zs as WARM_THROUGHPUT_MEMBERS, _ as streamMemberRefusals, _l as recordAttributeIdCopy, ac as configIntegerRefusal, as as refuseMalformedNestedChildOutputs, b as CONTRIBUTOR_INSIGHTS_KEY, ba as observeThenDisableInstanceApiTermination, bc as canonicalLambdaFunctionName, bl as carriesSecretMask, bo as parseWebACLArn, c as DynamoDBGlobalTableProvider, ca as unchangedBehindSecretReference, cc as replayWarn, cl as dynamicReferenceTokens, d as declaredStreamPolicyMember, dc as requireConfigString, dd as decodeListingKey, dt as listNestedTemplateRows, ea as getCurrentResourceSecrets, ec as toCfnInteger, en as chunks, et as markRefusedBeforeApplying, f as declaredStreamTagsMember, ft as renderNestedTemplateTreeDefect, fu as rewriteTemplateAssetReferences, g as streamDeclaresTags, ga as markWaitAbandoned, gc as blockDeviceMappingsDifferOnlyInDeleteOnTermination, gl as physicalNameCopiesOf, h as streamDeclaresPolicy, ha as isWaitAbandonedError, hc as withRetry, hd as derivePartitionAndUrlSuffix, hl as recoverMaskedOutput, ic as configBooleanRefusal, iu as timePhase, j as DYNAMODB_DELETE_POLL_COST_MS, jd as resolveAssemblyPath, k as DYNAMODB_DELETE_DEADLINE_MARGIN_MS, kd as displayAssemblyPath, l as STREAM_POLICY_KEY, lc as requireConfigArray, lo as getAccountInfo, lt as findNestedTemplateTreeDefect, m as reverseMapStreamPolicy, ma as withIndeterminateGuard, md as canonicalizeRegion, nc as coerceCfnBoolean, nn as lookupEachName, oa as slowCcOperationTimeoutMs, oc as configStringRefusal, ol as withoutPhysicalNameCopies, p as planStreamMemberOps, pa as deleteSkipReason, pi as secretNamedAttributeNamesOf, q as readTtlSpec, rc as coerceCfnInteger, rn as withApiLimit, sa as onlySecretReferencesDiffer, sc as readConfigString, su as stringifyValue, t as DeployEngine, tc as toFiniteNumber, tn as isAccessDeniedError, u as STREAM_TAGS_KEY, uc as requireConfigObject, ut as isAbsoluteAssetPath, v as streamPolicyMatchesDeclared, va as ec2InstanceProtectionSite, vc as ecsServiceLaunchTypeSetOrChanged, vt as enclosingDeadlineExpired, w as planIndexContributorInsightsOps, x as contributorInsightsRefusals, xa as reDisableInstanceApiTermination, xc as lambdaFunctionNameForMask, y as streamTagsMatchDeclared, ya as isTerminationProtectionPropagationError, yc as emrClusterInstancesReplaced, yt as enclosingDeadlineRemainingMs, z as TABLE_INDEX_NOUN, zi as readTagList, zn as REDACTED_DELETE_ADDRESS_SKIP_REASON, zt as revertNestedChildFromJournal } from "./deploy-engine-CVNzK__j.js";
6
+ import { n as collectInlinePolicyNamesManagedBySiblings, r as IamCreateClientCache, t as IAMRoleProvider } from "./iam-role-provider-DM7bN9m1.js";
7
+ import { a as resolveSecretDerivedPrincipals, i as isResolvableSecretPrincipalList, n as runDestroyForStack, o as canonicalizeIpProtocolValue, r as holdsUnprovenSecretPrincipalToken, s as resolvedResourceTimeoutMs, t as canonicalizeIpv4Cidr } from "./program-Nk_95KKk.js";
8
+ import { t as modifyDbInstanceWhenAvailable } from "./db-instance-modify-retry-D7wXWxVo.js";
9
+ import { RDSProvider } from "./rds-provider-CXSZq1c8.js";
10
+ import { NeptuneProvider } from "./neptune-provider-qdoLunCh.js";
11
+ import { ASGProvider } from "./asg-provider-CVLTQtQr.js";
12
12
  import { createHash, randomUUID } from "node:crypto";
13
13
  import { 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, ListBucketsCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchBucket, PutBucketAccelerateConfigurationCommand, PutBucketAnalyticsConfigurationCommand, PutBucketCorsCommand, PutBucketEncryptionCommand, PutBucketIntelligentTieringConfigurationCommand, PutBucketInventoryConfigurationCommand, PutBucketLifecycleConfigurationCommand, PutBucketLoggingCommand, PutBucketMetricsConfigurationCommand, PutBucketNotificationConfigurationCommand, PutBucketOwnershipControlsCommand, PutBucketPolicyCommand, PutBucketReplicationCommand, PutBucketTaggingCommand, PutBucketVersioningCommand, PutBucketWebsiteCommand, PutObjectLockConfigurationCommand, PutPublicAccessBlockCommand, S3Client } from "@aws-sdk/client-s3";
14
14
  import { AddRoleToInstanceProfileCommand, AddUserToGroupCommand, AttachGroupPolicyCommand, AttachRolePolicyCommand, AttachUserPolicyCommand, CreateAccessKeyCommand, CreateGroupCommand, CreateInstanceProfileCommand, CreateLoginProfileCommand, CreatePolicyCommand, CreatePolicyVersionCommand, CreateUserCommand, DeleteAccessKeyCommand, DeleteGroupCommand, DeleteGroupPolicyCommand, DeleteInstanceProfileCommand, DeleteLoginProfileCommand, DeletePolicyCommand, DeletePolicyVersionCommand, DeleteRolePolicyCommand, DeleteUserCommand, DeleteUserPermissionsBoundaryCommand, DeleteUserPolicyCommand, DetachGroupPolicyCommand, DetachRolePolicyCommand, DetachUserPolicyCommand, GetAccessKeyLastUsedCommand, GetGroupCommand, GetGroupPolicyCommand, GetInstanceProfileCommand, GetPolicyCommand, GetPolicyVersionCommand, GetRolePolicyCommand, GetUserCommand, GetUserPolicyCommand, IAMClient, ListAccessKeysCommand, ListAttachedGroupPoliciesCommand, ListAttachedUserPoliciesCommand, ListEntitiesForPolicyCommand, ListGroupPoliciesCommand, ListGroupsForUserCommand, ListPoliciesCommand, ListPolicyTagsCommand, ListPolicyVersionsCommand, ListUserPoliciesCommand, NoSuchEntityException, PutGroupPolicyCommand, PutRolePolicyCommand, PutUserPermissionsBoundaryCommand, PutUserPolicyCommand, RemoveRoleFromInstanceProfileCommand, RemoveUserFromGroupCommand, TagPolicyCommand, TagUserCommand, UntagPolicyCommand, UntagUserCommand, UpdateAccessKeyCommand, UpdateGroupCommand, UpdateLoginProfileCommand, UpdateUserCommand } from "@aws-sdk/client-iam";
@@ -63,7 +63,7 @@ import { CodeCommitClient, CreateCommitCommand, CreateRepositoryCommand as Creat
63
63
  import { CreateLifecyclePolicyCommand, DLMClient, DeleteLifecyclePolicyCommand as DeleteLifecyclePolicyCommand$1, GetLifecyclePoliciesCommand, GetLifecyclePolicyCommand as GetLifecyclePolicyCommand$1, ResourceNotFoundException as ResourceNotFoundException$16, TagResourceCommand as TagResourceCommand$26, UntagResourceCommand as UntagResourceCommand$27, UpdateLifecyclePolicyCommand } from "@aws-sdk/client-dlm";
64
64
  import { CreateVectorBucketCommand, DeleteIndexCommand, DeleteVectorBucketCommand, GetVectorBucketCommand, ListIndexesCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$18, S3VectorsClient, TagResourceCommand as TagResourceCommand$27, UntagResourceCommand as UntagResourceCommand$28 } from "@aws-sdk/client-s3vectors";
65
65
  import { ListTagsForResourceCommand as ListTagsForResourceCommand$19, S3ControlClient, TagResourceCommand as TagResourceCommand$28, UntagResourceCommand as UntagResourceCommand$29 } from "@aws-sdk/client-s3-control";
66
- import { CreateNamespaceCommand, CreateTableBucketCommand, CreateTableCommand as CreateTableCommand$2, DeleteNamespaceCommand as DeleteNamespaceCommand$1, DeleteTableBucketCommand, DeleteTableCommand as DeleteTableCommand$2, GetNamespaceCommand as GetNamespaceCommand$1, GetTableBucketCommand, GetTableCommand as GetTableCommand$1, ListNamespacesCommand as ListNamespacesCommand$1, ListTableBucketsCommand, ListTablesCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$20, NotFoundException as NotFoundException$7, RenameTableCommand, S3TablesClient, TagResourceCommand as TagResourceCommand$29, UntagResourceCommand as UntagResourceCommand$30 } from "@aws-sdk/client-s3tables";
66
+ import { CreateNamespaceCommand, CreateTableBucketCommand, CreateTableCommand as CreateTableCommand$2, DeleteNamespaceCommand as DeleteNamespaceCommand$1, DeleteTableBucketCommand, DeleteTableBucketMetricsConfigurationCommand, DeleteTableBucketReplicationCommand, DeleteTableCommand as DeleteTableCommand$2, GetNamespaceCommand as GetNamespaceCommand$1, GetTableBucketCommand, GetTableBucketEncryptionCommand, GetTableBucketMaintenanceConfigurationCommand, GetTableBucketMetricsConfigurationCommand, GetTableBucketReplicationCommand, GetTableBucketStorageClassCommand, GetTableCommand as GetTableCommand$1, GetTableMaintenanceConfigurationCommand, ListNamespacesCommand as ListNamespacesCommand$1, ListTableBucketsCommand, ListTablesCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$20, NotFoundException as NotFoundException$7, PutTableBucketEncryptionCommand, PutTableBucketMaintenanceConfigurationCommand, PutTableBucketMetricsConfigurationCommand, PutTableBucketReplicationCommand, PutTableBucketStorageClassCommand, PutTableMaintenanceConfigurationCommand, RenameTableCommand, S3TablesClient, TagResourceCommand as TagResourceCommand$29, UntagResourceCommand as UntagResourceCommand$30 } from "@aws-sdk/client-s3tables";
67
67
 
68
68
  //#region src/provisioning/providers/iam-policy-provider.ts
69
69
  const POLICY_NAME_SKIP_REASON = "no policy name in state — no delete issued";
@@ -11517,6 +11517,11 @@ var LambdaNetworkConnectorProvider = class {
11517
11517
  const tagList = refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, void 0, "Tags", DBPROXY_TAGS_WHAT, DBPROXY_TAG_OPTIONS);
11518
11518
  const name = typeof properties["Name"] === "string" && properties["Name"] !== "" ? properties["Name"] : generatedNameFor("AWS::Lambda::NetworkConnector", logicalId);
11519
11519
  const vpc = this.readVpcEgress(properties, logicalId, resourceType, void 0);
11520
+ if (declaredElasticIp(properties) !== void 0) {
11521
+ const message = elasticIpRefusalMessage(logicalId, "create");
11522
+ if (context?.replayingState !== true) throw new ProvisioningError(message, resourceType, logicalId);
11523
+ this.logger.warn(safeMsg`${message} Proceeding without it: this create replays a cdkd state record.`);
11524
+ }
11520
11525
  const createToken = acquireIdempotencyToken({
11521
11526
  scope: "CreateNetworkConnector",
11522
11527
  logicalId
@@ -11556,6 +11561,12 @@ var LambdaNetworkConnectorProvider = class {
11556
11561
  assertRegionMatch(context?.expectedRegion ? await this.client.config.region() : void 0, context?.expectedRegion, resourceType, logicalId, physicalId, "pre-update");
11557
11562
  refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId, "Tags", DBPROXY_TAGS_WHAT, DBPROXY_TAG_OPTIONS);
11558
11563
  const vpc = this.readVpcEgress(properties, logicalId, resourceType, physicalId);
11564
+ const desiredElasticIp = declaredElasticIp(properties);
11565
+ if (desiredElasticIp !== void 0 && !isDeepStrictEqual(desiredElasticIp, declaredElasticIp(previousProperties))) {
11566
+ const message = elasticIpRefusalMessage(logicalId, "update");
11567
+ if (context?.replayingState !== true && context?.desiredFromAwsReadback !== true) throw new ProvisioningError(message, resourceType, logicalId, physicalId);
11568
+ this.logger.warn(safeMsg`${message} Proceeding without it: this update restores a recorded or read-back configuration.`);
11569
+ }
11559
11570
  const updateRole = this.readOperatorRole(properties, logicalId, resourceType, physicalId, context);
11560
11571
  if (typeof previousProperties["OperatorRole"] === "string" && properties["OperatorRole"] === void 0 && context?.replayingState !== true && context?.desiredFromAwsReadback !== true) throw new ProvisioningError(`OperatorRole cannot be removed in place for Lambda network connector ${logicalIdShown(logicalId)}: cdkd sends no role when the template declares none, so the current one would stay attached. Set it to another role, or replace the connector (change its Name).`, resourceType, logicalId, physicalId);
11561
11572
  try {
@@ -11754,6 +11765,15 @@ var LambdaNetworkConnectorProvider = class {
11754
11765
  return markRedactedCause(build(`${failure.summary}${relayedNameCollision(failure.detail)}`));
11755
11766
  }
11756
11767
  };
11768
+ const ELASTIC_IP_KEY = "ElasticIpConfiguration";
11769
+ function declaredElasticIp(properties) {
11770
+ const config = properties["Configuration"];
11771
+ const vpc = isPlainRecord$3(config) ? config["VpcEgressConfiguration"] : void 0;
11772
+ return isPlainRecord$3(vpc) ? vpc[ELASTIC_IP_KEY] : void 0;
11773
+ }
11774
+ function elasticIpRefusalMessage(logicalId, mode) {
11775
+ return `AWS::Lambda::NetworkConnector ${logicalIdShown(logicalId)}: Configuration.VpcEgressConfiguration.${ELASTIC_IP_KEY} cannot be sent by cdkd yet — the AWS SDK for JavaScript (@aws-sdk/client-lambda-core) does not model the member, so it would be dropped from the ${mode === "create" ? "CreateNetworkConnector" : "UpdateNetworkConnector"} request without an error. Remove ${ELASTIC_IP_KEY} from Configuration.VpcEgressConfiguration to deploy the connector without it.`;
11776
+ }
11757
11777
  var TerminalConnectorStateError = class extends Error {};
11758
11778
  function buildAttributes(resp) {
11759
11779
  return definedAttributes({
@@ -11820,6 +11840,120 @@ async function waitForGoneAfterDelete(opts) {
11820
11840
  }
11821
11841
  }
11822
11842
 
11843
+ //#endregion
11844
+ //#region src/provisioning/dynamodb-vector-indexes.ts
11845
+ function vectorIndexesByName(value) {
11846
+ const out = /* @__PURE__ */ new Map();
11847
+ if (!Array.isArray(value)) return out;
11848
+ for (const entry of value) {
11849
+ if (typeof entry !== "object" || entry === null || Array.isArray(entry)) continue;
11850
+ const name = entry["IndexName"];
11851
+ if (typeof name === "string") out.set(name, entry);
11852
+ }
11853
+ return out;
11854
+ }
11855
+ function vectorIndexForSend(entry) {
11856
+ const out = {};
11857
+ for (const key of [
11858
+ "IndexName",
11859
+ "VectorAttribute",
11860
+ "Projection",
11861
+ "DistanceFunction"
11862
+ ]) if (entry[key] !== void 0) out[key] = entry[key];
11863
+ if (entry["Dimensions"] !== void 0) out["Dimensions"] = coerceCfnInteger(entry["Dimensions"]) ?? entry["Dimensions"];
11864
+ if (entry["SearchSchema"] !== void 0) out["SearchSchema"] = entry["SearchSchema"];
11865
+ return out;
11866
+ }
11867
+ function vectorIndexesForCreate(value) {
11868
+ if (value === void 0 || value === null) return void 0;
11869
+ if (!Array.isArray(value)) return value;
11870
+ return value.map((entry) => typeof entry === "object" && entry !== null && !Array.isArray(entry) ? vectorIndexForSend(entry) : entry);
11871
+ }
11872
+ function sortedByJson(list) {
11873
+ if (!Array.isArray(list)) return list;
11874
+ return [...list].sort((a, b) => {
11875
+ const x = JSON.stringify(a) ?? "";
11876
+ const y = JSON.stringify(b) ?? "";
11877
+ return x < y ? -1 : x > y ? 1 : 0;
11878
+ });
11879
+ }
11880
+ function vectorIndexKey(entry) {
11881
+ const e = entry;
11882
+ const projection = e["Projection"];
11883
+ const normalizedProjection = typeof projection === "object" && projection !== null && !Array.isArray(projection) ? {
11884
+ ProjectionType: projection["ProjectionType"],
11885
+ NonKeyAttributes: sortedByJson(nonEmpty(projection["NonKeyAttributes"]))
11886
+ } : projection;
11887
+ const attribute = e["VectorAttribute"];
11888
+ return JSON.stringify([
11889
+ e["IndexName"],
11890
+ typeof attribute === "object" && attribute !== null ? attribute["AttributeName"] : attribute,
11891
+ coerceCfnInteger(e["Dimensions"]) ?? e["Dimensions"],
11892
+ e["DistanceFunction"],
11893
+ normalizedProjection,
11894
+ sortedByJson(Array.isArray(e["SearchSchema"]) && e["SearchSchema"].length > 0 ? e["SearchSchema"].map((s) => typeof s === "object" && s !== null ? {
11895
+ AttributeName: s["AttributeName"],
11896
+ SearchSchemaElementType: s["SearchSchemaElementType"]
11897
+ } : s) : nonEmpty(e["SearchSchema"]))
11898
+ ]);
11899
+ }
11900
+ function nonEmpty(value) {
11901
+ return Array.isArray(value) && value.length === 0 ? void 0 : value;
11902
+ }
11903
+ function planVectorIndexUpdates(previous, desired, live) {
11904
+ const prevByName = vectorIndexesByName(previous);
11905
+ const desiredByName = vectorIndexesByName(desired);
11906
+ const liveByName = live === void 0 ? void 0 : new Map(live.filter((d) => typeof d.IndexName === "string").map((d) => [d.IndexName, d]));
11907
+ const plan = {
11908
+ ops: [],
11909
+ changed: [],
11910
+ adopted: [],
11911
+ alreadyGone: []
11912
+ };
11913
+ const liveHolds = (name, entry) => {
11914
+ const l = liveByName?.get(name);
11915
+ return l !== void 0 && l.IndexStatus !== "DELETING" && vectorIndexKey(l) === vectorIndexKey(entry);
11916
+ };
11917
+ for (const name of prevByName.keys()) {
11918
+ if (desiredByName.has(name)) continue;
11919
+ const l = liveByName?.get(name);
11920
+ if (liveByName !== void 0 && (l === void 0 || l.IndexStatus === "DELETING")) {
11921
+ plan.alreadyGone.push(name);
11922
+ continue;
11923
+ }
11924
+ plan.ops.push({ Delete: { IndexName: name } });
11925
+ }
11926
+ for (const [name, entry] of desiredByName) {
11927
+ const before = prevByName.get(name);
11928
+ if (before === void 0) {
11929
+ const l = liveByName?.get(name);
11930
+ if (l === void 0 || l.IndexStatus === "DELETING") plan.ops.push({ Create: vectorIndexForSend(entry) });
11931
+ else if (liveHolds(name, entry)) plan.adopted.push(name);
11932
+ else plan.changed.push(name);
11933
+ continue;
11934
+ }
11935
+ if (vectorIndexKey(before) === vectorIndexKey(entry)) continue;
11936
+ if (!liveHolds(name, entry)) plan.changed.push(name);
11937
+ }
11938
+ return plan;
11939
+ }
11940
+ function readbackVectorIndexes(live) {
11941
+ if (live === void 0 || live.length === 0) return void 0;
11942
+ return live.map((d) => {
11943
+ const out = {};
11944
+ if (d.IndexName !== void 0) out["IndexName"] = d.IndexName;
11945
+ if (d.VectorAttribute !== void 0) out["VectorAttribute"] = d.VectorAttribute;
11946
+ if (d.Dimensions !== void 0) out["Dimensions"] = d.Dimensions;
11947
+ if (d.DistanceFunction !== void 0) out["DistanceFunction"] = d.DistanceFunction;
11948
+ if (d.Projection !== void 0) out["Projection"] = d.Projection;
11949
+ if (d.SearchSchema !== void 0 && d.SearchSchema.length > 0) out["SearchSchema"] = d.SearchSchema;
11950
+ return out;
11951
+ });
11952
+ }
11953
+ function vectorIndexesSettled(live) {
11954
+ return (live ?? []).every((d) => d.IndexStatus === void 0 || d.IndexStatus === "ACTIVE");
11955
+ }
11956
+
11823
11957
  //#endregion
11824
11958
  //#region src/provisioning/providers/dynamodb-table-provider.ts
11825
11959
  function isTableName(id) {
@@ -12246,7 +12380,7 @@ var DynamoDBTableProvider = class {
12246
12380
  if (!failure.redacted) return wrapMaskedAwsError(m, error, build);
12247
12381
  this.logger.debug(m(build(m(failure.detail)).message));
12248
12382
  const relay = isAuxiliaryFailure(error) ? "" : relayedNameCollision(failure.detail);
12249
- const wrapped = build(`${m(failure.summary)}${relay}${relayedIndexBusyDelete(failure.detail)}`);
12383
+ const wrapped = build(`${m(failure.summary)}${relay}${relayedIndexBusyDelete(failure.detail, TABLE_INDEX_NOUN)}`);
12250
12384
  return error instanceof Error ? markRedactedCause(wrapped) : wrapped;
12251
12385
  }
12252
12386
  handledProperties = /* @__PURE__ */ new Map([["AWS::DynamoDB::Table", /* @__PURE__ */ new Set([
@@ -12268,7 +12402,8 @@ var DynamoDBTableProvider = class {
12268
12402
  "TimeToLiveSpecification",
12269
12403
  "ResourcePolicy",
12270
12404
  "KinesisStreamSpecification",
12271
- "ContributorInsightsSpecification"
12405
+ "ContributorInsightsSpecification",
12406
+ "VectorIndexes"
12272
12407
  ])]]);
12273
12408
  unhandledByDesign = /* @__PURE__ */ new Map([["AWS::DynamoDB::Table", /* @__PURE__ */ new Map([["ImportSourceSpecification", "S3 import uses the separate ImportTable API (not CreateTable) and is create-only with no readback; deferred to a dedicated import-from-S3 PR"]])]]);
12274
12409
  deleteBudgets = new ElapsedBudgetRegistry();
@@ -12342,6 +12477,8 @@ var DynamoDBTableProvider = class {
12342
12477
  const declaredGsis = properties["GlobalSecondaryIndexes"];
12343
12478
  createParams.GlobalSecondaryIndexes = Array.isArray(declaredGsis) ? declaredGsis.map((entry) => this.coerceIndexThroughputForCreate(logicalId, stripIndexContributorInsights(entry), maskSecrets)) : declaredGsis;
12344
12479
  }
12480
+ const createVectorIndexes = vectorIndexesForCreate(properties["VectorIndexes"]);
12481
+ if (createVectorIndexes !== void 0) createParams.VectorIndexes = createVectorIndexes;
12345
12482
  if (properties["LocalSecondaryIndexes"]) createParams.LocalSecondaryIndexes = properties["LocalSecondaryIndexes"];
12346
12483
  const sseCreateRefusal = sseSpecificationRefusal(properties["SSESpecification"], logicalId);
12347
12484
  if (sseCreateRefusal !== void 0 && context?.replayingState !== true) throw new ProvisioningError(`${maskSecrets(sseCreateRefusal)}. Nothing was created; fix the template value`, resourceType, logicalId);
@@ -12366,8 +12503,12 @@ var DynamoDBTableProvider = class {
12366
12503
  tableCreated = true;
12367
12504
  createdTableId = createOut?.TableDescription?.TableId;
12368
12505
  reportCreatedResource(logicalId, resourceType, tableName, createdTableId);
12369
- this.logger.debug(`CreateTable initiated for ${tableName}, waiting for ACTIVE status`);
12370
- const tableInfo = await timePhase("provider waits", "DynamoDB table: wait for ACTIVE", () => this.waitForTableActive(tableName), logicalId);
12506
+ debug(`CreateTable initiated for ${tableName}, waiting for ACTIVE status`);
12507
+ const tableInfo = await timePhase("provider waits", "DynamoDB table: wait for ACTIVE", () => this.waitForTableActive(tableName, maskSecrets), logicalId);
12508
+ if (createVectorIndexes !== void 0) await timePhase("provider waits", "DynamoDB table: wait for vector indexes", () => this.waitForTableAndIndexesActive(tableName, void 0, {
12509
+ after: "CreateTable",
12510
+ maskSecrets
12511
+ }), logicalId);
12371
12512
  await this.applyPointInTimeRecovery(tableName, properties["PointInTimeRecoverySpecification"], void 0, maskSecrets);
12372
12513
  await this.applyTimeToLive(tableName, properties["TimeToLiveSpecification"], void 0, "create", {
12373
12514
  logicalId,
@@ -12378,7 +12519,7 @@ var DynamoDBTableProvider = class {
12378
12519
  await this.applyContributorInsights(tableName, properties["ContributorInsightsSpecification"], void 0, maskSecrets);
12379
12520
  await this.applyIndexContributorInsights(tableName, properties["GlobalSecondaryIndexes"], void 0, maskSecrets);
12380
12521
  await this.applyStreamMembers(logicalId, resourceType, tableName, tableInfo.streamArn, properties["StreamSpecification"], void 0, true, maskSecrets);
12381
- this.logger.debug(`Successfully created DynamoDB table ${logicalId}: ${tableName}`);
12522
+ debug(`Successfully created DynamoDB table ${logicalId}: ${tableName}`);
12382
12523
  return {
12383
12524
  physicalId: tableName,
12384
12525
  attributes: {
@@ -12392,7 +12533,7 @@ var DynamoDBTableProvider = class {
12392
12533
  let tableLeftBehind = false;
12393
12534
  if (tableCreated) {
12394
12535
  try {
12395
- await this.dynamoDBClient.send(new DeleteTableCommand({ TableName: tableName }));
12536
+ await this.rollBackCreatedTable(logicalId, tableName, maskSecrets);
12396
12537
  retractCreatedResource(logicalId, resourceType, tableName);
12397
12538
  debug(`Rolled back partially-created DynamoDB table ${tableName}`);
12398
12539
  } catch (cleanupError) {
@@ -12410,6 +12551,38 @@ var DynamoDBTableProvider = class {
12410
12551
  throw thrown;
12411
12552
  }
12412
12553
  }
12554
+ async rollBackCreatedTable(logicalId, tableName, maskSecrets) {
12555
+ const logger = maskedLogger(this.logger, maskSecrets, tableName);
12556
+ const allowanceMs = Math.min(resolveDynamoDbDeleteBudgetMs(), enclosingDeadlineRemainingMs() - DYNAMODB_DELETE_DEADLINE_MARGIN_MS);
12557
+ const budget = allowanceMs > 0 ? new ElapsedBudget(allowanceMs, resolveDynamoDbDeleteBudgetClock()) : void 0;
12558
+ await deleteTableWithIndexBusyRetry({
12559
+ logicalId,
12560
+ physicalId: tableName,
12561
+ typeLabel: "table",
12562
+ indexNoun: TABLE_INDEX_NOUN,
12563
+ maxRetries: 14,
12564
+ logger,
12565
+ deleteTable: async () => {
12566
+ await this.dynamoDBClient.send(new DeleteTableCommand({ TableName: tableName }));
12567
+ },
12568
+ reArm: () => {
12569
+ const wait = beginDeleteWait(900, budget);
12570
+ return waitForIndexesSettled({
12571
+ tableName,
12572
+ logicalId,
12573
+ logger,
12574
+ describeTable: () => this.dynamoDBClient.send(new DescribeTableCommand({ TableName: tableName })),
12575
+ maxAttempts: wait.grantedPolls,
12576
+ budgetWait: wait,
12577
+ shortCapUnlessVectorBusy: 60,
12578
+ proceedNote: DELETE_INDEX_WAIT_PROCEED_NOTE
12579
+ });
12580
+ },
12581
+ shouldKeepRetrying: () => budget !== void 0 && !budget.isExhausted(),
12582
+ retryWarning: () => `DynamoDB table ${logicalId}: AWS refused the DeleteTable rolling back the partially-created table ${tableName} because ${TABLE_INDEX_NOUN} is still being created, updated or deleted. Waiting for the indexes to settle and retrying (up to ${14} retries in all, within ~${Math.max(1, Math.round((budget?.totalMs ?? 0) / 6e4))} minutes).`,
12583
+ sleepSeam: deleteTableRetryDelays
12584
+ });
12585
+ }
12413
12586
  async update(logicalId, physicalId, resourceType, properties, previousProperties, context) {
12414
12587
  const markUnsettled = (key) => context?.markUnsettled?.(key);
12415
12588
  const maskSecrets = context?.maskSecrets ?? ((text) => text);
@@ -12454,6 +12627,12 @@ var DynamoDBTableProvider = class {
12454
12627
  if (context?.replayingState !== true && context?.desiredFromAwsReadback !== true) throw new ProvisioningError(`${lsiMessage}. Nothing was applied to the table; revert the LocalSecondaryIndexes change, or create a new table under a new logical ID (a new table starts empty)`, resourceType, logicalId, physicalId);
12455
12628
  warn(`${lsiMessage}; the LocalSecondaryIndexes change was not applied`);
12456
12629
  }
12630
+ const vectorIndexPlan = JSON.stringify(properties["VectorIndexes"]) !== JSON.stringify(previousProperties["VectorIndexes"]) ? planVectorIndexUpdates(previousProperties["VectorIndexes"], properties["VectorIndexes"], table?.VectorIndexes ?? (table === void 0 ? void 0 : [])) : void 0;
12631
+ if (vectorIndexPlan !== void 0 && vectorIndexPlan.changed.length > 0) {
12632
+ const vectorMessage = `AWS::DynamoDB::Table ${logicalId}: VectorIndexes ${vectorIndexPlan.changed.map((n) => maskSecrets(n)).join(", ")} changed definition, which DynamoDB cannot modify in place`;
12633
+ if (context?.replayingState !== true && context?.desiredFromAwsReadback !== true) throw new ProvisioningError(`${maskSecrets(vectorMessage)}. Nothing was applied to the table; rename the index (so it is dropped and re-created) or revert the change`, resourceType, logicalId, physicalId);
12634
+ warn(`${vectorMessage}; that change was not applied`);
12635
+ }
12457
12636
  let latestStreamArn = table?.LatestStreamArn;
12458
12637
  if (table?.TableArn) await this.applyTagDiff(table.TableArn, resourceType, logicalId, previousProperties["Tags"], properties["Tags"], {
12459
12638
  forceUpsert: context?.unsettledProperties?.has("Tags") === true,
@@ -12572,7 +12751,7 @@ var DynamoDBTableProvider = class {
12572
12751
  if (tableClassChanged) markUnsettled("TableClass");
12573
12752
  if (updateInput.GlobalSecondaryIndexUpdates !== void 0) markUnsettled("GlobalSecondaryIndexes");
12574
12753
  await this.dynamoDBClient.send(new UpdateTableCommand(updateInput));
12575
- if (billingMode !== liveBillingMode) await this.waitForTableAndIndexesActive(physicalId, BILLING_FLIP_ACTIVE_WAIT_ATTEMPTS);
12754
+ if (billingMode !== liveBillingMode) await this.waitForTableAndIndexesActive(physicalId, BILLING_FLIP_ACTIVE_WAIT_ATTEMPTS, { maskSecrets });
12576
12755
  else await this.waitForTableActiveAfterUpdate(physicalId, 60);
12577
12756
  this.logger.debug(`Updated BillingMode/ProvisionedThroughput/TableClass on DynamoDB table ${physicalId}`);
12578
12757
  }
@@ -12687,6 +12866,7 @@ var DynamoDBTableProvider = class {
12687
12866
  markUnsettled("GlobalSecondaryIndexes");
12688
12867
  await this.applyGsiUpdates(physicalId, resourceType, logicalId, previousProperties["GlobalSecondaryIndexes"], properties["GlobalSecondaryIndexes"], properties["AttributeDefinitions"], gsiHandledByBillingFlip, currentLiveIndexNames, currentLiveIndexByName, liveCapacityComparable, effectiveBillingMode === "PAY_PER_REQUEST", maskSecrets, (indexName) => context?.markAttempted?.("GlobalSecondaryIndexes", [indexName]));
12689
12868
  }
12869
+ if (vectorIndexPlan !== void 0) await this.applyVectorIndexUpdates(physicalId, vectorIndexPlan, properties["AttributeDefinitions"], maskSecrets, () => markUnsettled("VectorIndexes"), (indexName) => context?.markAttempted?.("VectorIndexes", [indexName]));
12690
12870
  if (JSON.stringify(properties["PointInTimeRecoverySpecification"]) !== JSON.stringify(previousProperties["PointInTimeRecoverySpecification"])) {
12691
12871
  markUnsettled("PointInTimeRecoverySpecification");
12692
12872
  await this.applyPointInTimeRecovery(physicalId, properties["PointInTimeRecoverySpecification"], previousProperties["PointInTimeRecoverySpecification"], maskSecrets);
@@ -12802,16 +12982,18 @@ var DynamoDBTableProvider = class {
12802
12982
  }
12803
12983
  try {
12804
12984
  const reArmPolls = () => {
12805
- const wait = beginDeleteWait(60, budget);
12985
+ const wait = beginDeleteWait(900, budget);
12806
12986
  return {
12807
12987
  maxAttempts: wait.grantedPolls,
12808
- budgetWait: wait
12988
+ budgetWait: wait,
12989
+ shortCapUnlessVectorBusy: 60
12809
12990
  };
12810
12991
  };
12811
12992
  await deleteTableWithIndexBusyRetry({
12812
12993
  logicalId,
12813
12994
  physicalId,
12814
12995
  typeLabel: "table",
12996
+ indexNoun: TABLE_INDEX_NOUN,
12815
12997
  maxRetries: 14,
12816
12998
  logger: loopLogger,
12817
12999
  deleteTable: async () => {
@@ -13203,7 +13385,7 @@ var DynamoDBTableProvider = class {
13203
13385
  const warn = (message) => this.logger.warn(maskSecrets(message));
13204
13386
  const ops = planIndexContributorInsightsOps(desiredIndexes, previousIndexes, (indexName, reason) => warn(`${this.indexScopeAt(indexName, tableName, maskSecrets)}: ${reason}, so its Contributor Insights was left as it is. Fix the template value and re-deploy.`));
13205
13387
  if (ops.length === 0) return;
13206
- await this.waitForTableAndIndexesActive(tableName);
13388
+ await this.waitForTableAndIndexesActive(tableName, void 0, { maskSecrets });
13207
13389
  for (const op of ops) {
13208
13390
  beforeSend();
13209
13391
  await this.sendContributorInsightsOp(tableName, op, maskSecrets);
@@ -13220,11 +13402,11 @@ var DynamoDBTableProvider = class {
13220
13402
  })), `set ContributorInsights on ${target}`);
13221
13403
  debug(`Set ContributorInsightsAction=${op.action}${op.mode !== void 0 ? ` Mode=${op.mode}` : ""} on ${target}`);
13222
13404
  }
13223
- async waitForTableActive(tableName, maxAttempts = 60) {
13405
+ async waitForTableActive(tableName, maskSecrets, maxAttempts = 60) {
13224
13406
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
13225
13407
  const response = await this.dynamoDBClient.send(new DescribeTableCommand({ TableName: tableName }));
13226
13408
  const status = response.Table?.TableStatus;
13227
- this.logger.debug(`Table ${tableName} status: ${status} (attempt ${attempt}/${maxAttempts})`);
13409
+ this.logger.debug(maskSecrets(`Table ${tableName} status: ${status} (attempt ${attempt}/${maxAttempts})`));
13228
13410
  if (status === "ACTIVE") return {
13229
13411
  tableArn: response.Table?.TableArn,
13230
13412
  tableId: response.Table?.TableId,
@@ -13262,15 +13444,36 @@ var DynamoDBTableProvider = class {
13262
13444
  }
13263
13445
  throw new Error(maskSecrets(`DynamoDB table ${tableName} was still ${last ?? "unread"} ${KINESIS_DESTINATION_SETTLE_POLLS * KINESIS_DESTINATION_SETTLE_POLL_MS / 1e3} seconds after its encryption change`));
13264
13446
  }
13265
- async waitForTableAndIndexesActive(tableName, maxAttempts = 1800) {
13447
+ async waitForTableAndIndexesActive(tableName, maxAttempts = 1800, opts = {}) {
13266
13448
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
13267
13449
  const table = (await this.dynamoDBClient.send(new DescribeTableCommand({ TableName: tableName }))).Table;
13268
13450
  const tableActive = table?.TableStatus === "ACTIVE";
13269
13451
  const indexesActive = (table?.GlobalSecondaryIndexes ?? []).every((gsi) => gsi.IndexStatus === "ACTIVE");
13270
- if (tableActive && indexesActive) return;
13452
+ if (tableActive && indexesActive && vectorIndexesSettled(table?.VectorIndexes)) return;
13271
13453
  await new Promise((resolve) => setTimeout(resolve, 1e3));
13272
13454
  }
13273
- throw new Error(`Table ${tableName} and its global secondary indexes did not reach ACTIVE within ${maxAttempts} seconds after UpdateTable`);
13455
+ const m = maskerOrIdentity(opts.maskSecrets);
13456
+ throw new Error(m(`Table ${m(tableName)} and its indexes did not reach ACTIVE within ${maxAttempts} seconds after ${opts.after ?? "UpdateTable"}`));
13457
+ }
13458
+ async applyVectorIndexUpdates(physicalId, plan, desiredAttributeDefinitions, maskSecrets, beforeFirstOp, onCreated) {
13459
+ const debug = (message) => this.logger.debug(maskSecrets(message));
13460
+ const warn = (message) => this.logger.warn(maskSecrets(message));
13461
+ for (const name of plan.alreadyGone) debug(`${this.vectorIndexScopeAt(name, physicalId, maskSecrets)} is recorded in cdkd state but not live; skipping its Delete (already removed)`);
13462
+ for (const name of plan.adopted) warn(`${this.vectorIndexScopeAt(name, physicalId, maskSecrets)} already exists in AWS with the declared definition but is absent from cdkd's recorded previous state, so its Create is being skipped. This usually means an earlier deploy created the index and then failed before state was written.`);
13463
+ if (plan.ops.length === 0) return;
13464
+ await this.waitForTableAndIndexesActive(physicalId, void 0, { maskSecrets });
13465
+ beforeFirstOp();
13466
+ for (const op of plan.ops) {
13467
+ const input = {
13468
+ TableName: physicalId,
13469
+ VectorIndexUpdates: [op]
13470
+ };
13471
+ if (op.Create && desiredAttributeDefinitions) input.AttributeDefinitions = desiredAttributeDefinitions;
13472
+ await this.dynamoDBClient.send(new UpdateTableCommand(input));
13473
+ if (op.Create?.IndexName !== void 0) onCreated(op.Create.IndexName);
13474
+ await this.waitForTableAndIndexesActive(physicalId, void 0, { maskSecrets });
13475
+ debug(`${op.Create ? "created" : "deleted"} ` + this.vectorIndexScopeAt(op.Create?.IndexName ?? op.Delete?.IndexName, physicalId, maskSecrets));
13476
+ }
13274
13477
  }
13275
13478
  async applyGsiUpdates(physicalId, resourceType, logicalId, previousGsis, desiredGsis, desiredAttributeDefinitions, handledByBillingFlip, liveIndexNames, liveIndexByName, liveCapacityComparable, onDemandCeilingsSendable, maskSecrets, onCreated = () => void 0) {
13276
13479
  const warn = (message) => this.logger.warn(maskSecrets(message));
@@ -13374,6 +13577,9 @@ var DynamoDBTableProvider = class {
13374
13577
  this.logger.warn(maskSecrets(`${this.indexScopeAt(name, physicalId, maskSecrets)} is live, but neither cdkd's record nor the template declares it, so cdkd left it in place while converging the unsettled GlobalSecondaryIndexes (CloudFormation never deletes an index it did not record). It may belong to another tool, or an earlier failed cdkd update may have created it; cdkd cannot tell which. If it should not exist, delete it ` + (secretDerived ? `with an UpdateTable GlobalSecondaryIndexUpdates Delete for the index.` : `with: aws dynamodb update-table --table-name ${physicalId} --global-secondary-index-updates '[{"Delete":{"IndexName":"${name}"}}]' (in the table's region)`)));
13375
13578
  }
13376
13579
  }
13580
+ vectorIndexScopeAt(indexName, physicalId, maskSecrets) {
13581
+ return `vector index ${typeof indexName === "string" ? maskSecrets(indexName) : "<unnamed>"} on DynamoDB table ${maskSecrets(physicalId)}`;
13582
+ }
13377
13583
  indexScopeAt(indexName, physicalId, maskSecrets) {
13378
13584
  return `GSI ${typeof indexName === "string" ? maskSecrets(indexName) : "<unnamed>"} on DynamoDB table ${physicalId}`;
13379
13585
  }
@@ -13521,7 +13727,7 @@ var DynamoDBTableProvider = class {
13521
13727
  if (op.Create && desiredAttributeDefinitions) input.AttributeDefinitions = desiredAttributeDefinitions;
13522
13728
  await this.dynamoDBClient.send(new UpdateTableCommand(input));
13523
13729
  if (op.Create?.IndexName !== void 0) onCreated(op.Create.IndexName);
13524
- await this.waitForTableAndIndexesActive(physicalId);
13730
+ await this.waitForTableAndIndexesActive(physicalId, void 0, { maskSecrets });
13525
13731
  debug(`${op.Create ? "created" : op.Delete ? "deleted" : "updated"} ${this.indexScopeAt(op.Create?.IndexName ?? op.Delete?.IndexName ?? op.Update?.IndexName, physicalId, maskSecrets)}`);
13526
13732
  }
13527
13733
  }
@@ -13583,7 +13789,8 @@ var DynamoDBTableProvider = class {
13583
13789
  return [
13584
13790
  "AttributeDefinitions",
13585
13791
  "GlobalSecondaryIndexes[]",
13586
- "LocalSecondaryIndexes[]"
13792
+ "LocalSecondaryIndexes[]",
13793
+ "VectorIndexes"
13587
13794
  ];
13588
13795
  }
13589
13796
  getDriftUnknownPaths(resourceType, properties) {
@@ -13670,6 +13877,10 @@ var DynamoDBTableProvider = class {
13670
13877
  out["GlobalSecondaryIndexes"] = projectIndexesOnto(out["GlobalSecondaryIndexes"], recordedProperties?.["GlobalSecondaryIndexes"], desiredProperties?.["GlobalSecondaryIndexes"], attemptedItems?.get("GlobalSecondaryIndexes"));
13671
13878
  if (out["GlobalSecondaryIndexes"] === void 0) delete out["GlobalSecondaryIndexes"];
13672
13879
  }
13880
+ if (names.has("VectorIndexes")) {
13881
+ out["VectorIndexes"] = projectIndexesOnto(out["VectorIndexes"], recordedProperties?.["VectorIndexes"], desiredProperties?.["VectorIndexes"], attemptedItems?.get("VectorIndexes"));
13882
+ if (out["VectorIndexes"] === void 0) delete out["VectorIndexes"];
13883
+ }
13673
13884
  const strict = async (key, read) => {
13674
13885
  if (!names.has(key)) return;
13675
13886
  const value = await read();
@@ -13758,6 +13969,8 @@ var DynamoDBTableProvider = class {
13758
13969
  const desiredByName = desiredIndexEntriesByName(properties?.["LocalSecondaryIndexes"]);
13759
13970
  result["LocalSecondaryIndexes"] = table.LocalSecondaryIndexes.map((live) => reverseMapSecondaryIndex(live, live.IndexName === void 0 ? void 0 : desiredByName.get(live.IndexName), bagInformative));
13760
13971
  }
13972
+ const liveVectorIndexes = readbackVectorIndexes(table.VectorIndexes);
13973
+ if (liveVectorIndexes !== void 0) result["VectorIndexes"] = liveVectorIndexes;
13761
13974
  if (table.SSEDescription?.Status === "ENABLED") {
13762
13975
  const sse = { SSEEnabled: true };
13763
13976
  if (table.SSEDescription.KMSMasterKeyArn !== void 0) sse["KMSMasterKeyId"] = table.SSEDescription.KMSMasterKeyArn;
@@ -22917,6 +23130,20 @@ var ApiGatewayV2Provider = class ApiGatewayV2Provider {
22917
23130
  ])]
22918
23131
  ]);
22919
23132
  removalDefaults = /* @__PURE__ */ new Map([["AWS::ApiGatewayV2::Authorizer", /* @__PURE__ */ new Map([["IdentitySource", []]])]]);
23133
+ removalHandledInUpdate = /* @__PURE__ */ new Map([["AWS::ApiGatewayV2::Route", /* @__PURE__ */ new Set([
23134
+ "ApiId",
23135
+ "RouteKey",
23136
+ "AuthorizationScopes",
23137
+ "Target",
23138
+ "AuthorizationType",
23139
+ "AuthorizerId",
23140
+ "OperationName",
23141
+ "ApiKeyRequired",
23142
+ "RequestModels",
23143
+ "RequestParameters",
23144
+ "ModelSelectionExpression",
23145
+ "RouteResponseSelectionExpression"
23146
+ ])]]);
22920
23147
  unhandledByDesign = /* @__PURE__ */ new Map([["AWS::ApiGatewayV2::Api", /* @__PURE__ */ new Map([
22921
23148
  ["Body", "OpenAPI/Swagger inline spec; routed through ImportApi, not the field-by-field CreateApi path."],
22922
23149
  ["BodyS3Location", "OpenAPI/Swagger spec on S3; routed through ImportApi, not the field-by-field CreateApi path."],
@@ -23954,12 +24181,15 @@ var ApiGatewayV2Provider = class ApiGatewayV2Provider {
23954
24181
  input.OperationName = properties["OperationName"];
23955
24182
  changed = true;
23956
24183
  }
23957
- {
24184
+ if (restoreFromAws) {
23958
24185
  const r = this.clearableUpdate(properties["ApiKeyRequired"], previousProperties["ApiKeyRequired"], false);
23959
24186
  if (r.changed) {
23960
24187
  input.ApiKeyRequired = r.value;
23961
24188
  changed = true;
23962
24189
  }
24190
+ } else if (properties["ApiKeyRequired"] !== void 0 && properties["ApiKeyRequired"] !== previousProperties["ApiKeyRequired"]) {
24191
+ input.ApiKeyRequired = properties["ApiKeyRequired"];
24192
+ changed = true;
23963
24193
  }
23964
24194
  if (restoreFromAws) {
23965
24195
  const merged = this.mapWithRemovals(properties["RequestModels"], previousProperties["RequestModels"]);
@@ -26412,6 +26642,60 @@ function isEcsErrorNamed(error, names) {
26412
26642
  return typeof name === "string" && names.includes(name);
26413
26643
  }
26414
26644
  const settleRolloutDelays = { sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)) };
26645
+ function requestedRolloutOf(service) {
26646
+ if (!service) return void 0;
26647
+ const primary = service.deployments?.find((d) => d.status === "PRIMARY");
26648
+ const deploymentId = typeof primary?.id === "string" && primary.id ? primary.id : void 0;
26649
+ const taskDefinitionRaw = primary?.taskDefinition ?? service.taskDefinition;
26650
+ const taskDefinition = typeof taskDefinitionRaw === "string" && taskDefinitionRaw ? taskDefinitionRaw : void 0;
26651
+ if (deploymentId === void 0 && taskDefinition === void 0) return void 0;
26652
+ return {
26653
+ deploymentId,
26654
+ taskDefinition
26655
+ };
26656
+ }
26657
+ function failedRequestedDeployment(requested, deployments) {
26658
+ if (!Array.isArray(deployments)) return void 0;
26659
+ const target = requested?.deploymentId !== void 0 ? deployments.find((d) => d?.id === requested.deploymentId) : deployments.find((d) => d?.status === "PRIMARY");
26660
+ return target?.rolloutState === "FAILED" ? target : void 0;
26661
+ }
26662
+ function taskDefinitionRevision(arn) {
26663
+ const match = typeof arn === "string" ? /:task-definition\/[^:]+:(\d+)$/.exec(arn) : null;
26664
+ return match ? match[1] : void 0;
26665
+ }
26666
+ function describeRollout(rollout) {
26667
+ const revision = taskDefinitionRevision(rollout.taskDefinition);
26668
+ const id = typeof rollout.id === "string" && /^ecs-svc\/\d+$/.test(rollout.id) ? rollout.id : void 0;
26669
+ if (id && revision) return `deployment ${id} (task definition revision ${revision})`;
26670
+ if (id) return `deployment ${id}`;
26671
+ if (revision) return `task definition revision ${revision}`;
26672
+ return "another deployment";
26673
+ }
26674
+ var EcsCircuitBreakerVerdict = class extends Error {
26675
+ constructor(message) {
26676
+ super(message);
26677
+ this.name = "EcsCircuitBreakerVerdict";
26678
+ }
26679
+ };
26680
+ function wrapBreakerFailedError(failed) {
26681
+ return new EcsCircuitBreakerVerdict(`its deployment circuit breaker failed the rollout of ${describeRollout(failed)} (deployment FAILED). The new tasks failed to start or failed their health checks`);
26682
+ }
26683
+ function controllerSkipsWait(properties) {
26684
+ let type;
26685
+ try {
26686
+ type = readConfigString(properties["DeploymentController"], "Type", "ECS", "DeploymentController");
26687
+ } catch {
26688
+ return "its DeploymentController could not be read";
26689
+ }
26690
+ if (type === "ECS") return void 0;
26691
+ if (type === "CODE_DEPLOY" || type === "EXTERNAL") return `its DeploymentController is ${type}, which ECS does not settle`;
26692
+ return "its DeploymentController type is not one cdkd can settle";
26693
+ }
26694
+ function rolloutSupersededBy(requested, settled) {
26695
+ if (!requested || !settled) return void 0;
26696
+ if (requested.deploymentId !== void 0 && typeof settled.id === "string" && settled.id) return settled.id === requested.deploymentId ? void 0 : describeRollout(settled);
26697
+ if (requested.taskDefinition !== void 0 && typeof settled.taskDefinition === "string" && settled.taskDefinition) return settled.taskDefinition === requested.taskDefinition ? void 0 : describeRollout(settled);
26698
+ }
26415
26699
  function markNotGoneOnNotFoundClass$1(error, wrapped) {
26416
26700
  return error instanceof Error && error.name.includes("NotFound") ? markNotGone(wrapped) : wrapped;
26417
26701
  }
@@ -26561,7 +26845,7 @@ var ECSProvider = class {
26561
26845
  switch (resourceType) {
26562
26846
  case "AWS::ECS::Cluster": return this.createCluster(logicalId, resourceType, properties, this.operationSinks(context, [[properties["ClusterName"], properties["ClusterName"]]]));
26563
26847
  case "AWS::ECS::TaskDefinition": return this.createTaskDefinition(logicalId, resourceType, properties, this.operationSinks(context, [[properties["Family"], properties["Family"]]]));
26564
- case "AWS::ECS::Service": return this.createService(logicalId, resourceType, properties, this.operationSinks(context, [[properties["ServiceName"], properties["ServiceName"]], [properties["Cluster"], clusterNameOfRef(properties["Cluster"])]]));
26848
+ case "AWS::ECS::Service": return this.createService(logicalId, resourceType, properties, this.operationSinks(context, [[properties["ServiceName"], properties["ServiceName"]], [properties["Cluster"], clusterNameOfRef(properties["Cluster"])]]), context?.replayingState === true);
26565
26849
  default: throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId);
26566
26850
  }
26567
26851
  }
@@ -26578,7 +26862,7 @@ var ECSProvider = class {
26578
26862
  [properties["Cluster"], recordedCluster],
26579
26863
  [previousProperties["Cluster"], recordedCluster],
26580
26864
  [properties["Cluster"], clusterNameOfRef(properties["Cluster"])]
26581
- ]), context?.desiredFromAwsReadback === true);
26865
+ ]), context?.desiredFromAwsReadback === true, context?.replayingState === true);
26582
26866
  }
26583
26867
  default: throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId, physicalId);
26584
26868
  }
@@ -26798,14 +27082,15 @@ var ECSProvider = class {
26798
27082
  default: return;
26799
27083
  }
26800
27084
  }
26801
- async createService(logicalId, resourceType, properties, log) {
27085
+ async createService(logicalId, resourceType, properties, log, replayingState) {
26802
27086
  log.debug(`Creating ECS service ${logicalId}`);
26803
27087
  const desiredTags = refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId);
26804
27088
  const client = this.getClient();
26805
27089
  const serviceName = properties["ServiceName"] || generatedNameFor("AWS::ECS::Service", logicalId);
26806
27090
  let survivorArn;
26807
27091
  try {
26808
- const heldBefore = process.env["CDKD_FULL_WAIT"] === "true" ? await nameHeldBefore(() => this.serviceNameHeld(properties["Cluster"], serviceName), (error) => hasErrorName(error, ["ClusterNotFoundException"])) : "free";
27092
+ const skipReason = controllerSkipsWait(properties);
27093
+ const heldBefore = process.env["CDKD_NO_WAIT"] !== "true" && skipReason === void 0 && !replayingState ? await nameHeldBefore(() => this.serviceNameHeld(properties["Cluster"], serviceName), (error) => hasErrorName(error, ["ClusterNotFoundException"])) : "free";
26809
27094
  const service = (await client.send(new CreateServiceCommand({
26810
27095
  cluster: properties["Cluster"],
26811
27096
  serviceName,
@@ -26838,8 +27123,18 @@ var ECSProvider = class {
26838
27123
  log.debug(`Successfully created ECS service ${logicalId}: ${service.serviceArn}`);
26839
27124
  if (heldBefore === "free") reportCreatedResource(logicalId, resourceType, service.serviceArn);
26840
27125
  try {
26841
- await this.settleService(logicalId, service.serviceName ?? service.serviceArn, properties["Cluster"], log);
27126
+ await this.settleService(logicalId, service.serviceName ?? service.serviceArn, properties["Cluster"], log, requestedRolloutOf(service), skipReason);
26842
27127
  } catch (waitError) {
27128
+ if (replayingState) {
27129
+ log.warn(`${this.wrapSteadyStateError(logicalId, waitError, properties["Cluster"], log, false).message} Continuing the rollback: the restored service stays recorded.`);
27130
+ return {
27131
+ physicalId: service.serviceArn,
27132
+ attributes: {
27133
+ ServiceArn: service.serviceArn,
27134
+ Name: service.serviceName
27135
+ }
27136
+ };
27137
+ }
26843
27138
  const aws = pasteableAwsCommand(log.mask);
26844
27139
  const cleanupCluster = properties["Cluster"];
26845
27140
  const clusterArg = cleanupCluster ? aws` --cluster ${cleanupCluster}` : aws``;
@@ -26861,10 +27156,7 @@ var ECSProvider = class {
26861
27156
  if (cleanupFailure.redacted) log.debug(`${cleanupHead}${cleanupFailure.detail}`);
26862
27157
  log.warn(`${cleanupHead}${cleanupFailure.redacted ? `${cleanupFailure.summary} ` : `${cleanupFailure.detail}. `}Manual deletion may be required before the next deploy: ${deleteCommand.render()}`);
26863
27158
  }
26864
- const waitFailure = describeAwsFailure(waitError);
26865
- if (waitFailure.redacted) log.debug(`ECS service ${logicalId} steady-state wait failed: ${waitFailure.detail}`);
26866
- const steadyStateError = new Error(`ECS service ${logicalIdShown(logicalId)} did not reach steady state under --full-wait: ${waitFailure.summary.replace(/\.$/, "")}. Inspect why its tasks stopped (stopped tasks stay visible for about an hour): ${listStopped.render()}, then ${aws`aws ecs describe-tasks${clusterArg} --tasks '<task-arn>' --query 'tasks[].[stoppedReason,containers[].reason]'`.render()}`, { cause: waitError });
26867
- throw waitFailure.redacted ? markRedactedCause(steadyStateError) : steadyStateError;
27159
+ throw this.wrapSteadyStateError(logicalId, waitError, properties["Cluster"], log);
26868
27160
  }
26869
27161
  return {
26870
27162
  physicalId: service.serviceArn,
@@ -26907,30 +27199,68 @@ var ECSProvider = class {
26907
27199
  reduced.name = error.name;
26908
27200
  return markRedactedCause(reduced);
26909
27201
  }
26910
- async settleService(logicalId, serviceRef, cluster, log) {
26911
- if (process.env["CDKD_FULL_WAIT"] === "true") {
27202
+ wrapSteadyStateError(logicalId, waitError, cluster, log, offerNoWait = true) {
27203
+ const aws = pasteableAwsCommand(log.mask);
27204
+ const clusterArg = cluster ? aws` --cluster ${cluster}` : aws``;
27205
+ const listStopped = aws`aws ecs list-tasks${clusterArg} --desired-status STOPPED`;
27206
+ const waitFailure = describeAwsFailure(waitError);
27207
+ if (waitFailure.redacted) log.debug(`ECS service ${logicalId} steady-state wait failed: ${waitFailure.detail}`);
27208
+ const flagsAvailable = offerNoWait && process.env["CDKD_WAIT_FLAGS_AVAILABLE"] === "true";
27209
+ const timeoutHint = flagsAvailable && !(waitError instanceof EcsCircuitBreakerVerdict) ? ` To wait longer, raise the limit with --resource-timeout AWS::ECS::Service=${commandHole("duration")}.` : "";
27210
+ const noWaitHint = flagsAvailable ? " To deploy without waiting for steady state, pass --no-wait." : "";
27211
+ const steadyStateError = new Error(`ECS service ${logicalIdShown(logicalId)} did not reach steady state: ${waitFailure.summary.replace(/\.$/, "")}. Inspect why its tasks stopped (stopped tasks stay visible for about an hour): ${listStopped.render()}, then ${aws`aws ecs describe-tasks${clusterArg} --tasks '<task-arn>' --query 'tasks[].[stoppedReason,containers[].reason]'`.render()}.${timeoutHint}${noWaitHint}`, { cause: waitError });
27212
+ return waitFailure.redacted ? markRedactedCause(steadyStateError) : steadyStateError;
27213
+ }
27214
+ async settleService(logicalId, serviceRef, cluster, log, requested, skipReason) {
27215
+ if (skipReason !== void 0) {
27216
+ this.logger.info(log.mask(`ECS service ${logicalIdShown(logicalId)} accepted (not waiting for steady state: ${skipReason}).`));
27217
+ return;
27218
+ }
27219
+ if (process.env["CDKD_NO_WAIT"] !== "true") {
26912
27220
  log.debug(`Waiting for ECS service ${logicalId} to reach steady state...`);
26913
27221
  const maxWaitTime = Math.max(600, (resolvedResourceTimeoutMs("AWS::ECS::Service") ?? 0) / 1e3);
27222
+ const client = this.getClient();
27223
+ const breakerVerdict = new AbortController();
27224
+ let failedRollout;
27225
+ const watchedClient = { send: async (command) => {
27226
+ const output = await client.send(command);
27227
+ if (failedRollout === void 0) {
27228
+ failedRollout = failedRequestedDeployment(requested, output?.services?.[0]?.deployments);
27229
+ if (failedRollout !== void 0) breakerVerdict.abort();
27230
+ }
27231
+ return output;
27232
+ } };
26914
27233
  try {
26915
27234
  await waitUntilServicesStable({
26916
- client: this.getClient(),
27235
+ client: watchedClient,
26917
27236
  maxWaitTime,
26918
27237
  minDelay: 5,
26919
- maxDelay: 10
27238
+ maxDelay: 10,
27239
+ abortSignal: breakerVerdict.signal
26920
27240
  }, {
26921
27241
  cluster,
26922
27242
  services: [serviceRef]
26923
27243
  });
26924
27244
  } catch (waiterError) {
27245
+ if (failedRollout !== void 0) {
27246
+ log.debug(`ECS service ${logicalId} deployment ${failedRollout.id ?? "(no id)"} FAILED: ${failedRollout.rolloutStateReason ?? "(no rollout reason)"}`);
27247
+ throw wrapBreakerFailedError(failedRollout);
27248
+ }
26925
27249
  throw this.wrapWaiterResultError(waiterError, logicalId, log);
26926
27250
  }
27251
+ if (failedRollout !== void 0) throw wrapBreakerFailedError(failedRollout);
26927
27252
  const rolloutDeadline = Date.now() + 12e4;
27253
+ let settledDeployment;
26928
27254
  for (;;) {
26929
27255
  const deployments = (await this.getClient().send(new DescribeServicesCommand({
26930
27256
  cluster,
26931
27257
  services: [serviceRef]
26932
27258
  })))?.services?.[0]?.deployments;
26933
- const rolloutState = deployments && deployments.length === 1 ? deployments[0]?.rolloutState : void 0;
27259
+ const failedNow = failedRequestedDeployment(requested, deployments);
27260
+ if (failedNow !== void 0) throw wrapBreakerFailedError(failedNow);
27261
+ settledDeployment = deployments && deployments.length === 1 ? deployments[0] : void 0;
27262
+ const rolloutState = settledDeployment?.rolloutState;
27263
+ if (settledDeployment !== void 0 && rolloutState === "FAILED") throw wrapBreakerFailedError(settledDeployment);
26934
27264
  if (rolloutState === void 0 || rolloutState === "COMPLETED") break;
26935
27265
  if (Date.now() >= rolloutDeadline) {
26936
27266
  log.warn(`ECS service ${logicalId} is steady but its rollout is still ${rolloutState} after the post-stability grace window; continuing`);
@@ -26938,15 +27268,22 @@ var ECSProvider = class {
26938
27268
  }
26939
27269
  await settleRolloutDelays.sleep(3e3);
26940
27270
  }
27271
+ const supersededBy = rolloutSupersededBy(requested, settledDeployment);
27272
+ if (supersededBy !== void 0) {
27273
+ log.debug(`ECS service ${logicalId} settled deployment ${settledDeployment?.id ?? "(no id)"}: ${settledDeployment?.rolloutStateReason ?? "(no rollout reason)"}`);
27274
+ throw new EcsCircuitBreakerVerdict(`its deployment circuit breaker rolled the rollout back: the service settled on ${supersededBy}, not on the deployment this update started (${describeRollout({
27275
+ id: requested.deploymentId,
27276
+ taskDefinition: requested.taskDefinition
27277
+ })}). The new tasks failed to start or failed their health checks`);
27278
+ }
26941
27279
  log.debug(`ECS service ${logicalId} reached steady state`);
26942
27280
  return;
26943
27281
  }
26944
27282
  const aws = pasteableAwsCommand(log.mask);
26945
27283
  const clusterArg = cluster ? aws` --cluster ${cluster}` : aws``;
26946
- const fullWaitHint = process.env["CDKD_WAIT_FLAGS_AVAILABLE"] === "true" ? "; pass --full-wait to wait" : "";
26947
- this.logger.info(log.mask(`ECS service ${logicalIdShown(logicalId)} accepted (not waiting for steady state${fullWaitHint}). To wait manually: ${aws`aws ecs wait services-stable${clusterArg} --services ${serviceRef}`.render()}`));
27284
+ this.logger.info(log.mask(`ECS service ${logicalIdShown(logicalId)} accepted (not waiting for steady state under --no-wait). To wait manually: ${aws`aws ecs wait services-stable${clusterArg} --services ${serviceRef}`.render()}`));
26948
27285
  }
26949
- async updateService(logicalId, physicalId, resourceType, properties, previousProperties, log, desiredFromAwsReadback) {
27286
+ async updateService(logicalId, physicalId, resourceType, properties, previousProperties, log, desiredFromAwsReadback, replayingState) {
26950
27287
  log.debug(`Updating ECS service ${logicalId}: ${physicalId}`);
26951
27288
  refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId);
26952
27289
  const client = this.getClient();
@@ -27016,7 +27353,12 @@ var ECSProvider = class {
27016
27353
  forceNewDeployment: forceNewDeploymentInput
27017
27354
  }))).service;
27018
27355
  if (service?.serviceArn) await this.applyTagDiff(service.serviceArn, resourceType, logicalId, previousProperties["Tags"], properties["Tags"], log);
27019
- await this.settleService(logicalId, service?.serviceName ?? physicalId, properties["Cluster"], log);
27356
+ try {
27357
+ await this.settleService(logicalId, service?.serviceName ?? physicalId, properties["Cluster"], log, requestedRolloutOf(service), desiredFromAwsReadback ? "a drift revert does not wait for it" : controllerSkipsWait(properties));
27358
+ } catch (waitError) {
27359
+ if (replayingState) log.warn(`${this.wrapSteadyStateError(logicalId, waitError, properties["Cluster"], log, false).message} The rollback update was applied; continuing.`);
27360
+ else throw this.wrapSteadyStateError(logicalId, waitError, properties["Cluster"], log);
27361
+ }
27020
27362
  return {
27021
27363
  physicalId,
27022
27364
  wasReplaced: false,
@@ -29360,6 +29702,7 @@ const POLL_INTERVAL_MS$1 = 5e3;
29360
29702
  const POLL_TIMEOUT_MS$1 = 18e5;
29361
29703
  const RETAINED_ON_REMOVAL = [
29362
29704
  "Auth",
29705
+ "DefaultAuthScheme",
29363
29706
  "RequireTLS",
29364
29707
  "IdleClientTimeout",
29365
29708
  "DebugLogging",
@@ -29371,7 +29714,14 @@ const CFN_KEEPS_ON_REMOVAL$1 = /* @__PURE__ */ new Set([
29371
29714
  "DebugLogging",
29372
29715
  "VpcSecurityGroupIds"
29373
29716
  ]);
29374
- const authRemovalRefused = (properties) => {
29717
+ const authRemovalRefused = (properties, previousProperties) => authRequired({ DefaultAuthScheme: properties["DefaultAuthScheme"] !== void 0 ? properties["DefaultAuthScheme"] : previousProperties["DefaultAuthScheme"] });
29718
+ const leavesProxyWithoutAuth = (properties, previousProperties) => {
29719
+ const desired = properties["Auth"];
29720
+ const declaredEmpty = desired === null || Array.isArray(desired) && desired.length === 0;
29721
+ if (properties["DefaultAuthScheme"] === "NONE" && previousProperties["DefaultAuthScheme"] !== "NONE" && (desired === void 0 || declaredEmpty)) return true;
29722
+ return declaredEmpty && JSON.stringify(desired) !== JSON.stringify(previousProperties["Auth"]) && authRemovalRefused(properties, previousProperties);
29723
+ };
29724
+ const authRequired = (properties) => {
29375
29725
  const scheme = properties["DefaultAuthScheme"];
29376
29726
  return scheme === void 0 || scheme === "NONE";
29377
29727
  };
@@ -29391,6 +29741,9 @@ var RDSDBProxyProvider = class {
29391
29741
  "RequireTLS",
29392
29742
  "IdleClientTimeout",
29393
29743
  "DebugLogging",
29744
+ "DefaultAuthScheme",
29745
+ "EndpointNetworkType",
29746
+ "TargetConnectionNetworkType",
29394
29747
  "Tags"
29395
29748
  ])]]);
29396
29749
  getClient() {
@@ -29417,18 +29770,21 @@ var RDSDBProxyProvider = class {
29417
29770
  const engineFamily = properties["EngineFamily"];
29418
29771
  if (!engineFamily) throw new ProvisioningError(`EngineFamily is required for AWS::RDS::DBProxy ${logicalId}`, resourceType, logicalId);
29419
29772
  const auth = properties["Auth"];
29420
- if (!auth || auth.length === 0) throw new ProvisioningError(`Auth (at least one entry) is required for AWS::RDS::DBProxy ${logicalId}`, resourceType, logicalId);
29773
+ if ((!auth || auth.length === 0) && authRequired(properties)) throw new ProvisioningError(`Auth (at least one entry) is required for AWS::RDS::DBProxy ${logicalId} while DefaultAuthScheme is NONE or unset`, resourceType, logicalId);
29421
29774
  const roleArn = properties["RoleArn"];
29422
29775
  if (!roleArn) throw new ProvisioningError(`RoleArn is required for AWS::RDS::DBProxy ${logicalId}`, resourceType, logicalId);
29423
29776
  const vpcSubnetIds = properties["VpcSubnetIds"];
29424
29777
  if (!vpcSubnetIds || vpcSubnetIds.length === 0) throw new ProvisioningError(`VpcSubnetIds (at least one) is required for AWS::RDS::DBProxy ${logicalId}`, resourceType, logicalId);
29425
29778
  const client = this.getClient();
29426
- this.logger.debug(`Creating DBProxy ${dbProxyName} (${engineFamily})`);
29779
+ this.logger.debug(mask(`Creating DBProxy ${dbProxyName} (${engineFamily})`));
29427
29780
  try {
29428
29781
  await this.getCreateClient().send(new CreateDBProxyCommand({
29429
29782
  DBProxyName: dbProxyName,
29430
29783
  EngineFamily: engineFamily,
29431
- Auth: auth,
29784
+ Auth: auth && auth.length > 0 ? auth : void 0,
29785
+ DefaultAuthScheme: properties["DefaultAuthScheme"],
29786
+ EndpointNetworkType: properties["EndpointNetworkType"],
29787
+ TargetConnectionNetworkType: properties["TargetConnectionNetworkType"],
29432
29788
  RoleArn: roleArn,
29433
29789
  VpcSubnetIds: vpcSubnetIds,
29434
29790
  VpcSecurityGroupIds: properties["VpcSecurityGroupIds"],
@@ -29480,13 +29836,16 @@ var RDSDBProxyProvider = class {
29480
29836
  }
29481
29837
  async update(logicalId, physicalId, resourceType, properties, previousProperties, context) {
29482
29838
  refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId, "Tags", DBPROXY_TAGS_WHAT, DBPROXY_TAG_OPTIONS);
29483
- if (context?.replayingState !== true && context?.desiredFromAwsReadback !== true && this.removedRetained(properties, previousProperties, context).includes("Auth") && authRemovalRefused(properties)) throw markNonRetryable(new ProvisioningError(safeMsg`${logicalId} (${resourceType}): Auth was removed from the template, but AWS requires Auth while DefaultAuthScheme is NONE or unset, and CloudFormation's update fails on the same change. Declare Auth again; nothing was changed.`, resourceType, logicalId, physicalId));
29839
+ if (context?.replayingState !== true && context?.desiredFromAwsReadback !== true && this.removedRetained(properties, previousProperties, context).includes("Auth") && authRemovalRefused(properties, previousProperties)) throw markNonRetryable(new ProvisioningError(safeMsg`${logicalId} (${resourceType}): Auth was removed from the template, but AWS requires Auth while DefaultAuthScheme is NONE or unset, and CloudFormation's update fails on the same change. Declare Auth again; nothing was changed.`, resourceType, logicalId, physicalId));
29840
+ if (context?.replayingState !== true && context?.desiredFromAwsReadback !== true && leavesProxyWithoutAuth(properties, previousProperties)) throw markNonRetryable(new ProvisioningError(safeMsg`${logicalId} (${resourceType}): the update leaves the proxy with no Auth while DefaultAuthScheme is NONE or unset, and AWS requires Auth then. Declare Auth; nothing was changed.`, resourceType, logicalId, physicalId));
29484
29841
  const client = this.getClient();
29485
29842
  const { mask } = withDerivedNameMasks(this.logger, createMaskedLogSinks(this.logger, context?.maskSecrets), [[previousProperties["DBProxyName"], physicalId]]);
29486
29843
  for (const field of [
29487
29844
  "DBProxyName",
29488
29845
  "EngineFamily",
29489
- "VpcSubnetIds"
29846
+ "VpcSubnetIds",
29847
+ "EndpointNetworkType",
29848
+ "TargetConnectionNetworkType"
29490
29849
  ]) if (JSON.stringify(properties[field]) !== JSON.stringify(previousProperties[field]) && !await unchangedBehindSecretReference({
29491
29850
  resourceType,
29492
29851
  key: field,
@@ -29499,6 +29858,7 @@ var RDSDBProxyProvider = class {
29499
29858
  let hasModify = false;
29500
29859
  for (const key of [
29501
29860
  "Auth",
29861
+ "DefaultAuthScheme",
29502
29862
  "RequireTLS",
29503
29863
  "IdleClientTimeout",
29504
29864
  "DebugLogging",
@@ -29626,7 +29986,10 @@ var RDSDBProxyProvider = class {
29626
29986
  SecretArn: a.SecretArn,
29627
29987
  IAMAuth: a.IAMAuth,
29628
29988
  ClientPasswordAuthType: a.ClientPasswordAuthType
29629
- }))
29989
+ })),
29990
+ ...p.DefaultAuthScheme !== void 0 && { DefaultAuthScheme: p.DefaultAuthScheme },
29991
+ ...p.EndpointNetworkType !== void 0 && { EndpointNetworkType: p.EndpointNetworkType },
29992
+ ...p.TargetConnectionNetworkType !== void 0 && { TargetConnectionNetworkType: p.TargetConnectionNetworkType }
29630
29993
  };
29631
29994
  if (p.DBProxyArn) try {
29632
29995
  const tagResp = await client.send(new ListTagsForResourceCommand$10({ ResourceName: p.DBProxyArn }));
@@ -29729,6 +30092,7 @@ var RDSDBProxyEndpointProvider = class {
29729
30092
  "VpcSubnetIds",
29730
30093
  "VpcSecurityGroupIds",
29731
30094
  "TargetRole",
30095
+ "EndpointNetworkType",
29732
30096
  "Tags"
29733
30097
  ])]]);
29734
30098
  getClient() {
@@ -29765,6 +30129,7 @@ var RDSDBProxyEndpointProvider = class {
29765
30129
  VpcSubnetIds: vpcSubnetIds,
29766
30130
  VpcSecurityGroupIds: properties["VpcSecurityGroupIds"],
29767
30131
  TargetRole: properties["TargetRole"],
30132
+ EndpointNetworkType: properties["EndpointNetworkType"],
29768
30133
  Tags: tags.length > 0 ? tags : void 0
29769
30134
  }));
29770
30135
  } catch (error) {
@@ -29820,7 +30185,8 @@ var RDSDBProxyEndpointProvider = class {
29820
30185
  "DBProxyName",
29821
30186
  "DBProxyEndpointName",
29822
30187
  "VpcSubnetIds",
29823
- "TargetRole"
30188
+ "TargetRole",
30189
+ "EndpointNetworkType"
29824
30190
  ]) if (JSON.stringify(properties[field]) !== JSON.stringify(previousProperties[field]) && !await unchangedBehindSecretReference({
29825
30191
  resourceType,
29826
30192
  key: field,
@@ -29924,7 +30290,8 @@ var RDSDBProxyEndpointProvider = class {
29924
30290
  DBProxyName: e.DBProxyName,
29925
30291
  VpcSubnetIds: e.VpcSubnetIds ?? [],
29926
30292
  VpcSecurityGroupIds: e.VpcSecurityGroupIds ?? [],
29927
- TargetRole: e.TargetRole ?? "READ_WRITE"
30293
+ TargetRole: e.TargetRole ?? "READ_WRITE",
30294
+ ...e.EndpointNetworkType !== void 0 && { EndpointNetworkType: e.EndpointNetworkType }
29928
30295
  };
29929
30296
  if (e.DBProxyEndpointArn) try {
29930
30297
  const tagResp = await client.send(new ListTagsForResourceCommand$10({ ResourceName: e.DBProxyEndpointArn }));
@@ -30587,6 +30954,25 @@ function masterUserPasswordToSend(properties, previousProperties, context) {
30587
30954
  return typeof desired === "string" && typeof recorded === "string" && recorded === desired && dynamicReferenceTokens(recorded).length === 0 && recorded !== "***" ? void 0 : desired;
30588
30955
  }
30589
30956
  const DOCDB_DEFAULT_PORT = 27017;
30957
+ const DOCDB_CLUSTER_KEPT_ON_REMOVAL = [
30958
+ "DeletionProtection",
30959
+ "BackupRetentionPeriod",
30960
+ "VpcSecurityGroupIds",
30961
+ "EngineVersion",
30962
+ "PreferredBackupWindow",
30963
+ "PreferredMaintenanceWindow",
30964
+ "DBClusterParameterGroupName"
30965
+ ];
30966
+ const DOCDB_INSTANCE_KEPT_ON_REMOVAL = ["PreferredMaintenanceWindow"];
30967
+ function keptOnRemovalWarning$1(keys, properties, previousProperties, context, logicalId, resourceType) {
30968
+ const removedSet = context?.removedProperties ?? new Set(removedTemplateKeys(previousProperties, properties));
30969
+ const removed = keys.filter((key) => removedSet.has(key));
30970
+ if (removed.length === 0) return void 0;
30971
+ const one = removed.length === 1;
30972
+ const names = `${one ? "property" : "properties"} ${removed.join(", ")}`;
30973
+ const modify = resourceType === "AWS::DocDB::DBInstance" ? "ModifyDBInstance" : "ModifyDBCluster";
30974
+ return context?.replayingState ? safeMsg`${logicalId} (${resourceType}): ${names} ${one ? "is" : "are"} absent from the state being restored; ${modify} keeps a setting it is not sent, so the rollback leaves any value the failed deploy applied in place.` : safeMsg`${logicalId} (${resourceType}): ${names} ${one ? "was" : "were"} removed from the template; cdkd leaves the current AWS ${one ? "value" : "values"} in place, as CloudFormation does. Declare ${one ? "it" : "them"} to change ${one ? "it" : "them"}.`;
30975
+ }
30590
30976
  const SECURITY_GROUP_CHANGE_MEMBER_STATUSES = /* @__PURE__ */ new Set(["modifying"]);
30591
30977
  const PORT_CHANGE_MEMBER_STATUSES = /* @__PURE__ */ new Set(["modifying", "rebooting"]);
30592
30978
  function numberOrUndefined(value) {
@@ -30628,6 +31014,25 @@ var DocDBProvider = class {
30628
31014
  logger = getLogger().child("DocDBProvider");
30629
31015
  protectionFlips = new ProtectionFlipRegistry();
30630
31016
  disableCcApiFallback = true;
31017
+ removalHandledInUpdate = /* @__PURE__ */ new Map([["AWS::DocDB::DBCluster", /* @__PURE__ */ new Set([
31018
+ "DBClusterIdentifier",
31019
+ "DBSubnetGroupName",
31020
+ "KmsKeyId",
31021
+ "MasterUsername",
31022
+ "StorageEncrypted",
31023
+ "Port",
31024
+ "Tags",
31025
+ "MasterUserPassword",
31026
+ ...DOCDB_CLUSTER_KEPT_ON_REMOVAL
31027
+ ])], ["AWS::DocDB::DBInstance", /* @__PURE__ */ new Set([
31028
+ "DBInstanceIdentifier",
31029
+ "DBClusterIdentifier",
31030
+ "AvailabilityZone",
31031
+ "DBInstanceClass",
31032
+ "Tags",
31033
+ "AutoMinorVersionUpgrade",
31034
+ ...DOCDB_INSTANCE_KEPT_ON_REMOVAL
31035
+ ])]]);
30631
31036
  handledProperties = /* @__PURE__ */ new Map([["AWS::DocDB::DBCluster", /* @__PURE__ */ new Set([
30632
31037
  "DBClusterIdentifier",
30633
31038
  "EngineVersion",
@@ -30681,7 +31086,7 @@ var DocDBProvider = class {
30681
31086
  async update(logicalId, physicalId, resourceType, properties, previousProperties, context) {
30682
31087
  switch (resourceType) {
30683
31088
  case "AWS::DocDB::DBCluster": return this.updateDBCluster(logicalId, physicalId, resourceType, properties, previousProperties, context);
30684
- case "AWS::DocDB::DBInstance": return this.updateDBInstance(logicalId, physicalId, resourceType, properties, previousProperties, context?.maskSecrets);
31089
+ case "AWS::DocDB::DBInstance": return this.updateDBInstance(logicalId, physicalId, resourceType, properties, previousProperties, context);
30685
31090
  default: throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId, physicalId);
30686
31091
  }
30687
31092
  }
@@ -30773,6 +31178,8 @@ var DocDBProvider = class {
30773
31178
  for (const member of described?.DBClusterMembers ?? []) if (member.DBInstanceIdentifier) await this.waitForMemberAfterClusterChange(member.DBInstanceIdentifier, logicalId, SECURITY_GROUP_CHANGE_MEMBER_STATUSES, "VPC security groups");
30774
31179
  }
30775
31180
  if (described?.DBClusterArn) await applyDocDBTagDiff(this.getClient(), this.logger, described.DBClusterArn, resourceType, logicalId, previousProperties["Tags"], properties["Tags"]);
31181
+ const keptWarning = keptOnRemovalWarning$1(DOCDB_CLUSTER_KEPT_ON_REMOVAL, properties, previousProperties, context, logicalId, resourceType);
31182
+ if (keptWarning !== void 0) this.logger.warn(keptWarning);
30776
31183
  return {
30777
31184
  physicalId,
30778
31185
  wasReplaced: false,
@@ -30896,8 +31303,9 @@ var DocDBProvider = class {
30896
31303
  throw thrown;
30897
31304
  }
30898
31305
  }
30899
- async updateDBInstance(logicalId, physicalId, resourceType, properties, previousProperties, mask) {
31306
+ async updateDBInstance(logicalId, physicalId, resourceType, properties, previousProperties, context) {
30900
31307
  this.logger.debug(`Updating DocDB DBInstance ${logicalId}: ${physicalId}`);
31308
+ const mask = context?.maskSecrets;
30901
31309
  refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId);
30902
31310
  try {
30903
31311
  await modifyDbInstanceWhenAvailable({
@@ -30918,6 +31326,8 @@ var DocDBProvider = class {
30918
31326
  this.logger.debug(`Successfully updated DocDB DBInstance ${logicalId}`);
30919
31327
  const described = await this.describeDBInstance(physicalId);
30920
31328
  if (described?.DBInstanceArn) await applyDocDBTagDiff(this.getClient(), this.logger, described.DBInstanceArn, resourceType, logicalId, previousProperties["Tags"], properties["Tags"]);
31329
+ const keptWarning = keptOnRemovalWarning$1(DOCDB_INSTANCE_KEPT_ON_REMOVAL, properties, previousProperties, context, logicalId, resourceType);
31330
+ if (keptWarning !== void 0) this.logger.warn(keptWarning);
30921
31331
  return {
30922
31332
  physicalId,
30923
31333
  wasReplaced: false,
@@ -34150,6 +34560,36 @@ function nodesToRemove(nodes, desiredCount, desiredZones) {
34150
34560
  if (keep.size + unnamed < desiredCount) return void 0;
34151
34561
  return named.map((n) => n.id).filter((id) => !keep.has(id)).sort();
34152
34562
  }
34563
+ const KEPT_ON_REMOVAL$1 = [
34564
+ "EngineVersion",
34565
+ "CacheParameterGroupName",
34566
+ "PreferredMaintenanceWindow",
34567
+ "SnapshotWindow",
34568
+ "IpDiscovery",
34569
+ "SnapshotRetentionLimit",
34570
+ "AutoMinorVersionUpgrade",
34571
+ "NotificationTopicArn",
34572
+ "VpcSecurityGroupIds",
34573
+ "TransitEncryptionEnabled",
34574
+ "PreferredAvailabilityZone"
34575
+ ];
34576
+ const NOT_MODIFIABLE = /* @__PURE__ */ new Set(["TransitEncryptionEnabled", "PreferredAvailabilityZone"]);
34577
+ const PLACEMENT_ON_REMOVAL = ["AZMode", "PreferredAvailabilityZones"];
34578
+ const removalWarnings = (logicalId, kept, placement, caller) => {
34579
+ const lines = [];
34580
+ const head = (names) => safeMsg`${logicalId} (AWS::ElastiCache::CacheCluster): ${names.length === 1 ? "property" : "properties"} ${names.join(", ")}`;
34581
+ if (kept.length > 0) {
34582
+ const one = kept.length === 1;
34583
+ const fixed = kept.filter((name) => NOT_MODIFIABLE.has(name));
34584
+ const replaceNote = fixed.length === 0 ? "" : safeMsg` (${fixed.join(", ")} ${fixed.length === 1 ? "changes" : "change"} only by replacing the cluster)`;
34585
+ lines.push(caller === "rollback" ? `${head(kept)} ${one ? "is" : "are"} absent from the state being restored; the rollback sends nothing for ${one ? "it" : "them"}, so the cluster keeps the value it holds now.` : `${head(kept)} ${one ? "was" : "were"} removed from the template and ${one ? "keeps its" : "keep their"} current AWS value, as CloudFormation leaves ${one ? "it" : "them"}; cdkd sends nothing for a removed property. To change a value, declare it explicitly${replaceNote}.`);
34586
+ }
34587
+ if (placement.length > 0) {
34588
+ const one = placement.length === 1;
34589
+ lines.push(caller === "rollback" ? `${head(placement)} ${one ? "is" : "are"} absent from the state being restored; the rollback leaves the cluster unchanged.` : `${head(placement)} ${one ? "was" : "were"} removed from the template; cdkd sends nothing for a removed property, so the nodes stay in their zones. CloudFormation updates a cross-az cluster, or a single-az one that keeps its zone list, in place. It replaces a memcached single-az cluster left with no zone, and cdkd plans that replacement too (go-to-k/cdkd#5558). To move the nodes, replace the cluster, for example by changing its logical ID.`);
34590
+ }
34591
+ return lines;
34592
+ };
34153
34593
  var ElastiCacheProvider = class {
34154
34594
  client;
34155
34595
  createClient;
@@ -34199,6 +34639,22 @@ var ElastiCacheProvider = class {
34199
34639
  "TransitEncryptionEnabled"
34200
34640
  ])]]);
34201
34641
  unhandledByDesign = /* @__PURE__ */ new Map([["AWS::ElastiCache::CacheCluster", /* @__PURE__ */ new Map([["CacheSecurityGroupNames", "EC2-Classic-only — use VpcSecurityGroupIds for VPC-deployed clusters (EC2-Classic retired 2022-08-15)"]])]]);
34642
+ removalHandledInUpdate = /* @__PURE__ */ new Map([["AWS::ElastiCache::CacheCluster", /* @__PURE__ */ new Set([
34643
+ "CacheSubnetGroupName",
34644
+ "ClusterName",
34645
+ "Engine",
34646
+ "NetworkType",
34647
+ "Port",
34648
+ "SnapshotName",
34649
+ "SnapshotArns",
34650
+ "CacheSecurityGroupNames",
34651
+ "CacheNodeType",
34652
+ "NumCacheNodes",
34653
+ "Tags",
34654
+ "LogDeliveryConfigurations",
34655
+ ...KEPT_ON_REMOVAL$1,
34656
+ ...PLACEMENT_ON_REMOVAL
34657
+ ])]]);
34202
34658
  getClient() {
34203
34659
  if (!this.client) {
34204
34660
  this.client = new ElastiCacheClient({
@@ -34228,7 +34684,7 @@ var ElastiCacheProvider = class {
34228
34684
  const mask = context?.maskSecrets;
34229
34685
  switch (resourceType) {
34230
34686
  case "AWS::ElastiCache::SubnetGroup": return this.updateSubnetGroup(logicalId, physicalId, resourceType, properties, previousProperties, mask);
34231
- case "AWS::ElastiCache::CacheCluster": return this.updateCacheCluster(logicalId, physicalId, resourceType, properties, previousProperties, mask);
34687
+ case "AWS::ElastiCache::CacheCluster": return this.updateCacheCluster(logicalId, physicalId, resourceType, properties, previousProperties, mask, context);
34232
34688
  default: throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId, physicalId);
34233
34689
  }
34234
34690
  }
@@ -34360,7 +34816,7 @@ var ElastiCacheProvider = class {
34360
34816
  throw thrown;
34361
34817
  }
34362
34818
  }
34363
- async updateCacheCluster(logicalId, physicalId, resourceType, properties, previousProperties, mask) {
34819
+ async updateCacheCluster(logicalId, physicalId, resourceType, properties, previousProperties, mask, context) {
34364
34820
  this.logger.debug(`Updating CacheCluster ${logicalId}: ${physicalId}`);
34365
34821
  refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId);
34366
34822
  try {
@@ -34399,6 +34855,7 @@ var ElastiCacheProvider = class {
34399
34855
  const described = await this.describeCacheCluster(physicalId);
34400
34856
  this.warnTransitEncryptionNotApplied(logicalId, properties, previousProperties, described?.TransitEncryptionEnabled);
34401
34857
  if (described?.ARN) await this.applyTagDiff(described.ARN, resourceType, logicalId, previousProperties["Tags"], properties["Tags"]);
34858
+ this.warnRemovalsLeftInPlace(logicalId, properties, previousProperties, context);
34402
34859
  const attributes = {};
34403
34860
  if (described?.CacheNodes?.[0]?.Endpoint) {
34404
34861
  const endpoint = described.CacheNodes[0].Endpoint;
@@ -34499,6 +34956,13 @@ var ElastiCacheProvider = class {
34499
34956
  if (notApplied.length === 0) return;
34500
34957
  this.logger.warn(safeMsg`CacheCluster ${logicalId}: the ${notApplied.join(", ")} change is not applied to the ` + "existing cluster (ModifyCacheCluster cannot change it, and CloudFormation leaves it unchanged too). To apply it, replace the cluster, for example by changing its logical ID.");
34501
34958
  }
34959
+ warnRemovalsLeftInPlace(logicalId, properties, previousProperties, context) {
34960
+ if (context?.desiredFromAwsReadback) return;
34961
+ const removed = context?.removedProperties;
34962
+ const wasRemoved = (key) => removed !== void 0 ? removed.has(key) : properties[key] === void 0 && previousProperties[key] !== void 0;
34963
+ const lines = removalWarnings(logicalId, KEPT_ON_REMOVAL$1.filter(wasRemoved), PLACEMENT_ON_REMOVAL.filter(wasRemoved), context?.replayingState ? "rollback" : "deploy");
34964
+ for (const line of lines) this.logger.warn(line);
34965
+ }
34502
34966
  buildLogDeliveryConfigurationsForUpdate(newConfigs, previousConfigs) {
34503
34967
  const kept = newConfigs ?? [];
34504
34968
  const keptLogTypes = new Set(kept.map((c) => c.LogType).filter((t) => t !== void 0));
@@ -35665,6 +36129,25 @@ const APPSYNC_APIKEY_ID_FORMAT = {
35665
36129
  label: "AppSync ApiKey",
35666
36130
  segments: ["apiId", "apiKeyId"]
35667
36131
  };
36132
+ const CFN_APPSYNC_ARN_RESOURCE_PATHS = {
36133
+ "AWS::AppSync::GraphQLApi": /^apis\/([^/|]+)$/,
36134
+ "AWS::AppSync::DataSource": /^apis\/([^/|]+)\/datasources\/([^/|]+)$/,
36135
+ "AWS::AppSync::Resolver": /^apis\/([^/|]+)\/types\/([^/|]+)\/resolvers\/([^/|]+)$/,
36136
+ "AWS::AppSync::ApiKey": /^apis\/([^/|]+)\/apikeys?\/([^/|]+)$/
36137
+ };
36138
+ function graphQLSchemaApiId(physicalId) {
36139
+ const schema = /^([a-z0-9]+)GraphQLSchema$/.exec(physicalId);
36140
+ return schema ? schema[1] : physicalId;
36141
+ }
36142
+ function appSyncPhysicalIdFromCfn(resourceType, logicalId, physicalId, region) {
36143
+ if (resourceType === "AWS::AppSync::GraphQLSchema") return graphQLSchemaApiId(physicalId);
36144
+ const pathPattern = CFN_APPSYNC_ARN_RESOURCE_PATHS[resourceType];
36145
+ const arn = /^arn:[^:]+:appsync:([^:]*):[^:]*:(.+)$/.exec(physicalId);
36146
+ const segments = pathPattern && arn ? pathPattern.exec(arn[2]) : null;
36147
+ if (!arn || !segments) return physicalId;
36148
+ if (canonicalizeRegion(arn[1]) !== canonicalizeRegion(region)) throw markNonRetryable(new ProvisioningError(safeMsg`${resourceType} ${physicalId} is in region ${arn[1]}, not the import region ${region}`, resourceType, logicalId, physicalId));
36149
+ return segments.slice(1).join("|");
36150
+ }
35668
36151
  const MUTABLE_GRAPHQL_API_CONFIG_PROPERTIES = [
35669
36152
  "UserPoolConfig",
35670
36153
  "OpenIDConnectConfig",
@@ -35804,7 +36287,7 @@ var AppSyncProvider = class {
35804
36287
  }
35805
36288
  if (resourceType === "AWS::AppSync::ApiKey" && parts.length === 2) {
35806
36289
  const [apiId, apiKeyId] = parts;
35807
- const apiKeyArn = await arn(`apis/${apiId}/apikey/${apiKeyId}`);
36290
+ const apiKeyArn = await arn(`apis/${apiId}/apikeys/${apiKeyId}`);
35808
36291
  return {
35809
36292
  ApiKey: apiKeyId,
35810
36293
  ...apiKeyArn && { Arn: apiKeyArn }
@@ -35953,12 +36436,13 @@ var AppSyncProvider = class {
35953
36436
  };
35954
36437
  }
35955
36438
  async updateGraphQLSchema(logicalId, physicalId, resourceType, properties, previousProperties, mask = maskerOrIdentity(void 0)) {
36439
+ const recordedApiId = graphQLSchemaApiId(physicalId);
35956
36440
  if (properties["ApiId"] !== void 0 && previousProperties["ApiId"] !== void 0 && properties["ApiId"] !== previousProperties["ApiId"] && !await unchangedBehindSecretReference({
35957
36441
  resourceType,
35958
36442
  key: "ApiId",
35959
36443
  desired: properties["ApiId"],
35960
36444
  previous: previousProperties["ApiId"],
35961
- physicalName: physicalId,
36445
+ physicalName: recordedApiId,
35962
36446
  maskSecrets: mask
35963
36447
  })) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "AWS AppSync GraphQLSchema.ApiId cannot move a schema to another API in place (CloudFormation fails a template change of it too) — deploy with --replace, or give the schema a new logical ID, to create it on the new API");
35964
36448
  const newDef = properties["Definition"];
@@ -35983,7 +36467,7 @@ var AppSyncProvider = class {
35983
36467
  physicalId,
35984
36468
  wasReplaced: false
35985
36469
  };
35986
- const apiId = properties["ApiId"] ?? physicalId;
36470
+ const apiId = properties["ApiId"] ?? recordedApiId;
35987
36471
  try {
35988
36472
  await this.getClient().send(new StartSchemaCreationCommand({
35989
36473
  apiId,
@@ -36907,7 +37391,7 @@ var AppSyncProvider = class {
36907
37391
  maskSecrets: context?.maskSecrets,
36908
37392
  ...context?.replayingState === true && { onRefusal: (message) => this.logger.warn(message) }
36909
37393
  });
36910
- const apiKeyArn = await this.buildAppSyncArnOrWarn(`apis/${apiId}/apikey/${apiKeyId}`, logicalId, physicalId);
37394
+ const apiKeyArn = await this.buildAppSyncArnOrWarn(`apis/${apiId}/apikeys/${apiKeyId}`, logicalId, physicalId);
36911
37395
  return {
36912
37396
  physicalId,
36913
37397
  attributes: {
@@ -36992,10 +37476,11 @@ var AppSyncProvider = class {
36992
37476
  }
36993
37477
  }
36994
37478
  async readGraphQLSchema(physicalId, properties) {
37479
+ const apiId = graphQLSchemaApiId(physicalId);
36995
37480
  let resp;
36996
37481
  try {
36997
37482
  resp = await this.getClient().send(new GetIntrospectionSchemaCommand({
36998
- apiId: physicalId,
37483
+ apiId,
36999
37484
  format: "SDL"
37000
37485
  }));
37001
37486
  } catch (err) {
@@ -37012,7 +37497,7 @@ var AppSyncProvider = class {
37012
37497
  if (await this.canonicalizeSdl(stateDefinition, "state") === canonicalAws) definitionToReturn = stateDefinition;
37013
37498
  }
37014
37499
  return {
37015
- ApiId: physicalId,
37500
+ ApiId: apiId,
37016
37501
  Definition: definitionToReturn
37017
37502
  };
37018
37503
  }
@@ -37253,14 +37738,18 @@ var AppSyncProvider = class {
37253
37738
  return RESOURCE_NOT_FOUND;
37254
37739
  }
37255
37740
  async import(input) {
37741
+ const known = input.knownPhysicalId && appSyncPhysicalIdFromCfn(input.resourceType, input.logicalId, input.knownPhysicalId, input.region);
37256
37742
  if (input.resourceType !== "AWS::AppSync::GraphQLApi") {
37257
- if (input.knownPhysicalId) return {
37258
- physicalId: input.knownPhysicalId,
37259
- attributes: await this.childImportAttributes(input.resourceType, input.knownPhysicalId, input.region)
37743
+ if (known) return {
37744
+ physicalId: known,
37745
+ attributes: await this.childImportAttributes(input.resourceType, known, input.region)
37260
37746
  };
37261
37747
  return null;
37262
37748
  }
37263
- const explicit = resolveExplicitPhysicalId(input, null);
37749
+ const explicit = resolveExplicitPhysicalId(known ? {
37750
+ ...input,
37751
+ knownPhysicalId: known
37752
+ } : input, null);
37264
37753
  if (explicit) try {
37265
37754
  const response = await this.getClient().send(new GetGraphqlApiCommand({ apiId: explicit }));
37266
37755
  return {
@@ -43077,7 +43566,7 @@ var EFSProvider = class {
43077
43566
  const log = createMaskedLogSinks(this.logger, context?.maskSecrets);
43078
43567
  properties = withRemovalDefaults(this.removalDefaults, resourceType, properties, previousProperties, context);
43079
43568
  switch (resourceType) {
43080
- case "AWS::EFS::FileSystem": return this.updateFileSystem(logicalId, physicalId, resourceType, properties, previousProperties, log);
43569
+ case "AWS::EFS::FileSystem": return this.updateFileSystem(logicalId, physicalId, resourceType, properties, previousProperties, log, context?.replayingState === true || context?.desiredFromAwsReadback === true);
43081
43570
  case "AWS::EFS::MountTarget": return this.updateMountTarget(logicalId, physicalId, resourceType, properties, log);
43082
43571
  case "AWS::EFS::AccessPoint": return this.updateAccessPoint(logicalId, physicalId, resourceType, properties, previousProperties, log);
43083
43572
  default: throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId, physicalId);
@@ -43125,7 +43614,7 @@ var EFSProvider = class {
43125
43614
  throw this.wrapMaskedError(log, error, (text) => new ProvisioningError(`Failed to update EFS AccessPoint ${logicalId}: ${text}`, resourceType, logicalId, physicalId, cause));
43126
43615
  }
43127
43616
  }
43128
- async updateFileSystem(logicalId, physicalId, resourceType, properties, previousProperties, log) {
43617
+ async updateFileSystem(logicalId, physicalId, resourceType, properties, previousProperties, log, stateBorneDesired) {
43129
43618
  for (const key of [
43130
43619
  "Encrypted",
43131
43620
  "KmsKeyId",
@@ -43140,8 +43629,13 @@ var EFSProvider = class {
43140
43629
  const newProvisioned = properties["ProvisionedThroughputInMibps"];
43141
43630
  const oldThroughputMode = previousProperties["ThroughputMode"];
43142
43631
  const oldProvisioned = previousProperties["ProvisionedThroughputInMibps"];
43632
+ const throughputValueMissing = newThroughputMode === "provisioned" && newProvisioned === void 0 && (oldProvisioned !== void 0 || oldThroughputMode !== "provisioned");
43633
+ if (throughputValueMissing) {
43634
+ if (!stateBorneDesired) throw new ProvisioningError(`Failed to update EFS FileSystem ${logicalId}: Throughput value must be specified for provisioned throughput mode. The template sets ThroughputMode: provisioned without ProvisionedThroughputInMibps, which CloudFormation rejects too. Set ProvisionedThroughputInMibps, or change ThroughputMode (e.g. to bursting or elastic).`, resourceType, logicalId, physicalId);
43635
+ log.warn(`EFS FileSystem ${logicalId}: the desired properties (from cdkd state or an AWS readback, not the template) set ThroughputMode: provisioned without ProvisionedThroughputInMibps, which AWS rejects; leaving the file system's throughput as it is on AWS and applying the rest of the update. Its throughput may now differ from the record: run cdkd drift to see it.`);
43636
+ }
43143
43637
  const effectiveThroughputMode = newThroughputMode === void 0 && newProvisioned === void 0 && oldThroughputMode === "provisioned" ? "bursting" : newThroughputMode;
43144
- const throughputModeChanged = effectiveThroughputMode !== void 0 && effectiveThroughputMode !== oldThroughputMode;
43638
+ const throughputModeChanged = !throughputValueMissing && effectiveThroughputMode !== void 0 && effectiveThroughputMode !== oldThroughputMode;
43145
43639
  const provisionedChanged = newProvisioned !== void 0 && newProvisioned !== oldProvisioned;
43146
43640
  const changed = (key) => JSON.stringify(properties[key]) !== JSON.stringify(previousProperties[key]);
43147
43641
  const lifecycleChanged = changed("LifecyclePolicies");
@@ -48642,7 +49136,8 @@ var CodeBuildProvider = class {
48642
49136
  batchReportMode: cfnBuildBatchConfig["BatchReportMode"],
48643
49137
  restrictions: restrictions ? {
48644
49138
  maximumBuildsAllowed: restrictions["MaximumBuildsAllowed"],
48645
- computeTypesAllowed: restrictions["ComputeTypesAllowed"]
49139
+ computeTypesAllowed: restrictions["ComputeTypesAllowed"],
49140
+ fleetsAllowed: restrictions["FleetsAllowed"]
48646
49141
  } : void 0
48647
49142
  };
48648
49143
  }
@@ -48951,6 +49446,7 @@ var CodeBuildProvider = class {
48951
49446
  const r = {};
48952
49447
  if (project.buildBatchConfig.restrictions.maximumBuildsAllowed !== void 0) r["MaximumBuildsAllowed"] = project.buildBatchConfig.restrictions.maximumBuildsAllowed;
48953
49448
  if (project.buildBatchConfig.restrictions.computeTypesAllowed !== void 0) r["ComputeTypesAllowed"] = project.buildBatchConfig.restrictions.computeTypesAllowed;
49449
+ if (project.buildBatchConfig.restrictions.fleetsAllowed !== void 0) r["FleetsAllowed"] = project.buildBatchConfig.restrictions.fleetsAllowed;
48954
49450
  bbc["Restrictions"] = r;
48955
49451
  }
48956
49452
  if (project.buildBatchConfig.timeoutInMins !== void 0) bbc["TimeoutInMins"] = project.buildBatchConfig.timeoutInMins;
@@ -49519,6 +50015,28 @@ var CodeCommitRepositoryProvider = class {
49519
50015
 
49520
50016
  //#endregion
49521
50017
  //#region src/provisioning/providers/dlm-lifecycle-policy-provider.ts
50018
+ const KEPT_ON_REMOVAL = [
50019
+ "Description",
50020
+ "ExecutionRoleArn",
50021
+ "State",
50022
+ "PolicyDetails",
50023
+ "CreateInterval",
50024
+ "RetainInterval",
50025
+ "CopyTags",
50026
+ "ExtendDeletion",
50027
+ "CrossRegionCopyTargets",
50028
+ "Exclusions"
50029
+ ];
50030
+ function keptRemovedNames(properties, previousProperties, context) {
50031
+ if (context?.desiredFromAwsReadback) return [];
50032
+ const removed = context?.removedProperties;
50033
+ return KEPT_ON_REMOVAL.filter((key) => previousProperties[key] != null && properties[key] == null && (removed === void 0 || removed.has(key) || properties[key] === null));
50034
+ }
50035
+ const keptOnRemovalWarning = (logicalId, names, caller) => {
50036
+ const one = names.length === 1;
50037
+ const subject = one ? "property" : "properties";
50038
+ return caller === "rollback" ? safeMsg`${logicalId} (AWS::DLM::LifecyclePolicy): ${subject} ${names.join(", ")} ${one ? "is" : "are"} absent from the state being restored; UpdateLifecyclePolicy keeps a field it is not sent, so the rollback leaves the value the failed deploy applied in place.` : safeMsg`${logicalId} (AWS::DLM::LifecyclePolicy): ${subject} ${names.join(", ")} ${one ? "was" : "were"} removed from the template and ${one ? "keeps its" : "keep their"} current AWS value, as CloudFormation leaves ${one ? "it" : "them"}; UpdateLifecyclePolicy keeps a field it is not sent. Declare the intended value explicitly to change it.`;
50039
+ };
49522
50040
  const createLifecyclePolicyLatch = new AmbiguousCreateLatch("dlm:CreateLifecyclePolicy");
49523
50041
  const policiesCreatedByThisProcess = new RecentIdSet();
49524
50042
  var DLMLifecyclePolicyProvider = class {
@@ -49548,6 +50066,11 @@ var DLMLifecyclePolicyProvider = class {
49548
50066
  "CrossRegionCopyTargets",
49549
50067
  "Exclusions"
49550
50068
  ])]]);
50069
+ removalHandledInUpdate = /* @__PURE__ */ new Map([["AWS::DLM::LifecyclePolicy", /* @__PURE__ */ new Set([
50070
+ ...KEPT_ON_REMOVAL,
50071
+ "Tags",
50072
+ "DefaultPolicy"
50073
+ ])]]);
49551
50074
  getClient() {
49552
50075
  if (!this.client) this.client = new DLMClient({
49553
50076
  ...ambientClientDefaults(),
@@ -49672,6 +50195,8 @@ var DLMLifecyclePolicyProvider = class {
49672
50195
  ...properties["CreateInterval"] != null && { CreateInterval: Number(properties["CreateInterval"]) },
49673
50196
  ...properties["RetainInterval"] != null && { RetainInterval: Number(properties["RetainInterval"]) }
49674
50197
  }));
50198
+ const keptNames = keptRemovedNames(properties, previousProperties, context);
50199
+ if (keptNames.length > 0) this.logger.warn(keptOnRemovalWarning(logicalId, keptNames, context?.replayingState ? "rollback" : "deploy"));
49675
50200
  const plan = planTagDiff(previousProperties["Tags"], properties["Tags"]);
49676
50201
  const tagWarning = tagPlanWarning(plan, resourceType, logicalId);
49677
50202
  if (tagWarning !== void 0) this.logger.warn(tagWarning);
@@ -50875,6 +51400,173 @@ function tableIdentityFromGetTable(tableARN, namespace, name) {
50875
51400
  name
50876
51401
  };
50877
51402
  }
51403
+ function isCfnObject(value) {
51404
+ return value !== null && typeof value === "object" && !Array.isArray(value);
51405
+ }
51406
+ function desiredObject(properties, key, resourceType, logicalId, physicalId) {
51407
+ const value = properties[key];
51408
+ if (value === void 0) return void 0;
51409
+ if (isCfnObject(value)) return value;
51410
+ throw new ProvisioningError(`${key} for ${resourceType} ${logicalId} must be an object; refusing before any call`, resourceType, logicalId, physicalId);
51411
+ }
51412
+ function recordedObject(properties, key) {
51413
+ const value = properties[key];
51414
+ return isCfnObject(value) ? value : void 0;
51415
+ }
51416
+ var NotAnInteger = class extends Error {
51417
+ member;
51418
+ constructor(member) {
51419
+ super(`${member} must be an integer`);
51420
+ this.member = member;
51421
+ }
51422
+ };
51423
+ function integer(value, member) {
51424
+ if (value === void 0) return void 0;
51425
+ const n = typeof value === "number" ? value : typeof value === "string" && value.trim() !== "" ? Number(value) : NaN;
51426
+ if (Number.isInteger(n)) return n;
51427
+ throw new NotAnInteger(member);
51428
+ }
51429
+ function refuseNonIntegers(convert, key, resourceType, logicalId, physicalId) {
51430
+ try {
51431
+ return convert();
51432
+ } catch (error) {
51433
+ if (!(error instanceof NotAnInteger)) throw error;
51434
+ throw new ProvisioningError(`${key}.${error.member} for ${resourceType} ${logicalId} must be an integer; refusing before any call`, resourceType, logicalId, physicalId, error);
51435
+ }
51436
+ }
51437
+ function list(value) {
51438
+ return Array.isArray(value) ? value : void 0;
51439
+ }
51440
+ function defined(value) {
51441
+ return Object.fromEntries(Object.entries(value).filter(([, v]) => v !== void 0));
51442
+ }
51443
+ function maintenanceStatus(value) {
51444
+ return typeof value === "string" ? value.toLowerCase() : void 0;
51445
+ }
51446
+ function sdkEncryption(cfn) {
51447
+ return defined({
51448
+ sseAlgorithm: cfn["SSEAlgorithm"],
51449
+ kmsKeyArn: cfn["KMSKeyArn"]
51450
+ });
51451
+ }
51452
+ function sdkStorageClass(cfn) {
51453
+ return defined({ storageClass: cfn["StorageClass"] });
51454
+ }
51455
+ function sdkReplication(cfn) {
51456
+ return defined({
51457
+ role: cfn["Role"],
51458
+ rules: list(cfn["Rules"])?.map((rule) => defined({ destinations: list(isCfnObject(rule) ? rule["Destinations"] : void 0)?.map((destination) => defined({ destinationTableBucketARN: isCfnObject(destination) ? destination["DestinationTableBucketARN"] : void 0 })) }))
51459
+ });
51460
+ }
51461
+ function sdkUnreferencedFileRemoval(cfn) {
51462
+ const unreferencedDays = integer(cfn["UnreferencedDays"], "UnreferencedDays");
51463
+ const nonCurrentDays = integer(cfn["NoncurrentDays"], "NoncurrentDays");
51464
+ return defined({
51465
+ status: maintenanceStatus(cfn["Status"]),
51466
+ settings: unreferencedDays === void 0 && nonCurrentDays === void 0 ? void 0 : { icebergUnreferencedFileRemoval: defined({
51467
+ unreferencedDays,
51468
+ nonCurrentDays
51469
+ }) }
51470
+ });
51471
+ }
51472
+ function sdkCompaction(cfn) {
51473
+ const targetFileSizeMB = integer(cfn["TargetFileSizeMB"], "TargetFileSizeMB");
51474
+ return defined({
51475
+ status: maintenanceStatus(cfn["Status"]),
51476
+ settings: targetFileSizeMB === void 0 ? void 0 : { icebergCompaction: { targetFileSizeMB } }
51477
+ });
51478
+ }
51479
+ function sdkSnapshotManagement(cfn) {
51480
+ const minSnapshotsToKeep = integer(cfn["MinSnapshotsToKeep"], "MinSnapshotsToKeep");
51481
+ const maxSnapshotAgeHours = integer(cfn["MaxSnapshotAgeHours"], "MaxSnapshotAgeHours");
51482
+ return defined({
51483
+ status: maintenanceStatus(cfn["Status"]),
51484
+ settings: minSnapshotsToKeep === void 0 && maxSnapshotAgeHours === void 0 ? void 0 : { icebergSnapshotManagement: defined({
51485
+ minSnapshotsToKeep,
51486
+ maxSnapshotAgeHours
51487
+ }) }
51488
+ });
51489
+ }
51490
+ function mapObjects(value, map) {
51491
+ return list(value)?.map((element) => map(isCfnObject(element) ? element : {}));
51492
+ }
51493
+ function sdkIcebergMetadata(cfn) {
51494
+ const schema = isCfnObject(cfn["IcebergSchema"]) ? cfn["IcebergSchema"] : void 0;
51495
+ const schemaV2 = isCfnObject(cfn["IcebergSchemaV2"]) ? cfn["IcebergSchemaV2"] : void 0;
51496
+ const partitionSpec = isCfnObject(cfn["IcebergPartitionSpec"]) ? cfn["IcebergPartitionSpec"] : void 0;
51497
+ const sortOrder = isCfnObject(cfn["IcebergSortOrder"]) ? cfn["IcebergSortOrder"] : void 0;
51498
+ return defined({
51499
+ schema: schema && defined({ fields: mapObjects(schema["SchemaFieldList"], (f) => defined({
51500
+ id: integer(f["Id"], "IcebergSchema.SchemaFieldList.Id"),
51501
+ name: f["Name"],
51502
+ type: f["Type"],
51503
+ required: f["Required"]
51504
+ })) }),
51505
+ schemaV2: schemaV2 && defined({
51506
+ type: schemaV2["SchemaV2FieldType"],
51507
+ fields: mapObjects(schemaV2["SchemaV2FieldList"], (f) => defined({
51508
+ id: integer(f["Id"], "IcebergSchemaV2.SchemaV2FieldList.Id"),
51509
+ name: f["Name"],
51510
+ type: f["Type"],
51511
+ required: f["Required"],
51512
+ doc: f["Doc"]
51513
+ })),
51514
+ schemaId: integer(schemaV2["SchemaId"], "IcebergSchemaV2.SchemaId"),
51515
+ identifierFieldIds: list(schemaV2["IdentifierFieldIds"])?.map((id) => integer(id, "IcebergSchemaV2.IdentifierFieldIds"))
51516
+ }),
51517
+ partitionSpec: partitionSpec && defined({
51518
+ fields: mapObjects(partitionSpec["Fields"], (f) => defined({
51519
+ sourceId: integer(f["SourceId"], "IcebergPartitionSpec.Fields.SourceId"),
51520
+ transform: f["Transform"],
51521
+ name: f["Name"],
51522
+ fieldId: integer(f["FieldId"], "IcebergPartitionSpec.Fields.FieldId")
51523
+ })),
51524
+ specId: integer(partitionSpec["SpecId"], "IcebergPartitionSpec.SpecId")
51525
+ }),
51526
+ writeOrder: sortOrder && defined({
51527
+ orderId: integer(sortOrder["OrderId"], "IcebergSortOrder.OrderId"),
51528
+ fields: mapObjects(sortOrder["Fields"], (f) => defined({
51529
+ sourceId: integer(f["SourceId"], "IcebergSortOrder.Fields.SourceId"),
51530
+ transform: f["Transform"],
51531
+ direction: f["Direction"],
51532
+ nullOrder: f["NullOrder"]
51533
+ }))
51534
+ }),
51535
+ properties: isCfnObject(cfn["TableProperties"]) ? cfn["TableProperties"] : void 0
51536
+ });
51537
+ }
51538
+ const UPDATABLE_CONFIG_KEYS = {
51539
+ "AWS::S3Tables::TableBucket": [
51540
+ "EncryptionConfiguration",
51541
+ "StorageClassConfiguration",
51542
+ "MetricsConfiguration",
51543
+ "UnreferencedFileRemoval",
51544
+ "ReplicationConfiguration"
51545
+ ],
51546
+ "AWS::S3Tables::Table": ["Compaction", "SnapshotManagement"]
51547
+ };
51548
+ function metricsEnabled(metrics, resourceType, logicalId, physicalId) {
51549
+ const status = metrics?.["Status"];
51550
+ if (status === void 0 || status === "Disabled") return false;
51551
+ if (status === "Enabled") return true;
51552
+ throw new ProvisioningError(safeMsg`MetricsConfiguration.Status for ${resourceType} ${logicalId} must be 'Enabled' or 'Disabled'; refusing before any call`, resourceType, logicalId, physicalId);
51553
+ }
51554
+ const TABLE_MAINTENANCE = [[
51555
+ "Compaction",
51556
+ "icebergCompaction",
51557
+ sdkCompaction
51558
+ ], [
51559
+ "SnapshotManagement",
51560
+ "icebergSnapshotManagement",
51561
+ sdkSnapshotManagement
51562
+ ]];
51563
+ const INTEGER_BEARING_CONFIGS = {
51564
+ "AWS::S3Tables::TableBucket": [["UnreferencedFileRemoval", sdkUnreferencedFileRemoval]],
51565
+ "AWS::S3Tables::Table": TABLE_MAINTENANCE.map(([key, , toSdk]) => [key, toSdk])
51566
+ };
51567
+ function cfnBucketStatus(status) {
51568
+ return status === void 0 ? void 0 : `${status.charAt(0).toUpperCase()}${status.slice(1)}`;
51569
+ }
50878
51570
  function sentence(text) {
50879
51571
  return text.endsWith(".") ? text : `${text}.`;
50880
51572
  }
@@ -50891,7 +51583,15 @@ var S3TablesProvider = class {
50891
51583
  return markRedactedCause(build(`${m(failure.summary)}${relayedNameCollision(failure.detail)}`));
50892
51584
  }
50893
51585
  handledProperties = /* @__PURE__ */ new Map([
50894
- ["AWS::S3Tables::TableBucket", /* @__PURE__ */ new Set(["TableBucketName", "Tags"])],
51586
+ ["AWS::S3Tables::TableBucket", /* @__PURE__ */ new Set([
51587
+ "TableBucketName",
51588
+ "Tags",
51589
+ "EncryptionConfiguration",
51590
+ "StorageClassConfiguration",
51591
+ "MetricsConfiguration",
51592
+ "UnreferencedFileRemoval",
51593
+ "ReplicationConfiguration"
51594
+ ])],
50895
51595
  ["AWS::S3Tables::Namespace", /* @__PURE__ */ new Set(["TableBucketARN", "Namespace"])],
50896
51596
  ["AWS::S3Tables::Table", /* @__PURE__ */ new Set([
50897
51597
  "TableBucketARN",
@@ -50900,9 +51600,24 @@ var S3TablesProvider = class {
50900
51600
  "Name",
50901
51601
  "OpenTableFormat",
50902
51602
  "Format",
50903
- "Tags"
51603
+ "Tags",
51604
+ "IcebergMetadata",
51605
+ "StorageClassConfiguration",
51606
+ "Compaction",
51607
+ "SnapshotManagement",
51608
+ "WithoutMetadata"
50904
51609
  ])]
50905
51610
  ]);
51611
+ getDriftUnknownPaths(resourceType) {
51612
+ return resourceType === "AWS::S3Tables::Table" ? [
51613
+ "IcebergMetadata",
51614
+ "StorageClassConfiguration",
51615
+ "WithoutMetadata"
51616
+ ] : [];
51617
+ }
51618
+ getDriftAbsentMeansDefaultKeys(resourceType, properties) {
51619
+ return resourceType === "AWS::S3Tables::TableBucket" && properties["ReplicationConfiguration"] === void 0 ? ["ReplicationConfiguration"] : [];
51620
+ }
50906
51621
  getClient() {
50907
51622
  if (!this.client) {
50908
51623
  this.client = new S3TablesClient({
@@ -50931,18 +51646,25 @@ var S3TablesProvider = class {
50931
51646
  async update(logicalId, physicalId, resourceType, properties, previousProperties, context) {
50932
51647
  assertRegionMatch(context?.expectedRegion ? await this.getClient().config.region() : void 0, context?.expectedRegion, resourceType, logicalId, physicalId, "pre-update");
50933
51648
  if (resourceType === "AWS::S3Tables::Table" || resourceType === "AWS::S3Tables::TableBucket") refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId);
51649
+ for (const key of UPDATABLE_CONFIG_KEYS[resourceType] ?? []) desiredObject(properties, key, resourceType, logicalId, physicalId);
51650
+ for (const [key, convert] of INTEGER_BEARING_CONFIGS[resourceType] ?? []) {
51651
+ const value = desiredObject(properties, key, resourceType, logicalId, physicalId);
51652
+ if (value !== void 0) refuseNonIntegers(() => convert(value), key, resourceType, logicalId, physicalId);
51653
+ }
51654
+ if (resourceType === "AWS::S3Tables::TableBucket") metricsEnabled(recordedObject(properties, "MetricsConfiguration"), resourceType, logicalId, physicalId);
50934
51655
  try {
50935
- return await this.applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, context?.maskSecrets, context?.recordedAttributes);
51656
+ return await this.applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, context?.maskSecrets, context?.recordedAttributes, (key) => context?.markUnsettled?.(key));
50936
51657
  } catch (error) {
50937
51658
  if (error instanceof CdkdError) throw error;
50938
51659
  const cause = error instanceof Error ? error : void 0;
50939
51660
  throw this.wrapCaughtError(context?.maskSecrets, error, (text) => new ProvisioningError(`Failed to update S3 Tables resource ${logicalId}: ${text}`, resourceType, logicalId, physicalId, cause));
50940
51661
  }
50941
51662
  }
50942
- async applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, mask, recordedAttributes) {
51663
+ async applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, mask, recordedAttributes, markUnsettled) {
50943
51664
  if (resourceType === "AWS::S3Tables::Table") {
50944
51665
  const rename = await this.planTableRename(logicalId, physicalId, resourceType, properties, mask);
50945
51666
  await this.applyTableTagsDiff(logicalId, physicalId, resourceType, previousProperties["Tags"], properties["Tags"], mask);
51667
+ await this.applyTableMaintenanceUpdate(logicalId, physicalId, resourceType, properties, previousProperties, markUnsettled);
50946
51668
  if (rename === void 0) return {
50947
51669
  physicalId,
50948
51670
  wasReplaced: false
@@ -50957,8 +51679,10 @@ var S3TablesProvider = class {
50957
51679
  physicalId: rename.physicalId,
50958
51680
  wasReplaced: false
50959
51681
  };
50960
- } else if (resourceType === "AWS::S3Tables::TableBucket") await this.applyTableBucketTagsDiff(logicalId, physicalId, resourceType, previousProperties["Tags"], properties["Tags"], mask);
50961
- else this.logger.debug(`Update is no-op for ${resourceType} ${logicalId}`);
51682
+ } else if (resourceType === "AWS::S3Tables::TableBucket") {
51683
+ await this.applyTableBucketTagsDiff(logicalId, physicalId, resourceType, previousProperties["Tags"], properties["Tags"], mask);
51684
+ await this.applyTableBucketConfigUpdate(logicalId, physicalId, resourceType, properties, previousProperties, markUnsettled);
51685
+ } else this.logger.debug(`Update is no-op for ${resourceType} ${logicalId}`);
50962
51686
  return {
50963
51687
  physicalId,
50964
51688
  wasReplaced: false
@@ -50979,11 +51703,32 @@ var S3TablesProvider = class {
50979
51703
  const tableBucketName = properties["TableBucketName"];
50980
51704
  if (!tableBucketName) throw new ProvisioningError(`TableBucketName is required for S3 Table Bucket ${logicalId}`, resourceType, logicalId);
50981
51705
  const tags = this.tagListToSdkMap(desiredTags);
51706
+ const encryption = desiredObject(properties, "EncryptionConfiguration", resourceType, logicalId);
51707
+ const storageClass = desiredObject(properties, "StorageClassConfiguration", resourceType, logicalId);
51708
+ const metricsOn = metricsEnabled(desiredObject(properties, "MetricsConfiguration", resourceType, logicalId), resourceType, logicalId);
51709
+ const unreferenced = desiredObject(properties, "UnreferencedFileRemoval", resourceType, logicalId);
51710
+ const replication = desiredObject(properties, "ReplicationConfiguration", resourceType, logicalId);
51711
+ const unreferencedValue = unreferenced && refuseNonIntegers(() => sdkUnreferencedFileRemoval(unreferenced), "UnreferencedFileRemoval", resourceType, logicalId);
51712
+ let createdArn;
50982
51713
  try {
50983
51714
  const tableBucketARN = (await this.getCreateClient().send(new CreateTableBucketCommand({
50984
51715
  name: tableBucketName,
51716
+ ...encryption !== void 0 && { encryptionConfiguration: sdkEncryption(encryption) },
51717
+ ...storageClass !== void 0 && { storageClassConfiguration: sdkStorageClass(storageClass) },
50985
51718
  ...tags !== void 0 && { tags }
50986
51719
  }))).arn;
51720
+ createdArn = tableBucketARN;
51721
+ reportCreatedResource(logicalId, resourceType, tableBucketARN);
51722
+ if (metricsOn) await this.getClient().send(new PutTableBucketMetricsConfigurationCommand({ tableBucketARN }));
51723
+ if (unreferencedValue !== void 0) await this.getClient().send(new PutTableBucketMaintenanceConfigurationCommand({
51724
+ tableBucketARN,
51725
+ type: "icebergUnreferencedFileRemoval",
51726
+ value: unreferencedValue
51727
+ }));
51728
+ if (replication !== void 0) await this.getClient().send(new PutTableBucketReplicationCommand({
51729
+ tableBucketARN,
51730
+ configuration: sdkReplication(replication)
51731
+ }));
50987
51732
  this.logger.debug(`Successfully created S3 Table Bucket ${logicalId}: ${tableBucketARN}`);
50988
51733
  return {
50989
51734
  physicalId: tableBucketARN,
@@ -50991,7 +51736,104 @@ var S3TablesProvider = class {
50991
51736
  };
50992
51737
  } catch (error) {
50993
51738
  const cause = error instanceof Error ? error : void 0;
50994
- throw this.wrapCaughtError(context?.maskSecrets, error, (text) => new ProvisioningError(`Failed to create S3 Table Bucket ${logicalId}: ${text}`, resourceType, logicalId, void 0, cause));
51739
+ const thrown = this.wrapCaughtError(context?.maskSecrets, error, (text) => new ProvisioningError(`Failed to create S3 Table Bucket ${logicalId}: ${text}`, resourceType, logicalId, void 0, cause));
51740
+ if (createdArn !== void 0) markCreatedBeforeFailure(thrown, logicalId, resourceType, createdArn);
51741
+ throw thrown;
51742
+ }
51743
+ }
51744
+ async applyTableBucketConfigUpdate(logicalId, tableBucketARN, resourceType, properties, previousProperties, markUnsettled) {
51745
+ const changed = (key) => {
51746
+ const next = desiredObject(properties, key, resourceType, logicalId, tableBucketARN);
51747
+ return [next, !isDeepStrictEqual(next, recordedObject(previousProperties, key))];
51748
+ };
51749
+ const client = this.getClient();
51750
+ const [encryption, encryptionChanged] = changed("EncryptionConfiguration");
51751
+ if (encryptionChanged) {
51752
+ if (encryption !== void 0) {
51753
+ markUnsettled("EncryptionConfiguration");
51754
+ await client.send(new PutTableBucketEncryptionCommand({
51755
+ tableBucketARN,
51756
+ encryptionConfiguration: sdkEncryption(encryption)
51757
+ }));
51758
+ } else this.warnRemovalKept(logicalId, "EncryptionConfiguration");
51759
+ }
51760
+ const [storageClass, storageClassChanged] = changed("StorageClassConfiguration");
51761
+ if (storageClassChanged) {
51762
+ if (storageClass !== void 0) {
51763
+ markUnsettled("StorageClassConfiguration");
51764
+ await client.send(new PutTableBucketStorageClassCommand({
51765
+ tableBucketARN,
51766
+ storageClassConfiguration: sdkStorageClass(storageClass)
51767
+ }));
51768
+ } else this.warnRemovalKept(logicalId, "StorageClassConfiguration");
51769
+ }
51770
+ const metricsOn = metricsEnabled(desiredObject(properties, "MetricsConfiguration", resourceType, logicalId, tableBucketARN), resourceType, logicalId);
51771
+ const metricsWasOn = recordedObject(previousProperties, "MetricsConfiguration")?.["Status"] === "Enabled";
51772
+ if (metricsOn && !metricsWasOn) {
51773
+ markUnsettled("MetricsConfiguration");
51774
+ await client.send(new PutTableBucketMetricsConfigurationCommand({ tableBucketARN }));
51775
+ } else if (!metricsOn && metricsWasOn) {
51776
+ markUnsettled("MetricsConfiguration");
51777
+ await this.deleteBucketConfig(tableBucketARN, new DeleteTableBucketMetricsConfigurationCommand({ tableBucketARN }));
51778
+ }
51779
+ const [unreferenced, unreferencedChanged] = changed("UnreferencedFileRemoval");
51780
+ if (unreferencedChanged) {
51781
+ if (unreferenced !== void 0) {
51782
+ markUnsettled("UnreferencedFileRemoval");
51783
+ await client.send(new PutTableBucketMaintenanceConfigurationCommand({
51784
+ tableBucketARN,
51785
+ type: "icebergUnreferencedFileRemoval",
51786
+ value: sdkUnreferencedFileRemoval(unreferenced)
51787
+ }));
51788
+ } else this.warnRemovalKept(logicalId, "UnreferencedFileRemoval");
51789
+ }
51790
+ const [replication, replicationChanged] = changed("ReplicationConfiguration");
51791
+ if (replicationChanged) {
51792
+ if (replication !== void 0) {
51793
+ markUnsettled("ReplicationConfiguration");
51794
+ await client.send(new PutTableBucketReplicationCommand({
51795
+ tableBucketARN,
51796
+ configuration: sdkReplication(replication)
51797
+ }));
51798
+ } else {
51799
+ markUnsettled("ReplicationConfiguration");
51800
+ await this.deleteBucketConfig(tableBucketARN, new DeleteTableBucketReplicationCommand({ tableBucketARN }));
51801
+ }
51802
+ }
51803
+ }
51804
+ async applyTableMaintenanceUpdate(logicalId, physicalId, resourceType, properties, previousProperties, markUnsettled) {
51805
+ const writes = [];
51806
+ for (const [key, type, toSdk] of TABLE_MAINTENANCE) {
51807
+ const next = desiredObject(properties, key, resourceType, logicalId, physicalId);
51808
+ if (isDeepStrictEqual(next, recordedObject(previousProperties, key))) continue;
51809
+ if (next === void 0) this.warnRemovalKept(logicalId, key);
51810
+ else writes.push({
51811
+ key,
51812
+ type,
51813
+ value: toSdk(next)
51814
+ });
51815
+ }
51816
+ if (writes.length === 0) return;
51817
+ const table = await this.resolveTableParts(physicalId);
51818
+ if (table === "not-found" || table === "unparseable") throw new ProvisioningError(table === "not-found" ? safeMsg`S3 Tables Table '${physicalId}' no longer exists (state is out of sync); ` + `refusing to record a maintenance configuration that was not applied` : compositeIdFormatMessage(S3_TABLES_TABLE_ID_FORMAT, logicalId, physicalId), resourceType, logicalId, physicalId);
51819
+ for (const { key, type, value } of writes) {
51820
+ markUnsettled(key);
51821
+ await this.getClient().send(new PutTableMaintenanceConfigurationCommand({
51822
+ ...table,
51823
+ type,
51824
+ value
51825
+ }));
51826
+ }
51827
+ }
51828
+ warnRemovalKept(logicalId, key) {
51829
+ this.logger.warn(safeMsg`${logicalId}: ${key} was removed from the template; cdkd leaves its current AWS value in ` + `place. Declare the value you want (e.g. its default) to change it.`);
51830
+ }
51831
+ async deleteBucketConfig(tableBucketARN, command) {
51832
+ try {
51833
+ await this.getClient().send(command);
51834
+ } catch (error) {
51835
+ if (!(error instanceof NotFoundException$7)) throw error;
51836
+ await this.getClient().send(new GetTableBucketCommand({ tableBucketARN }));
50995
51837
  }
50996
51838
  }
50997
51839
  async deleteTableBucket(logicalId, physicalId, resourceType, context) {
@@ -51126,6 +51968,17 @@ var S3TablesProvider = class {
51126
51968
  const format = properties["OpenTableFormat"] ?? properties["Format"];
51127
51969
  if (!format) throw new ProvisioningError(`OpenTableFormat is required for S3 Tables Table ${logicalId}`, resourceType, logicalId);
51128
51970
  const tags = this.tagListToSdkMap(desiredTags);
51971
+ const icebergCfn = desiredObject(properties, "IcebergMetadata", resourceType, logicalId);
51972
+ const iceberg = icebergCfn && refuseNonIntegers(() => sdkIcebergMetadata(icebergCfn), "IcebergMetadata", resourceType, logicalId);
51973
+ const storageClass = desiredObject(properties, "StorageClassConfiguration", resourceType, logicalId);
51974
+ const maintenance = [];
51975
+ for (const [key, type, toSdk] of TABLE_MAINTENANCE) {
51976
+ const value = desiredObject(properties, key, resourceType, logicalId);
51977
+ if (value !== void 0) maintenance.push({
51978
+ type,
51979
+ value: refuseNonIntegers(() => toSdk(value), key, resourceType, logicalId)
51980
+ });
51981
+ }
51129
51982
  const physicalId = packCompositeId(resourceType, logicalId, [
51130
51983
  {
51131
51984
  name: "tableBucketARN",
@@ -51150,10 +52003,18 @@ var S3TablesProvider = class {
51150
52003
  namespace,
51151
52004
  name,
51152
52005
  format,
52006
+ ...iceberg !== void 0 && { metadata: { iceberg } },
52007
+ ...storageClass !== void 0 && { storageClassConfiguration: sdkStorageClass(storageClass) },
51153
52008
  ...tags !== void 0 && { tags }
51154
52009
  }));
51155
52010
  tableCreated = true;
51156
52011
  reportCreatedResource(logicalId, resourceType, physicalId);
52012
+ for (const write of maintenance) await this.getClient().send(new PutTableMaintenanceConfigurationCommand({
52013
+ tableBucketARN,
52014
+ namespace,
52015
+ name,
52016
+ ...write
52017
+ }));
51157
52018
  if (!response.tableARN) throw new ProvisioningError(`CreateTable did not return a tableARN for ${logicalId} (${physicalId}) — refusing to record an empty TableARN attribute`, resourceType, logicalId, physicalId);
51158
52019
  const tableARN = response.tableARN;
51159
52020
  this.logger.debug(`Successfully created S3 Tables Table ${logicalId}: ${physicalId}`);
@@ -51189,8 +52050,58 @@ var S3TablesProvider = class {
51189
52050
  const result = {};
51190
52051
  if (bucket.name !== void 0) result["TableBucketName"] = bucket.name;
51191
52052
  result["Tags"] = await this.readTagsBestEffort(physicalId);
52053
+ Object.assign(result, await this.readTableBucketConfigs(physicalId));
51192
52054
  return result;
51193
52055
  }
52056
+ async readTableBucketConfigs(tableBucketARN, strict = false) {
52057
+ const client = this.getClient();
52058
+ const out = {};
52059
+ await this.readConfig(out, "EncryptionConfiguration", async () => {
52060
+ const e = (await client.send(new GetTableBucketEncryptionCommand({ tableBucketARN }))).encryptionConfiguration;
52061
+ return defined({
52062
+ SSEAlgorithm: e?.sseAlgorithm ?? "AES256",
52063
+ KMSKeyArn: e?.kmsKeyArn
52064
+ });
52065
+ }, { SSEAlgorithm: "AES256" }, strict);
52066
+ await this.readConfig(out, "StorageClassConfiguration", async () => {
52067
+ return { StorageClass: (await client.send(new GetTableBucketStorageClassCommand({ tableBucketARN }))).storageClassConfiguration?.storageClass ?? "STANDARD" };
52068
+ }, { StorageClass: "STANDARD" }, strict);
52069
+ await this.readConfig(out, "MetricsConfiguration", async () => {
52070
+ await client.send(new GetTableBucketMetricsConfigurationCommand({ tableBucketARN }));
52071
+ return { Status: "Enabled" };
52072
+ }, { Status: "Disabled" }, strict);
52073
+ await this.readConfig(out, "UnreferencedFileRemoval", async () => {
52074
+ const value = (await client.send(new GetTableBucketMaintenanceConfigurationCommand({ tableBucketARN }))).configuration?.icebergUnreferencedFileRemoval;
52075
+ const settings = value?.settings?.icebergUnreferencedFileRemoval;
52076
+ return defined({
52077
+ Status: cfnBucketStatus(value?.status) ?? "Enabled",
52078
+ UnreferencedDays: settings?.unreferencedDays,
52079
+ NoncurrentDays: settings?.nonCurrentDays
52080
+ });
52081
+ }, { Status: "Enabled" }, strict);
52082
+ await this.readConfig(out, "ReplicationConfiguration", async () => {
52083
+ const c = (await client.send(new GetTableBucketReplicationCommand({ tableBucketARN }))).configuration;
52084
+ if (c === void 0) return void 0;
52085
+ return defined({
52086
+ Role: c.role,
52087
+ Rules: (c.rules ?? []).map((rule) => ({ Destinations: (rule.destinations ?? []).map((d) => ({ DestinationTableBucketARN: d.destinationTableBucketARN })) }))
52088
+ });
52089
+ }, "absent", strict);
52090
+ return out;
52091
+ }
52092
+ async readConfig(out, key, read, notFound, strict = false) {
52093
+ try {
52094
+ const value = await read();
52095
+ if (value !== void 0) out[key] = value;
52096
+ } catch (err) {
52097
+ if (err instanceof NotFoundException$7) {
52098
+ if (notFound !== "absent") out[key] = notFound;
52099
+ return;
52100
+ }
52101
+ if (strict) throw err;
52102
+ this.logger.debug(safeMsg`readCurrentState: reading ${key} failed: ${describeAwsFailure(err).detail} — leaving it out`);
52103
+ }
52104
+ }
51194
52105
  async readNamespaceCurrentState(physicalId) {
51195
52106
  const [tableBucketARN, namespaceName] = physicalId.split("|");
51196
52107
  if (!tableBucketARN || !namespaceName) return void 0;
@@ -51264,8 +52175,62 @@ var S3TablesProvider = class {
51264
52175
  result["Format"] = resp.format;
51265
52176
  }
51266
52177
  result["Tags"] = resp.tableARN ? await this.readTagsBestEffort(resp.tableARN) : [];
52178
+ Object.assign(result, await this.readTableMaintenance(physicalId, {
52179
+ tableBucketARN,
52180
+ namespace,
52181
+ name
52182
+ }));
52183
+ return result;
52184
+ }
52185
+ async readTableMaintenance(physicalId, table, strict = false) {
52186
+ const result = {};
52187
+ let maintenance;
52188
+ let maintenanceRead = true;
52189
+ try {
52190
+ maintenance = (await this.getClient().send(new GetTableMaintenanceConfigurationCommand(table))).configuration;
52191
+ } catch (err) {
52192
+ maintenanceRead = err instanceof NotFoundException$7;
52193
+ if (!maintenanceRead) {
52194
+ if (strict) throw err;
52195
+ this.logger.debug(safeMsg`readCurrentState: reading the maintenance configuration of ${physicalId} failed: ` + safeMsg`${describeAwsFailure(err).detail} — leaving Compaction / SnapshotManagement out`);
52196
+ }
52197
+ }
52198
+ if (maintenanceRead) {
52199
+ const compaction = maintenance?.icebergCompaction;
52200
+ const compactionSettings = compaction?.settings && "icebergCompaction" in compaction.settings ? compaction.settings.icebergCompaction : void 0;
52201
+ result["Compaction"] = defined({
52202
+ Status: compaction?.status ?? "enabled",
52203
+ TargetFileSizeMB: compactionSettings?.targetFileSizeMB
52204
+ });
52205
+ const snapshots = maintenance?.icebergSnapshotManagement;
52206
+ const snapshotSettings = snapshots?.settings && "icebergSnapshotManagement" in snapshots.settings ? snapshots.settings.icebergSnapshotManagement : void 0;
52207
+ result["SnapshotManagement"] = defined({
52208
+ Status: snapshots?.status ?? "enabled",
52209
+ MinSnapshotsToKeep: snapshotSettings?.minSnapshotsToKeep,
52210
+ MaxSnapshotAgeHours: snapshotSettings?.maxSnapshotAgeHours
52211
+ });
52212
+ }
51267
52213
  return result;
51268
52214
  }
52215
+ async readUnsettled(physicalId, logicalId, resourceType, names) {
52216
+ let live;
52217
+ if (resourceType === "AWS::S3Tables::TableBucket") {
52218
+ try {
52219
+ await this.getClient().send(new GetTableBucketCommand({ tableBucketARN: physicalId }));
52220
+ } catch (err) {
52221
+ if (err instanceof NotFoundException$7) return RESOURCE_NOT_FOUND;
52222
+ throw err;
52223
+ }
52224
+ live = await this.readTableBucketConfigs(physicalId, true);
52225
+ } else if (resourceType === "AWS::S3Tables::Table") {
52226
+ const table = await this.resolveTableParts(physicalId);
52227
+ if (table === "not-found") return RESOURCE_NOT_FOUND;
52228
+ if (table === "unparseable") throw new ProvisioningError(compositeIdFormatMessage(S3_TABLES_TABLE_ID_FORMAT, logicalId, physicalId), resourceType, logicalId, physicalId);
52229
+ if (await this.lookupTableArn(table.tableBucketARN, table.namespace, table.name) === null) return RESOURCE_NOT_FOUND;
52230
+ live = await this.readTableMaintenance(physicalId, table, true);
52231
+ } else return;
52232
+ return Object.fromEntries(Object.entries(live).filter(([key]) => names.has(key)));
52233
+ }
51269
52234
  async import(input) {
51270
52235
  switch (input.resourceType) {
51271
52236
  case "AWS::S3Tables::TableBucket": return this.importTableBucket(input);
@@ -52713,4 +53678,4 @@ var ACMCertificateProvider = class {
52713
53678
 
52714
53679
  //#endregion
52715
53680
  export { ACMCertificateProvider, ASGProvider, AgentCoreBrowserProvider, AgentCoreCodeInterpreterProvider, AgentCoreEvaluatorProvider, AgentCoreRuntimeProvider, ApiGatewayProvider, ApiGatewayV2Provider, AppSyncProvider, BudgetsBudgetProvider, CloudFrontDistributionProvider, CloudFrontOACProvider, CloudFrontOAIProvider, CloudTrailProvider, CloudWatchAlarmProvider, CloudWatchAnomalyDetectorProvider, CodeBuildProvider, CodeCommitRepositoryProvider, CognitoUserPoolProvider, DLMLifecyclePolicyProvider, DocDBProvider, DocDBSubnetGroupProvider, DynamoDBGlobalTableProvider, DynamoDBTableProvider, EC2Provider, ECRProvider, ECSProvider, EFSProvider, ELBv2Provider, EMRClusterProvider, EMRInstanceFleetConfigProvider, EMRInstanceGroupConfigProvider, ElastiCacheProvider, EventBridgeBusProvider, EventBridgeRuleProvider, FSxFileSystemProvider, FirehoseProvider, GlueConnectionProvider, GlueCrawlerProvider, GlueJobProvider, GlueProvider, GlueSecurityConfigurationProvider, GlueTriggerProvider, GlueWorkflowProvider, IAMAccessKeyProvider, IAMInstanceProfileProvider, IAMManagedPolicyProvider, IAMPolicyProvider, IAMRoleProvider, IAMUserGroupProvider, KMSProvider, KinesisStreamConsumerProvider, KinesisStreamProvider, LambdaEventInvokeConfigProvider, LambdaEventSourceMappingProvider, LambdaFunctionProvider, LambdaLayerVersionProvider, LambdaMicrovmImageProvider, LambdaNetworkConnectorProvider, LambdaPermissionProvider, LambdaUrlProvider, LambdaWebFunctionEndpointProvider, LambdaWebFunctionRevisionProvider, LogsLogGroupProvider, NeptuneProvider, NestedStackProvider, PipesPipeProvider, RDSDBProxyEndpointProvider, RDSDBProxyProvider, RDSDBProxyTargetGroupProvider, RDSProvider, Route53Provider, S3BucketPolicyProvider, S3BucketProvider, S3DirectoryBucketProvider, S3TablesProvider, S3VectorsProvider, SNSSubscriptionProvider, SNSTopicPolicyProvider, SNSTopicProvider, SQSQueuePolicyProvider, SQSQueueProvider, SSMParameterProvider, SchedulerScheduleProvider, SecretsManagerSecretProvider, ServiceDiscoveryProvider, StepFunctionsProvider, WAFv2WebACLProvider, WaitConditionHandleProvider };
52716
- //# sourceMappingURL=provider-classes-DktsDsTf.js.map
53681
+ //# sourceMappingURL=provider-classes-Dz0pYmlJ.js.map