@go-to-k/cdkd 0.308.1 → 0.310.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.
- package/dist/{asg-provider-B7pAjRIc.js → asg-provider-I1bFHVsO.js} +2 -2
- package/dist/{asg-provider-B7pAjRIc.js.map → asg-provider-I1bFHVsO.js.map} +1 -1
- package/dist/cli.js +2 -2
- package/dist/{deploy-engine-CDjAtIrn.js → deploy-engine-DZO2SOQJ.js} +1238 -248
- package/dist/deploy-engine-DZO2SOQJ.js.map +1 -0
- package/dist/iam-policy-targets-D94wh05t.js.map +1 -1
- package/dist/{iam-role-provider-DbtvFel_.js → iam-role-provider-BWw7I-SZ.js} +2 -2
- package/dist/{iam-role-provider-DbtvFel_.js.map → iam-role-provider-BWw7I-SZ.js.map} +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/{neptune-provider-Y3Ii8oYI.js → neptune-provider-8kjFmR1l.js} +2 -2
- package/dist/{neptune-provider-Y3Ii8oYI.js.map → neptune-provider-8kjFmR1l.js.map} +1 -1
- package/dist/{program-Ymf7svYk.js → program-CS420Kx9.js} +101 -257
- package/dist/program-CS420Kx9.js.map +1 -0
- package/dist/{provider-classes-BxfIHcea.js → provider-classes-KsrvwO_r.js} +942 -166
- package/dist/provider-classes-KsrvwO_r.js.map +1 -0
- package/dist/{rds-provider-CZhBLQgJ.js → rds-provider-BqwTQeS-.js} +27 -13
- package/dist/rds-provider-BqwTQeS-.js.map +1 -0
- package/dist/{version-BWqrjGBS.js → version-QOtLxcEo.js} +2 -2
- package/dist/{version-BWqrjGBS.js.map → version-QOtLxcEo.js.map} +1 -1
- package/package.json +9 -10
- package/dist/deploy-engine-CDjAtIrn.js.map +0 -1
- package/dist/program-Ymf7svYk.js.map +0 -1
- package/dist/provider-classes-BxfIHcea.js.map +0 -1
- package/dist/rds-provider-CZhBLQgJ.js.map +0 -1
|
@@ -2,13 +2,13 @@ import { r as getAwsClients, s as withApiGatewayPacing } from "./aws-clients-Bu9
|
|
|
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
3
|
import { $ as userPoolProtectionSite, $t as injectiveKeyPrefix, A as isPlainImportJson, C as setBounded, Cr as markNonRetryable, Ct as createMaskedLogSinks, D as markNotGone, Dn as ResourceUpdateNotSupportedError, Dt as maskerOrIdentity, Et as maskDeep, F as refusalTypeShown, Ft as isAuxiliaryFailure, G as isTerminalDbWaitStatus, H as deleteWithProtectionCompensation, Hn as hasClauseBreak, I as remedyLogicalId, J as observeThenDisableProtection, K as isTerminalDeleteFailure, Kn as plainOrDescribed, L as resolveExplicitPhysicalId, Lt as markAuxiliaryFailure, M as isQuotableImportValue, N as normalizeAwsTagsToCfn, O as assertRegionMatch, Ot as withDerivedNameMasks, P as quotedRemedyLogicalId, Qt as injectiveKey, Rt as markCreatedBeforeFailure, S as replayedSendWindow, Sr as isThrottlingError, St as stateOrphanRecordRemedy, T as RESOURCE_NOT_FOUND, Tn as ProvisioningError, Tr as wrapMaskedAwsError, Tt as isSecretDerivedValue, Un as isInertUnquoted, V as deleteAfterProtectionFlipWithFinalSnapshot, Vn as commandHole, Wn as pasteableCommand, X as rdsFamilyProtectionSite, Xn as withheldTargetClause, Y as protectionFlipKey, Yn as shellQuote, _ as RecentIdSet, _r as isRetryableTransientError, _t as compositeIdSkipResult, a as onlySecretDerived, an as ambientCredentialConfig, ar as markNameCollision, at as protectedReplacementAdvice, b as isInsideWindow, br as THROTTLING_ERROR_NAMES, c as recordedPrincipalsRepair, cn as AccountIdUnavailableError, dr as explicitDenyPolicyKind, ft as isInterruptedWaitError, g as AmbiguousCreateLatch, gt as compositeIdSeparatorRefusal, h as AMBIGUOUS_LATCH_TTL_MS, hr as isExplicitDenyError, ht as compositeIdFormatMessage, i as holdsSecretDerivedEntry, in as ambientClientDefaults, it as pasteableAwsCommand, j as isPlainImportValue, jt as clearCreatedBeforeFailure, k as VALUE_NOT_SHOWN, mr as isAmbiguousOutcomeError, mt as canonicalizeRoute53QueryName, nt as WITHHELD_AWS_COMMAND, o as readPrincipalLists, on as clientDefaultsFor, or as markReplayMayCollide, ot as renderDisableCommand, p as withRemovalDefaults, pt as startInterruptWatch, q as logGroupProtectionSite, r as SECRET_DERIVED_READ_LIVE, rn as withPasteableAwsProfile, rt as isAwsCliLiteral, sn as credentialFingerprint, sr as relayedNameCollision, st as ElapsedBudgetRegistry, tt as UNNAMEABLE_ID_CLAUSE, u as clearOnUpdateRemoval, un as CdkdError, v as ambiguousAttemptLead, vr as isTransientServerError, vt as logicalIdShown, w as withoutServerErrorRetries, wr as markRedactedCause, wt as createMaskedRetryLogger, x as replayFollowedAmbiguousAttempt, xr as isMarkedNonRetryable, xt as segmentAfterAnchor, y as createAttemptKey, yt as packCompositeId, z as ProtectionFlipRegistry, zt as markSupersedesEarlierCreate } from "./iam-policy-targets-D94wh05t.js";
|
|
4
4
|
import { c as ambientRegion } from "./aws-client-defaults-BX9Y_fKp.js";
|
|
5
|
-
import { $
|
|
6
|
-
import { n as collectInlinePolicyNamesManagedBySiblings, r as IamCreateClientCache, t as IAMRoleProvider } from "./iam-role-provider-
|
|
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-
|
|
5
|
+
import { $l as stringifyValue, $s as readConfigString, $t as lookupEachName, A as beginDeleteWait, Aa as s3BucketRegionalDomainName, Ai as isRefusedByName, Ar as awaitInFlightSibling, As as withheldAccountClause, B as waitForIndexesSettled, Bi as stringifyIfAssigned, Bt as getCurrentNestedStackContext, C as planContributorInsightsOp, Cd as resolveAssemblyPath, Co as accountArgs, D as reverseMapTableContributorInsights, Da as s3BucketArn, E as reverseMapIndexContributorInsights, Ea as isSettledInstanceState, Ec as passedNoEchoParametersOf, Ei as acquireIdempotencyToken, F as DELETE_INDEX_WAIT_PROCEED_NOTE, Fc as snapshotPassProvenance, Fi as readTagList, G as sendTtlWaitingOutRateLimit, Gs as isWarmThroughputDecrease, H as isTtlRateLimited, I as INDEX_SETTLE_POLL_INTERVAL_MS, Ia as outputReferenceProvenanceOf, Ii as refuseMalformedDesiredTags, In as REDACTED_DELETE_ADDRESS_SKIP_REASON, It as revertNestedChildFromJournal, J as hasCdkAutoDeleteTag, Js as coerceCfnBoolean, K as ECR_AUTO_DELETE_IMAGES_TAG, Ki as waitForLambdaFunctionActive, Ks as toCfnInteger, L as deleteTableWithIndexBusyRetry, Li as tagMapAsList, Ln as isRedactedRecordedValue, M as deleteBudgetKey, Mc as markSameGenerationBag, Mi as DBPROXY_TAGS_WHAT, Mr as getStackRecords, Ms as findSilentDropProperties, N as resolveDynamoDbDeleteBudgetClock, Nc as redactForState, Ni as DBPROXY_TAG_OPTIONS, Nt as getNestedRevertRun, O as stripIndexContributorInsights, Oa as s3BucketDomainName, P as resolveDynamoDbDeleteBudgetMs, Pc as recordReferenceProvenanceEntry, Pi as planTagDiff, Pn as getCurrentProducerRegions, Pr as replacedDeleteFailureVerdict, Ps as withoutSilentDropProperties, Qc as withoutPhysicalNameCopies, Qo as refuseMalformedNestedChildOutputs, Qs as configStringRefusal, Qt as isAccessDeniedError, R as maskedLogger, Rc as hasMaskableValues, Ri as tagPlanWarning, Rn as redactedDeleteAddressFields, S as indexDeclaresContributorInsights, Sd as renderAssemblyPathEscape, Si as earliestDefined, T as readContributorInsightsSpec, U as planTimeToLive, Us as WARM_THROUGHPUT_MEMBERS, V as isTtlAlreadyDisabled, Vt as withNestedStackContext, W as readTtlSpec, Ws as coerceWarmThroughput$1, X as getPriorAttempts, Xi as getCurrentResourceSecrets, Xl as timePhase, Xs as configBooleanRefusal, Y as isTruthyCfnBoolean, Ys as coerceCfnInteger, Z as markRefusedBeforeApplying, Zs as configIntegerRefusal, Zt as chunks, _ as streamMemberRefusals, _a as reDisableInstanceApiTermination, b as CONTRIBUTOR_INSIGHTS_KEY, bd as describeFileReadFailure, c as DynamoDBGlobalTableProvider, cc as blockDeviceMappingsDifferOnlyInDeleteOnTermination, cl as physicalNameCopiesOf, ct as listNestedTemplateRows, d as declaredStreamPolicyMember, da as isWaitAbandonedError, dc as emrClusterInstancesReplaced, ec as replayWarn, el as dynamicReferenceTokens, en as withApiLimit, f as declaredStreamTagsMember, fa as markWaitAbandoned, fc as canonicalLambdaFunctionName, fl as carriesSecretMask, g as streamDeclaresTags, ga as observeThenDisableInstanceApiTermination, go as passedParameterClassesOf, gt as enclosingDeadlineRemainingMs, h as streamDeclaresPolicy, ha as isTerminationProtectionPropagationError, ht as enclosingDeadlineExpired, ia as unchangedBehindSecretReference, iu as rewriteTemplateAssetReferences, j as compensateRemovedDeletionProtection, ja as s3BucketWebsiteUrl, ji as markDeleteStarted, k as DYNAMODB_DELETE_MIN_RESOURCE_TIMEOUT_MS, ka as s3BucketDualStackDomainName, l as STREAM_POLICY_KEY, la as deleteSkipReason, li as secretNamedAttributeNamesOf, ll as recordAttributeIdCopy, lt as renderNestedTemplateTreeDefect, m as reverseMapStreamPolicy, ma as ec2InstanceProtectionSite, mc as sameLambdaFunctionAddress, na as slowCcOperationTimeoutMs, nc as requireConfigObject, no as getAccountInfo, od as canonicalizeRegion, ot as findNestedTemplateTreeDefect, p as planStreamMemberOps, pc as lambdaFunctionNameForMask, po as parseWebACLArn, q as S3_AUTO_DELETE_OBJECTS_TAG, qs as toFiniteNumber, ra as onlySecretReferencesDiffer, rc as requireConfigString, rd as decodeListingKey, sc as withRetry, sd as derivePartitionAndUrlSuffix, sl as recoverMaskedOutput, st as isAbsoluteAssetPath, t as DeployEngine, tc as requireConfigArray, u as STREAM_TAGS_KEY, ua as withIndeterminateGuard, uc as ecsServiceLaunchTypeSetOrChanged, v as streamPolicyMatchesDeclared, va as reEnableInstanceApiTermination, vs as refuseMalformedResourcesForDestroy, w as planIndexContributorInsightsOps, wi as reserveStackCreateToken, x as contributorInsightsRefusals, xd as displayAssemblyPath, y as streamTagsMatchDeclared, z as relayedIndexBusyDelete, zi as definedAttributes, zn as redactedDeleteAddressSkip } from "./deploy-engine-DZO2SOQJ.js";
|
|
6
|
+
import { n as collectInlinePolicyNamesManagedBySiblings, r as IamCreateClientCache, t as IAMRoleProvider } from "./iam-role-provider-BWw7I-SZ.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-CS420Kx9.js";
|
|
8
8
|
import { t as modifyDbInstanceWhenAvailable } from "./db-instance-modify-retry-BUG7NMWS.js";
|
|
9
|
-
import { RDSProvider } from "./rds-provider-
|
|
10
|
-
import { NeptuneProvider } from "./neptune-provider-
|
|
11
|
-
import { ASGProvider } from "./asg-provider-
|
|
9
|
+
import { RDSProvider } from "./rds-provider-BqwTQeS-.js";
|
|
10
|
+
import { NeptuneProvider } from "./neptune-provider-8kjFmR1l.js";
|
|
11
|
+
import { ASGProvider } from "./asg-provider-I1bFHVsO.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";
|
|
@@ -53,17 +53,17 @@ import { BudgetsClient, CreateBudgetCommand, CreateNotificationCommand, CreateSu
|
|
|
53
53
|
import { AddTagsToStreamCommand, CreateStreamCommand, DecreaseStreamRetentionPeriodCommand, DeleteStreamCommand, DeregisterStreamConsumerCommand, DescribeStreamCommand, DescribeStreamConsumerCommand, DescribeStreamSummaryCommand, DisableEnhancedMonitoringCommand, EnableEnhancedMonitoringCommand, IncreaseStreamRetentionPeriodCommand, KinesisClient, ListTagsForResourceCommand as ListTagsForResourceCommand$16, ListTagsForStreamCommand, RegisterStreamConsumerCommand, RemoveTagsFromStreamCommand, ResourceNotFoundException as ResourceNotFoundException$12, StartStreamEncryptionCommand, StopStreamEncryptionCommand, TagResourceCommand as TagResourceCommand$21, UntagResourceCommand as UntagResourceCommand$22, UpdateMaxRecordSizeCommand, UpdateShardCountCommand, UpdateStreamModeCommand, UpdateStreamRecordDistributionStrategyCommand } from "@aws-sdk/client-kinesis";
|
|
54
54
|
import { CreateScheduleCommand, DeleteScheduleCommand, GetScheduleCommand, ListSchedulesCommand, ResourceNotFoundException as ResourceNotFoundException$13, SchedulerClient, UpdateScheduleCommand } from "@aws-sdk/client-scheduler";
|
|
55
55
|
import { CreatePipeCommand, DeletePipeCommand, DescribePipeCommand, NotFoundException as NotFoundException$6, PipesClient, TagResourceCommand as TagResourceCommand$22, UntagResourceCommand as UntagResourceCommand$23, UpdatePipeCommand } from "@aws-sdk/client-pipes";
|
|
56
|
-
import { AccessPointAlreadyExists, AccessPointNotFound, CreateAccessPointCommand, CreateFileSystemCommand, CreateMountTargetCommand, DeleteAccessPointCommand, DeleteFileSystemCommand, DeleteMountTargetCommand, DescribeAccessPointsCommand, DescribeBackupPolicyCommand, DescribeFileSystemPolicyCommand, DescribeFileSystemsCommand, DescribeLifecycleConfigurationCommand, DescribeMountTargetSecurityGroupsCommand, DescribeMountTargetsCommand, EFSClient, FileSystemAlreadyExists, FileSystemNotFound, ModifyMountTargetSecurityGroupsCommand, MountTargetNotFound, PutBackupPolicyCommand, PutFileSystemPolicyCommand, PutLifecycleConfigurationCommand, UpdateFileSystemCommand, UpdateFileSystemProtectionCommand } from "@aws-sdk/client-efs";
|
|
57
|
-
import { CreateFileSystemCommand as CreateFileSystemCommand$1, CreateFileSystemFromBackupCommand, DeleteFileSystemCommand as DeleteFileSystemCommand$1, DescribeFileSystemsCommand as DescribeFileSystemsCommand$1, FSxClient, FileSystemNotFound as FileSystemNotFound$1, TagResourceCommand as TagResourceCommand$
|
|
56
|
+
import { AccessPointAlreadyExists, AccessPointNotFound, CreateAccessPointCommand, CreateFileSystemCommand, CreateMountTargetCommand, DeleteAccessPointCommand, DeleteFileSystemCommand, DeleteFileSystemPolicyCommand, DeleteMountTargetCommand, DescribeAccessPointsCommand, DescribeBackupPolicyCommand, DescribeFileSystemPolicyCommand, DescribeFileSystemsCommand, DescribeLifecycleConfigurationCommand, DescribeMountTargetSecurityGroupsCommand, DescribeMountTargetsCommand, EFSClient, FileSystemAlreadyExists, FileSystemNotFound, ModifyMountTargetSecurityGroupsCommand, MountTargetNotFound, PutBackupPolicyCommand, PutFileSystemPolicyCommand, PutLifecycleConfigurationCommand, TagResourceCommand as TagResourceCommand$23, UntagResourceCommand as UntagResourceCommand$24, UpdateFileSystemCommand, UpdateFileSystemProtectionCommand } from "@aws-sdk/client-efs";
|
|
57
|
+
import { AssociateFileSystemAliasesCommand, CreateFileSystemCommand as CreateFileSystemCommand$1, CreateFileSystemFromBackupCommand, DeleteFileSystemCommand as DeleteFileSystemCommand$1, DescribeFileSystemAliasesCommand, DescribeFileSystemsCommand as DescribeFileSystemsCommand$1, DisassociateFileSystemAliasesCommand, FSxClient, FileSystemNotFound as FileSystemNotFound$1, TagResourceCommand as TagResourceCommand$24, UntagResourceCommand as UntagResourceCommand$25, UpdateFileSystemCommand as UpdateFileSystemCommand$1 } from "@aws-sdk/client-fsx";
|
|
58
58
|
import { AddInstanceFleetCommand, AddInstanceGroupsCommand, AddTagsCommand as AddTagsCommand$1, DescribeClusterCommand, EMRClient, InvalidRequestException, ListClustersCommand, ListInstanceFleetsCommand, ListInstanceGroupsCommand, ModifyClusterCommand, ModifyInstanceFleetCommand, ModifyInstanceGroupsCommand, PutAutoScalingPolicyCommand, PutAutoTerminationPolicyCommand, PutManagedScalingPolicyCommand, RemoveAutoScalingPolicyCommand, RemoveAutoTerminationPolicyCommand, RemoveManagedScalingPolicyCommand, RemoveTagsCommand as RemoveTagsCommand$1, RunJobFlowCommand, SetTerminationProtectionCommand, SetUnhealthyNodeReplacementCommand, SetVisibleToAllUsersCommand, TerminateJobFlowsCommand } from "@aws-sdk/client-emr";
|
|
59
59
|
import { CreateDeliveryStreamCommand, DeleteDeliveryStreamCommand, DescribeDeliveryStreamCommand, FirehoseClient, ListTagsForDeliveryStreamCommand, ResourceNotFoundException as ResourceNotFoundException$14, StartDeliveryStreamEncryptionCommand, StopDeliveryStreamEncryptionCommand, TagDeliveryStreamCommand, UntagDeliveryStreamCommand, UpdateDestinationCommand } from "@aws-sdk/client-firehose";
|
|
60
|
-
import { AddTagsCommand as AddTagsCommand$2, CloudTrailClient, CreateTrailCommand, DeleteTrailCommand, GetEventSelectorsCommand, GetInsightSelectorsCommand, GetTrailCommand, GetTrailStatusCommand, ListTagsCommand as ListTagsCommand$2, PutEventSelectorsCommand, PutInsightSelectorsCommand, RemoveTagsCommand as RemoveTagsCommand$2, StartLoggingCommand, StopLoggingCommand, TrailNotFoundException, UpdateTrailCommand } from "@aws-sdk/client-cloudtrail";
|
|
60
|
+
import { AddTagsCommand as AddTagsCommand$2, CloudTrailClient, CreateTrailCommand, DeleteTrailCommand, GetEventConfigurationCommand, GetEventSelectorsCommand, GetInsightSelectorsCommand, GetTrailCommand, GetTrailStatusCommand, ListTagsCommand as ListTagsCommand$2, PutEventConfigurationCommand, PutEventSelectorsCommand, PutInsightSelectorsCommand, RemoveTagsCommand as RemoveTagsCommand$2, StartLoggingCommand, StopLoggingCommand, TrailNotFoundException, UpdateTrailCommand } from "@aws-sdk/client-cloudtrail";
|
|
61
61
|
import { BatchGetProjectsCommand, CodeBuildClient, CreateProjectCommand, DeleteProjectCommand, ResourceNotFoundException as ResourceNotFoundException$15, UpdateProjectCommand, UpdateProjectVisibilityCommand } from "@aws-sdk/client-codebuild";
|
|
62
|
-
import { CodeCommitClient, CreateCommitCommand, CreateRepositoryCommand as CreateRepositoryCommand$1, DeleteRepositoryCommand as DeleteRepositoryCommand$1, GetRepositoryCommand, GetRepositoryTriggersCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$17, PutRepositoryTriggersCommand, RepositoryDoesNotExistException, TagResourceCommand as TagResourceCommand$
|
|
63
|
-
import { CreateLifecyclePolicyCommand, DLMClient, DeleteLifecyclePolicyCommand as DeleteLifecyclePolicyCommand$1, GetLifecyclePoliciesCommand, GetLifecyclePolicyCommand as GetLifecyclePolicyCommand$1, ResourceNotFoundException as ResourceNotFoundException$16, TagResourceCommand as TagResourceCommand$
|
|
64
|
-
import { CreateVectorBucketCommand, DeleteIndexCommand, DeleteVectorBucketCommand, GetVectorBucketCommand, ListIndexesCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$18, S3VectorsClient, TagResourceCommand as TagResourceCommand$
|
|
65
|
-
import { ListTagsForResourceCommand as ListTagsForResourceCommand$19, S3ControlClient, TagResourceCommand as TagResourceCommand$
|
|
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$
|
|
62
|
+
import { CodeCommitClient, CreateCommitCommand, CreateRepositoryCommand as CreateRepositoryCommand$1, DeleteRepositoryCommand as DeleteRepositoryCommand$1, GetRepositoryCommand, GetRepositoryTriggersCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$17, PutRepositoryTriggersCommand, RepositoryDoesNotExistException, TagResourceCommand as TagResourceCommand$25, UntagResourceCommand as UntagResourceCommand$26, UpdateRepositoryDescriptionCommand, UpdateRepositoryEncryptionKeyCommand, UpdateRepositoryNameCommand } from "@aws-sdk/client-codecommit";
|
|
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
|
+
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
|
+
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";
|
|
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";
|
|
@@ -7924,6 +7924,13 @@ function inlineCodeFileNameForRuntime(runtime) {
|
|
|
7924
7924
|
if (runtime?.startsWith("python")) return "index.py";
|
|
7925
7925
|
return "index.js";
|
|
7926
7926
|
}
|
|
7927
|
+
const SEPARATELY_APPLIED_KEYS = /* @__PURE__ */ new Set([
|
|
7928
|
+
"Tags",
|
|
7929
|
+
"ReservedConcurrentExecutions",
|
|
7930
|
+
"RecursiveLoop",
|
|
7931
|
+
"CodeSigningConfigArn",
|
|
7932
|
+
"RuntimeManagementConfig"
|
|
7933
|
+
]);
|
|
7927
7934
|
var LambdaFunctionProvider = class {
|
|
7928
7935
|
lambdaClient;
|
|
7929
7936
|
createClient = new LambdaCreateClientCache(() => this.lambdaClient);
|
|
@@ -8168,6 +8175,7 @@ var LambdaFunctionProvider = class {
|
|
|
8168
8175
|
}));
|
|
8169
8176
|
}
|
|
8170
8177
|
async update(logicalId, physicalId, resourceType, properties, previousProperties, context) {
|
|
8178
|
+
const markUnsettled = (key) => context?.markUnsettled?.(key);
|
|
8171
8179
|
properties = withRemovalDefaults(this.removalDefaults, resourceType, properties, previousProperties, context);
|
|
8172
8180
|
const log = lambdaOperationSinks(this.logger, context?.maskSecrets, [[physicalId, physicalId], [previousProperties["FunctionName"], physicalId]], properties);
|
|
8173
8181
|
const operationMask = log.mask;
|
|
@@ -8195,12 +8203,9 @@ var LambdaFunctionProvider = class {
|
|
|
8195
8203
|
"LoggingConfig",
|
|
8196
8204
|
"DurableConfig"
|
|
8197
8205
|
];
|
|
8198
|
-
|
|
8199
|
-
for (const field of configFields) if (JSON.stringify(properties[field]) !== JSON.stringify(previousProperties[field]))
|
|
8200
|
-
|
|
8201
|
-
break;
|
|
8202
|
-
}
|
|
8203
|
-
if (hasConfigChanges) {
|
|
8206
|
+
const changedConfigFields = [];
|
|
8207
|
+
for (const field of configFields) if (JSON.stringify(properties[field]) !== JSON.stringify(previousProperties[field])) changedConfigFields.push(field);
|
|
8208
|
+
if (changedConfigFields.length > 0) {
|
|
8204
8209
|
const configParams = {
|
|
8205
8210
|
FunctionName: physicalId,
|
|
8206
8211
|
Role: properties["Role"],
|
|
@@ -8222,6 +8227,7 @@ var LambdaFunctionProvider = class {
|
|
|
8222
8227
|
LoggingConfig: properties["LoggingConfig"],
|
|
8223
8228
|
DurableConfig: properties["DurableConfig"]
|
|
8224
8229
|
};
|
|
8230
|
+
for (const field of changedConfigFields) markUnsettled(field);
|
|
8225
8231
|
await this.lambdaClient.send(new UpdateFunctionConfigurationCommand(configParams));
|
|
8226
8232
|
log.debug(`Updated configuration for Lambda function ${log.value(physicalId)}`);
|
|
8227
8233
|
await this.waitForFunctionUpdated(logicalId, resourceType, physicalId, log);
|
|
@@ -8229,6 +8235,7 @@ var LambdaFunctionProvider = class {
|
|
|
8229
8235
|
const newCodeSigningConfigArn = properties["CodeSigningConfigArn"];
|
|
8230
8236
|
const codeSigningChanged = newCodeSigningConfigArn !== previousProperties["CodeSigningConfigArn"];
|
|
8231
8237
|
if (codeSigningChanged && newCodeSigningConfigArn === void 0) {
|
|
8238
|
+
markUnsettled("CodeSigningConfigArn");
|
|
8232
8239
|
await this.lambdaClient.send(new DeleteFunctionCodeSigningConfigCommand({ FunctionName: physicalId }));
|
|
8233
8240
|
log.debug(`Detached CodeSigningConfigArn from Lambda function ${log.value(physicalId)} (template removed the property)`);
|
|
8234
8241
|
}
|
|
@@ -8249,6 +8256,8 @@ var LambdaFunctionProvider = class {
|
|
|
8249
8256
|
ImageUri: builtCode.ImageUri,
|
|
8250
8257
|
Architectures: architecturesChanged ? normalizeArchitectures(properties["Architectures"]) : void 0
|
|
8251
8258
|
};
|
|
8259
|
+
markUnsettled("Code");
|
|
8260
|
+
if (architecturesChanged) markUnsettled("Architectures");
|
|
8252
8261
|
await this.lambdaClient.send(new UpdateFunctionCodeCommand(codeParams));
|
|
8253
8262
|
log.debug(`Updated code for Lambda function ${log.value(physicalId)}`);
|
|
8254
8263
|
await this.waitForFunctionUpdated(logicalId, resourceType, physicalId, log);
|
|
@@ -8256,6 +8265,7 @@ var LambdaFunctionProvider = class {
|
|
|
8256
8265
|
const newRecursiveLoop = properties["RecursiveLoop"];
|
|
8257
8266
|
const prevRecursiveLoop = previousProperties["RecursiveLoop"];
|
|
8258
8267
|
if (newRecursiveLoop !== void 0 && newRecursiveLoop !== prevRecursiveLoop) {
|
|
8268
|
+
markUnsettled("RecursiveLoop");
|
|
8259
8269
|
await this.lambdaClient.send(new PutFunctionRecursionConfigCommand({
|
|
8260
8270
|
FunctionName: physicalId,
|
|
8261
8271
|
RecursiveLoop: newRecursiveLoop
|
|
@@ -8264,6 +8274,7 @@ var LambdaFunctionProvider = class {
|
|
|
8264
8274
|
}
|
|
8265
8275
|
const newReservedConcurrentExecutions = properties["ReservedConcurrentExecutions"];
|
|
8266
8276
|
if (newReservedConcurrentExecutions !== previousProperties["ReservedConcurrentExecutions"]) {
|
|
8277
|
+
markUnsettled("ReservedConcurrentExecutions");
|
|
8267
8278
|
if (newReservedConcurrentExecutions === void 0) {
|
|
8268
8279
|
await this.lambdaClient.send(new DeleteFunctionConcurrencyCommand({ FunctionName: physicalId }));
|
|
8269
8280
|
log.debug(`Cleared ReservedConcurrentExecutions for Lambda function ${log.value(physicalId)} (template removed the property)`);
|
|
@@ -8276,6 +8287,7 @@ var LambdaFunctionProvider = class {
|
|
|
8276
8287
|
}
|
|
8277
8288
|
}
|
|
8278
8289
|
if (codeSigningChanged && newCodeSigningConfigArn !== void 0) {
|
|
8290
|
+
markUnsettled("CodeSigningConfigArn");
|
|
8279
8291
|
await this.lambdaClient.send(new PutFunctionCodeSigningConfigCommand({
|
|
8280
8292
|
FunctionName: physicalId,
|
|
8281
8293
|
CodeSigningConfigArn: newCodeSigningConfigArn
|
|
@@ -8285,12 +8297,16 @@ var LambdaFunctionProvider = class {
|
|
|
8285
8297
|
const newRuntimeManagementConfig = properties["RuntimeManagementConfig"];
|
|
8286
8298
|
const prevRuntimeManagementConfig = previousProperties["RuntimeManagementConfig"];
|
|
8287
8299
|
if (newRuntimeManagementConfig?.["UpdateRuntimeOn"] !== prevRuntimeManagementConfig?.["UpdateRuntimeOn"] || newRuntimeManagementConfig?.["RuntimeVersionArn"] !== prevRuntimeManagementConfig?.["RuntimeVersionArn"]) {
|
|
8300
|
+
markUnsettled("RuntimeManagementConfig");
|
|
8288
8301
|
await this.putRuntimeManagementConfig(physicalId, newRuntimeManagementConfig ?? { UpdateRuntimeOn: "Auto" });
|
|
8289
8302
|
log.debug(`Updated RuntimeManagementConfig for Lambda function ${log.value(physicalId)} to ${JSON.stringify(maskDeep(newRuntimeManagementConfig ?? { UpdateRuntimeOn: "Auto" }, operationMask))}`);
|
|
8290
8303
|
}
|
|
8291
8304
|
const getResponse = await this.lambdaClient.send(new GetFunctionCommand({ FunctionName: physicalId }));
|
|
8292
8305
|
const functionArn = getResponse.Configuration?.FunctionArn;
|
|
8293
|
-
await this.applyTagDiff(functionArn, physicalId, resourceType, logicalId, previousProperties["Tags"], properties["Tags"], log
|
|
8306
|
+
await this.applyTagDiff(functionArn, physicalId, resourceType, logicalId, previousProperties["Tags"], properties["Tags"], log, {
|
|
8307
|
+
forceUpsert: context?.unsettledProperties?.has("Tags") === true,
|
|
8308
|
+
beforeWrite: () => markUnsettled("Tags")
|
|
8309
|
+
});
|
|
8294
8310
|
return {
|
|
8295
8311
|
physicalId,
|
|
8296
8312
|
wasReplaced: false,
|
|
@@ -8377,13 +8393,17 @@ var LambdaFunctionProvider = class {
|
|
|
8377
8393
|
const subnets = raw["SubnetIds"];
|
|
8378
8394
|
return Array.isArray(subnets) && subnets.length > 0;
|
|
8379
8395
|
}
|
|
8380
|
-
async applyTagDiff(functionArn, functionName, resourceType, logicalId, oldTagsRaw, newTagsRaw, log
|
|
8396
|
+
async applyTagDiff(functionArn, functionName, resourceType, logicalId, oldTagsRaw, newTagsRaw, log, unsettled = {
|
|
8397
|
+
forceUpsert: false,
|
|
8398
|
+
beforeWrite: () => void 0
|
|
8399
|
+
}) {
|
|
8381
8400
|
if (!functionArn) return;
|
|
8382
8401
|
const plan = planTagDiff(oldTagsRaw, newTagsRaw);
|
|
8383
8402
|
const tagWarning = tagPlanWarning(plan, resourceType, logicalId);
|
|
8384
8403
|
if (tagWarning !== void 0) log.warn(tagWarning);
|
|
8385
|
-
const tagsToAdd = Object.fromEntries(plan.set);
|
|
8404
|
+
const tagsToAdd = Object.fromEntries(unsettled.forceUpsert ? planTagDiff(void 0, newTagsRaw).set : plan.set);
|
|
8386
8405
|
const tagsToRemove = plan.remove;
|
|
8406
|
+
if (tagsToRemove.length > 0 || Object.keys(tagsToAdd).length > 0) unsettled.beforeWrite();
|
|
8387
8407
|
if (tagsToRemove.length > 0) {
|
|
8388
8408
|
await this.lambdaClient.send(new UntagResourceCommand$1({
|
|
8389
8409
|
Resource: functionArn,
|
|
@@ -8623,6 +8643,43 @@ var LambdaFunctionProvider = class {
|
|
|
8623
8643
|
throw err;
|
|
8624
8644
|
}
|
|
8625
8645
|
}
|
|
8646
|
+
async readUnsettled(physicalId, logicalId, resourceType, names) {
|
|
8647
|
+
const live = await this.readCurrentState(physicalId, logicalId, resourceType);
|
|
8648
|
+
if (typeof live !== "object" || live === null) return live;
|
|
8649
|
+
const out = { ...live };
|
|
8650
|
+
const strict = async (read) => {
|
|
8651
|
+
try {
|
|
8652
|
+
return await read();
|
|
8653
|
+
} catch (error) {
|
|
8654
|
+
if (error instanceof ResourceNotFoundException) return void 0;
|
|
8655
|
+
throw error;
|
|
8656
|
+
}
|
|
8657
|
+
};
|
|
8658
|
+
const set = (key, value) => {
|
|
8659
|
+
if (value === void 0) delete out[key];
|
|
8660
|
+
else out[key] = value;
|
|
8661
|
+
};
|
|
8662
|
+
if (names.has("ReservedConcurrentExecutions")) set("ReservedConcurrentExecutions", (await strict(() => this.lambdaClient.send(new GetFunctionConcurrencyCommand({ FunctionName: physicalId }))))?.ReservedConcurrentExecutions);
|
|
8663
|
+
if (names.has("RecursiveLoop")) set("RecursiveLoop", (await strict(() => this.lambdaClient.send(new GetFunctionRecursionConfigCommand({ FunctionName: physicalId }))))?.RecursiveLoop);
|
|
8664
|
+
if (names.has("RuntimeManagementConfig")) {
|
|
8665
|
+
const r = await strict(() => this.lambdaClient.send(new GetRuntimeManagementConfigCommand({ FunctionName: physicalId })));
|
|
8666
|
+
set("RuntimeManagementConfig", r?.UpdateRuntimeOn === void 0 ? void 0 : {
|
|
8667
|
+
UpdateRuntimeOn: r.UpdateRuntimeOn,
|
|
8668
|
+
...r.RuntimeVersionArn !== void 0 && { RuntimeVersionArn: r.RuntimeVersionArn }
|
|
8669
|
+
});
|
|
8670
|
+
}
|
|
8671
|
+
if (names.has("CodeSigningConfigArn")) set("CodeSigningConfigArn", (await strict(() => this.lambdaClient.send(new GetFunctionCodeSigningConfigCommand({ FunctionName: physicalId }))))?.CodeSigningConfigArn);
|
|
8672
|
+
return out;
|
|
8673
|
+
}
|
|
8674
|
+
async unsettledInTransition(physicalId, _logicalId, _resourceType, names) {
|
|
8675
|
+
try {
|
|
8676
|
+
const cfg = (await this.lambdaClient.send(new GetFunctionCommand({ FunctionName: physicalId }))).Configuration;
|
|
8677
|
+
if (cfg?.State !== "Pending" && cfg?.LastUpdateStatus !== "InProgress") return /* @__PURE__ */ new Set();
|
|
8678
|
+
return new Set([...names].filter((name) => !SEPARATELY_APPLIED_KEYS.has(name)));
|
|
8679
|
+
} catch {
|
|
8680
|
+
return names;
|
|
8681
|
+
}
|
|
8682
|
+
}
|
|
8626
8683
|
async readCurrentState(physicalId, _logicalId, _resourceType) {
|
|
8627
8684
|
try {
|
|
8628
8685
|
const resp = await this.lambdaClient.send(new GetFunctionCommand({ FunctionName: physicalId }));
|
|
@@ -12267,6 +12324,7 @@ var DynamoDBTableProvider = class {
|
|
|
12267
12324
|
}
|
|
12268
12325
|
}
|
|
12269
12326
|
async update(logicalId, physicalId, resourceType, properties, previousProperties, context) {
|
|
12327
|
+
const markUnsettled = (key) => context?.markUnsettled?.(key);
|
|
12270
12328
|
const maskSecrets = context?.maskSecrets ?? ((text) => text);
|
|
12271
12329
|
const warn = (message) => this.logger.warn(maskSecrets(message));
|
|
12272
12330
|
const debug = (message) => this.logger.debug(maskSecrets(message));
|
|
@@ -12310,7 +12368,10 @@ var DynamoDBTableProvider = class {
|
|
|
12310
12368
|
warn(`${lsiMessage}; the LocalSecondaryIndexes change was not applied`);
|
|
12311
12369
|
}
|
|
12312
12370
|
let latestStreamArn = table?.LatestStreamArn;
|
|
12313
|
-
if (table?.TableArn) await this.applyTagDiff(table.TableArn, resourceType, logicalId, previousProperties["Tags"], properties["Tags"]
|
|
12371
|
+
if (table?.TableArn) await this.applyTagDiff(table.TableArn, resourceType, logicalId, previousProperties["Tags"], properties["Tags"], {
|
|
12372
|
+
forceUpsert: context?.unsettledProperties?.has("Tags") === true,
|
|
12373
|
+
beforeWrite: () => markUnsettled("Tags")
|
|
12374
|
+
});
|
|
12314
12375
|
const normalizeTableClass = (v) => typeof v === "string" && v.length > 0 ? v : "STANDARD";
|
|
12315
12376
|
const tableClassChanged = normalizeTableClass(properties["TableClass"]) !== normalizeTableClass(previousProperties["TableClass"]);
|
|
12316
12377
|
const liveBillingMode = table?.BillingModeSummary?.BillingMode ?? "PROVISIONED";
|
|
@@ -12369,6 +12430,7 @@ var DynamoDBTableProvider = class {
|
|
|
12369
12430
|
warn(`AWS::DynamoDB::Table ${logicalId}: this deploy removes global secondary index(es) ${removable.map((n) => maskSecrets(n)).join(", ")} and flips BillingMode to PROVISIONED. The removal would normally be applied BEFORE the flip, but ${reasons.join(" and ")}, so AWS rejects the flip either way. Nothing was removed.`);
|
|
12370
12431
|
} else if (removable.length > 0) {
|
|
12371
12432
|
debug(`Deleting GSI(s) ${removable.join(", ")} on DynamoDB table ${physicalId} before the BillingMode flip to PROVISIONED`);
|
|
12433
|
+
markUnsettled("GlobalSecondaryIndexes");
|
|
12372
12434
|
await this.runGsiOps(physicalId, removable.map((name) => ({ Delete: { IndexName: name } })), void 0, maskSecrets);
|
|
12373
12435
|
for (const name of removable) preFlipDeletedIndexNames.add(name);
|
|
12374
12436
|
}
|
|
@@ -12415,6 +12477,10 @@ var DynamoDBTableProvider = class {
|
|
|
12415
12477
|
if (indexUpdates.length > 0) updateInput.GlobalSecondaryIndexUpdates = indexUpdates;
|
|
12416
12478
|
if (unspecified.length > 0) warn(`AWS::DynamoDB::Table ${logicalId}: flipping BillingMode to PROVISIONED, but the template declares no usable ProvisionedThroughput for live index(es) ${unspecified.map((n) => maskSecrets(n)).join(", ")}. AWS requires per-index capacity in the same UpdateTable and will reject the flip naming them. Declare GlobalSecondaryIndexes[].ProvisionedThroughput (both ReadCapacityUnits and WriteCapacityUnits) for each. An index this deploy REMOVES is deleted BEFORE the flip automatically, so a name here is one the template still keeps, one that exists in AWS but in neither the template nor cdkd state (created out of band), or one whose pre-flip removal was skipped for the reason warned above.`);
|
|
12417
12479
|
}
|
|
12480
|
+
if (billingMode !== prevBillingMode) markUnsettled("BillingMode");
|
|
12481
|
+
if (JSON.stringify(properties["ProvisionedThroughput"]) !== JSON.stringify(previousProperties["ProvisionedThroughput"])) markUnsettled("ProvisionedThroughput");
|
|
12482
|
+
if (tableClassChanged) markUnsettled("TableClass");
|
|
12483
|
+
if (updateInput.GlobalSecondaryIndexUpdates !== void 0) markUnsettled("GlobalSecondaryIndexes");
|
|
12418
12484
|
await this.dynamoDBClient.send(new UpdateTableCommand(updateInput));
|
|
12419
12485
|
if (billingMode !== liveBillingMode) await this.waitForTableAndIndexesActive(physicalId, BILLING_FLIP_ACTIVE_WAIT_ATTEMPTS);
|
|
12420
12486
|
else await this.waitForTableActiveAfterUpdate(physicalId, 60);
|
|
@@ -12425,6 +12491,7 @@ var DynamoDBTableProvider = class {
|
|
|
12425
12491
|
if (properties["OnDemandThroughput"] || ceilingRemovals.length > 0) {
|
|
12426
12492
|
const declaredForSend = properties["OnDemandThroughput"] ? this.coerceOnDemandCeilingsForSend(`AWS::DynamoDB::Table ${logicalId}`, properties["OnDemandThroughput"], maskSecrets) : {};
|
|
12427
12493
|
if (ceilingRemovals.length > 0) debug(`AWS::DynamoDB::Table ${logicalId}: removing the OnDemandThroughput ${ceilingRemovals.join(" / ")} the template no longer declares (sending ${ON_DEMAND_LIMIT_RESET}, DynamoDB's reset sentinel)`);
|
|
12494
|
+
markUnsettled("OnDemandThroughput");
|
|
12428
12495
|
await this.dynamoDBClient.send(new UpdateTableCommand({
|
|
12429
12496
|
TableName: physicalId,
|
|
12430
12497
|
OnDemandThroughput: withOnDemandCeilingRemovals(declaredForSend, ceilingRemovals)
|
|
@@ -12437,6 +12504,7 @@ var DynamoDBTableProvider = class {
|
|
|
12437
12504
|
this.warnRefusedWarmThroughput(`AWS::DynamoDB::Table ${logicalId}`, properties["WarmThroughput"], maskSecrets);
|
|
12438
12505
|
const warmThroughputToSend = this.coerceWarmThroughputForSend(`AWS::DynamoDB::Table ${logicalId}`, properties["WarmThroughput"], maskSecrets);
|
|
12439
12506
|
if (warmThroughputToSend !== void 0 && !this.skipWarmThroughputDecrease(logicalId, physicalId, warmThroughputToSend, table?.WarmThroughput, maskSecrets)) {
|
|
12507
|
+
markUnsettled("WarmThroughput");
|
|
12440
12508
|
await this.dynamoDBClient.send(new UpdateTableCommand({
|
|
12441
12509
|
TableName: physicalId,
|
|
12442
12510
|
WarmThroughput: warmThroughputToSend
|
|
@@ -12452,6 +12520,7 @@ var DynamoDBTableProvider = class {
|
|
|
12452
12520
|
if (liveSseStatus === "UPDATING" || liveSseStatus === "ENABLING" || liveSseStatus === "DISABLING") liveTable = await this.waitForTableSseSettled(physicalId, maskSecrets);
|
|
12453
12521
|
const sseUpdate = sseSpecificationToSend(properties["SSESpecification"], previousProperties["SSESpecification"], liveTable?.SSEDescription, liveTable !== void 0);
|
|
12454
12522
|
if (sseUpdate !== void 0) {
|
|
12523
|
+
markUnsettled("SSESpecification");
|
|
12455
12524
|
await this.dynamoDBClient.send(new UpdateTableCommand({
|
|
12456
12525
|
TableName: physicalId,
|
|
12457
12526
|
SSESpecification: sseUpdate
|
|
@@ -12465,6 +12534,7 @@ var DynamoDBTableProvider = class {
|
|
|
12465
12534
|
const desiredDeletionProtection = rawDeletionProtection === void 0 ? false : coerceCfnBoolean(rawDeletionProtection);
|
|
12466
12535
|
if (desiredDeletionProtection === void 0) warn(`AWS::DynamoDB::Table ${logicalId}: DeletionProtectionEnabled is not a boolean, so it was not applied`);
|
|
12467
12536
|
else if (table?.DeletionProtectionEnabled !== desiredDeletionProtection) {
|
|
12537
|
+
markUnsettled("DeletionProtectionEnabled");
|
|
12468
12538
|
await this.dynamoDBClient.send(new UpdateTableCommand({
|
|
12469
12539
|
TableName: physicalId,
|
|
12470
12540
|
DeletionProtectionEnabled: desiredDeletionProtection
|
|
@@ -12474,6 +12544,7 @@ var DynamoDBTableProvider = class {
|
|
|
12474
12544
|
}
|
|
12475
12545
|
}
|
|
12476
12546
|
if (JSON.stringify(properties["StreamSpecification"]) !== JSON.stringify(previousProperties["StreamSpecification"])) {
|
|
12547
|
+
markUnsettled("StreamSpecification");
|
|
12477
12548
|
const newViewType = this.extractStreamViewType(properties["StreamSpecification"]);
|
|
12478
12549
|
const prevViewType = this.extractStreamViewType(previousProperties["StreamSpecification"]);
|
|
12479
12550
|
const liveStream = table?.StreamSpecification;
|
|
@@ -12521,10 +12592,18 @@ var DynamoDBTableProvider = class {
|
|
|
12521
12592
|
}
|
|
12522
12593
|
if (newViewType) await this.applyStreamMembers(logicalId, resourceType, physicalId, latestStreamArn, properties["StreamSpecification"], previousProperties["StreamSpecification"], mintedStream, maskSecrets, mintedStream ? preUpdateStreamArn : void 0, contentsUnknown);
|
|
12523
12594
|
}
|
|
12524
|
-
if (
|
|
12525
|
-
if (JSON.stringify(properties["
|
|
12595
|
+
if (context?.unsettledProperties?.has("GlobalSecondaryIndexes") === true && currentLiveIndexNames !== void 0) this.warnUndeclaredLiveIndexes(physicalId, currentLiveIndexNames, [previousProperties["GlobalSecondaryIndexes"], properties["GlobalSecondaryIndexes"]], maskSecrets);
|
|
12596
|
+
if (JSON.stringify(properties["GlobalSecondaryIndexes"]) !== JSON.stringify(previousProperties["GlobalSecondaryIndexes"])) {
|
|
12597
|
+
markUnsettled("GlobalSecondaryIndexes");
|
|
12598
|
+
await this.applyGsiUpdates(physicalId, resourceType, logicalId, previousProperties["GlobalSecondaryIndexes"], properties["GlobalSecondaryIndexes"], properties["AttributeDefinitions"], gsiHandledByBillingFlip, currentLiveIndexNames, currentLiveIndexByName, liveCapacityComparable, effectiveBillingMode === "PAY_PER_REQUEST", maskSecrets);
|
|
12599
|
+
}
|
|
12600
|
+
if (JSON.stringify(properties["PointInTimeRecoverySpecification"]) !== JSON.stringify(previousProperties["PointInTimeRecoverySpecification"])) {
|
|
12601
|
+
markUnsettled("PointInTimeRecoverySpecification");
|
|
12602
|
+
await this.applyPointInTimeRecovery(physicalId, properties["PointInTimeRecoverySpecification"], previousProperties["PointInTimeRecoverySpecification"], maskSecrets);
|
|
12603
|
+
}
|
|
12526
12604
|
if (JSON.stringify(properties["TimeToLiveSpecification"]) !== JSON.stringify(previousProperties["TimeToLiveSpecification"])) {
|
|
12527
12605
|
this.assertNoActiveTtlAttributeNameChange(logicalId, resourceType, physicalId, properties["TimeToLiveSpecification"], previousProperties["TimeToLiveSpecification"]);
|
|
12606
|
+
markUnsettled("TimeToLiveSpecification");
|
|
12528
12607
|
await this.applyTimeToLive(physicalId, properties["TimeToLiveSpecification"], previousProperties["TimeToLiveSpecification"], "update", {
|
|
12529
12608
|
logicalId,
|
|
12530
12609
|
resourceType,
|
|
@@ -12533,11 +12612,18 @@ var DynamoDBTableProvider = class {
|
|
|
12533
12612
|
}
|
|
12534
12613
|
if (JSON.stringify(properties["ResourcePolicy"]) !== JSON.stringify(previousProperties["ResourcePolicy"])) {
|
|
12535
12614
|
if (!table?.TableArn) throw new ProvisioningError(`Cannot apply ResourcePolicy change for DynamoDB table ${logicalId}: DescribeTable returned no TableArn`, resourceType, logicalId, physicalId);
|
|
12615
|
+
markUnsettled("ResourcePolicy");
|
|
12536
12616
|
await this.applyResourcePolicy(table.TableArn, properties["ResourcePolicy"], previousProperties["ResourcePolicy"]);
|
|
12537
12617
|
}
|
|
12538
|
-
if (JSON.stringify(properties["KinesisStreamSpecification"]) !== JSON.stringify(previousProperties["KinesisStreamSpecification"]))
|
|
12539
|
-
|
|
12540
|
-
|
|
12618
|
+
if (JSON.stringify(properties["KinesisStreamSpecification"]) !== JSON.stringify(previousProperties["KinesisStreamSpecification"])) {
|
|
12619
|
+
markUnsettled("KinesisStreamSpecification");
|
|
12620
|
+
await this.applyKinesisStreamingDestination(physicalId, properties["KinesisStreamSpecification"], previousProperties["KinesisStreamSpecification"], maskSecrets);
|
|
12621
|
+
}
|
|
12622
|
+
if (JSON.stringify(properties["ContributorInsightsSpecification"]) !== JSON.stringify(previousProperties["ContributorInsightsSpecification"])) {
|
|
12623
|
+
markUnsettled("ContributorInsightsSpecification");
|
|
12624
|
+
await this.applyContributorInsights(physicalId, properties["ContributorInsightsSpecification"], previousProperties["ContributorInsightsSpecification"], maskSecrets);
|
|
12625
|
+
}
|
|
12626
|
+
await this.applyIndexContributorInsights(physicalId, properties["GlobalSecondaryIndexes"], previousProperties["GlobalSecondaryIndexes"], maskSecrets, () => markUnsettled("GlobalSecondaryIndexes"));
|
|
12541
12627
|
return {
|
|
12542
12628
|
physicalId,
|
|
12543
12629
|
wasReplaced: false,
|
|
@@ -12675,15 +12761,19 @@ var DynamoDBTableProvider = class {
|
|
|
12675
12761
|
throw error instanceof Error && error.name.includes("NotFound") ? markNotGone(thrown) : thrown;
|
|
12676
12762
|
}
|
|
12677
12763
|
}
|
|
12678
|
-
async applyTagDiff(tableArn, resourceType, logicalId, oldTagsRaw, newTagsRaw
|
|
12764
|
+
async applyTagDiff(tableArn, resourceType, logicalId, oldTagsRaw, newTagsRaw, unsettled = {
|
|
12765
|
+
forceUpsert: false,
|
|
12766
|
+
beforeWrite: () => void 0
|
|
12767
|
+
}) {
|
|
12679
12768
|
const plan = planTagDiff(oldTagsRaw, newTagsRaw);
|
|
12680
12769
|
const tagWarning = tagPlanWarning(plan, resourceType, logicalId);
|
|
12681
12770
|
if (tagWarning !== void 0) this.logger.warn(tagWarning);
|
|
12682
|
-
const tagsToAdd = [...plan.set].map(([k, v]) => ({
|
|
12771
|
+
const tagsToAdd = [...unsettled.forceUpsert ? planTagDiff(void 0, newTagsRaw).set : plan.set].map(([k, v]) => ({
|
|
12683
12772
|
Key: k,
|
|
12684
12773
|
Value: v
|
|
12685
12774
|
}));
|
|
12686
12775
|
const tagsToRemove = plan.remove;
|
|
12776
|
+
if (tagsToRemove.length > 0 || tagsToAdd.length > 0) unsettled.beforeWrite();
|
|
12687
12777
|
if (tagsToRemove.length > 0) {
|
|
12688
12778
|
await this.dynamoDBClient.send(new UntagResourceCommand$2({
|
|
12689
12779
|
ResourceArn: tableArn,
|
|
@@ -12996,12 +13086,15 @@ var DynamoDBTableProvider = class {
|
|
|
12996
13086
|
if (op === void 0) return;
|
|
12997
13087
|
await this.sendContributorInsightsOp(tableName, op, maskSecrets);
|
|
12998
13088
|
}
|
|
12999
|
-
async applyIndexContributorInsights(tableName, desiredIndexes, previousIndexes, maskSecrets) {
|
|
13089
|
+
async applyIndexContributorInsights(tableName, desiredIndexes, previousIndexes, maskSecrets, beforeSend = () => void 0) {
|
|
13000
13090
|
const warn = (message) => this.logger.warn(maskSecrets(message));
|
|
13001
13091
|
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.`));
|
|
13002
13092
|
if (ops.length === 0) return;
|
|
13003
13093
|
await this.waitForTableAndIndexesActive(tableName);
|
|
13004
|
-
for (const op of ops)
|
|
13094
|
+
for (const op of ops) {
|
|
13095
|
+
beforeSend();
|
|
13096
|
+
await this.sendContributorInsightsOp(tableName, op, maskSecrets);
|
|
13097
|
+
}
|
|
13005
13098
|
}
|
|
13006
13099
|
async sendContributorInsightsOp(tableName, op, maskSecrets) {
|
|
13007
13100
|
const debug = (message) => this.logger.debug(maskSecrets(message));
|
|
@@ -13153,6 +13246,21 @@ var DynamoDBTableProvider = class {
|
|
|
13153
13246
|
indexScope(indexName, logicalId, maskSecrets) {
|
|
13154
13247
|
return `GSI ${typeof indexName === "string" ? maskSecrets(indexName) : "<unnamed>"} on AWS::DynamoDB::Table ${logicalId}`;
|
|
13155
13248
|
}
|
|
13249
|
+
warnUndeclaredLiveIndexes(physicalId, liveIndexNames, lists, maskSecrets) {
|
|
13250
|
+
const named = /* @__PURE__ */ new Set();
|
|
13251
|
+
for (const list of lists) {
|
|
13252
|
+
if (!Array.isArray(list)) continue;
|
|
13253
|
+
for (const entry of list) {
|
|
13254
|
+
const name = typeof entry === "object" && entry !== null ? entry["IndexName"] : void 0;
|
|
13255
|
+
if (typeof name === "string") named.add(name);
|
|
13256
|
+
}
|
|
13257
|
+
}
|
|
13258
|
+
for (const name of liveIndexNames) {
|
|
13259
|
+
if (named.has(name)) continue;
|
|
13260
|
+
const secretDerived = maskSecrets(name) !== name || maskSecrets(physicalId) !== physicalId;
|
|
13261
|
+
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)`)));
|
|
13262
|
+
}
|
|
13263
|
+
}
|
|
13156
13264
|
indexScopeAt(indexName, physicalId, maskSecrets) {
|
|
13157
13265
|
return `GSI ${typeof indexName === "string" ? maskSecrets(indexName) : "<unnamed>"} on DynamoDB table ${physicalId}`;
|
|
13158
13266
|
}
|
|
@@ -13439,6 +13547,62 @@ var DynamoDBTableProvider = class {
|
|
|
13439
13547
|
aws
|
|
13440
13548
|
};
|
|
13441
13549
|
}
|
|
13550
|
+
async readUnsettled(physicalId, logicalId, resourceType, names, recordedProperties, desiredProperties) {
|
|
13551
|
+
const live = await this.readCurrentState(physicalId, logicalId, resourceType, recordedProperties);
|
|
13552
|
+
if (typeof live !== "object" || live === null) return live;
|
|
13553
|
+
const out = { ...live };
|
|
13554
|
+
if (out["BillingMode"] === "PAY_PER_REQUEST") delete out["ProvisionedThroughput"];
|
|
13555
|
+
if (names.has("GlobalSecondaryIndexes")) {
|
|
13556
|
+
out["GlobalSecondaryIndexes"] = projectIndexesOnto(out["GlobalSecondaryIndexes"], recordedProperties?.["GlobalSecondaryIndexes"], desiredProperties?.["GlobalSecondaryIndexes"]);
|
|
13557
|
+
if (out["GlobalSecondaryIndexes"] === void 0) delete out["GlobalSecondaryIndexes"];
|
|
13558
|
+
}
|
|
13559
|
+
const strict = async (key, read) => {
|
|
13560
|
+
if (!names.has(key)) return;
|
|
13561
|
+
const value = await read();
|
|
13562
|
+
if (value === void 0) delete out[key];
|
|
13563
|
+
else out[key] = value;
|
|
13564
|
+
};
|
|
13565
|
+
await strict("PointInTimeRecoverySpecification", () => this.readPointInTimeRecovery(physicalId, true));
|
|
13566
|
+
await strict("TimeToLiveSpecification", () => this.readTimeToLive(physicalId, true));
|
|
13567
|
+
await strict("KinesisStreamSpecification", () => this.readKinesisStreamSpecification(physicalId, true));
|
|
13568
|
+
await strict("ContributorInsightsSpecification", () => this.readTableContributorInsights(physicalId, true));
|
|
13569
|
+
if (names.has("ResourcePolicy")) {
|
|
13570
|
+
const table = (await this.dynamoDBClient.send(new DescribeTableCommand({ TableName: physicalId }))).Table;
|
|
13571
|
+
if (!table?.TableArn) throw new ProvisioningError(`DescribeTable returned no TableArn for the table, which reading its unsettled ResourcePolicy needs`, resourceType, logicalId, physicalId);
|
|
13572
|
+
const tableArn = table.TableArn;
|
|
13573
|
+
await strict("ResourcePolicy", () => this.readTableResourcePolicy(physicalId, tableArn, true));
|
|
13574
|
+
}
|
|
13575
|
+
return out;
|
|
13576
|
+
}
|
|
13577
|
+
async unsettledInTransition(physicalId, _logicalId, _resourceType, names) {
|
|
13578
|
+
const SEPARATE = /* @__PURE__ */ new Set([
|
|
13579
|
+
"Tags",
|
|
13580
|
+
"PointInTimeRecoverySpecification",
|
|
13581
|
+
"TimeToLiveSpecification",
|
|
13582
|
+
"ResourcePolicy",
|
|
13583
|
+
"KinesisStreamSpecification",
|
|
13584
|
+
"ContributorInsightsSpecification"
|
|
13585
|
+
]);
|
|
13586
|
+
try {
|
|
13587
|
+
const table = (await this.dynamoDBClient.send(new DescribeTableCommand({ TableName: physicalId }))).Table;
|
|
13588
|
+
const moving = /* @__PURE__ */ new Set();
|
|
13589
|
+
if (table?.TableStatus === "CREATING" || table?.TableStatus === "UPDATING" || table?.TableStatus === "DELETING") {
|
|
13590
|
+
for (const name of names) if (!SEPARATE.has(name)) moving.add(name);
|
|
13591
|
+
}
|
|
13592
|
+
if (names.has("GlobalSecondaryIndexes") && (table?.GlobalSecondaryIndexes ?? []).some((index) => index.IndexStatus === "CREATING" || index.IndexStatus === "UPDATING" || index.IndexStatus === "DELETING")) moving.add("GlobalSecondaryIndexes");
|
|
13593
|
+
const sse = table?.SSEDescription?.Status;
|
|
13594
|
+
if (names.has("SSESpecification") && (sse === "ENABLING" || sse === "DISABLING" || sse === "UPDATING")) moving.add("SSESpecification");
|
|
13595
|
+
if (names.has("TimeToLiveSpecification")) {
|
|
13596
|
+
if ((await this.dynamoDBClient.send(new DescribeTimeToLiveCommand({ TableName: physicalId }))).TimeToLiveDescription?.TimeToLiveStatus === "ENABLING") moving.add("TimeToLiveSpecification");
|
|
13597
|
+
}
|
|
13598
|
+
if (names.has("KinesisStreamSpecification")) {
|
|
13599
|
+
if (((await this.dynamoDBClient.send(new DescribeKinesisStreamingDestinationCommand({ TableName: physicalId }))).KinesisDataStreamDestinations ?? []).some((d) => d.DestinationStatus === "ENABLING" || d.DestinationStatus === "DISABLING" || d.DestinationStatus === "UPDATING")) moving.add("KinesisStreamSpecification");
|
|
13600
|
+
}
|
|
13601
|
+
return moving;
|
|
13602
|
+
} catch {
|
|
13603
|
+
return names;
|
|
13604
|
+
}
|
|
13605
|
+
}
|
|
13442
13606
|
async readCurrentState(physicalId, _logicalId, _resourceType, properties, context) {
|
|
13443
13607
|
try {
|
|
13444
13608
|
const table = (await this.dynamoDBClient.send(new DescribeTableCommand({ TableName: physicalId }))).Table;
|
|
@@ -13521,7 +13685,7 @@ var DynamoDBTableProvider = class {
|
|
|
13521
13685
|
throw err;
|
|
13522
13686
|
}
|
|
13523
13687
|
}
|
|
13524
|
-
async readPointInTimeRecovery(physicalId) {
|
|
13688
|
+
async readPointInTimeRecovery(physicalId, strict = false) {
|
|
13525
13689
|
try {
|
|
13526
13690
|
const pitrDesc = (await this.dynamoDBClient.send(new DescribeContinuousBackupsCommand({ TableName: physicalId }))).ContinuousBackupsDescription?.PointInTimeRecoveryDescription;
|
|
13527
13691
|
const pitrStatus = pitrDesc?.PointInTimeRecoveryStatus;
|
|
@@ -13530,11 +13694,12 @@ var DynamoDBTableProvider = class {
|
|
|
13530
13694
|
if (pitrStatus === "ENABLED" && pitrDesc?.RecoveryPeriodInDays !== void 0) pitr["RecoveryPeriodInDays"] = pitrDesc.RecoveryPeriodInDays;
|
|
13531
13695
|
return pitr;
|
|
13532
13696
|
} catch (err) {
|
|
13697
|
+
if (strict) throw err;
|
|
13533
13698
|
this.logger.debug(`Could not read PointInTimeRecovery for ${physicalId}: ${describeAwsFailure(err).detail}`);
|
|
13534
13699
|
return;
|
|
13535
13700
|
}
|
|
13536
13701
|
}
|
|
13537
|
-
async readTimeToLive(physicalId) {
|
|
13702
|
+
async readTimeToLive(physicalId, strict = false) {
|
|
13538
13703
|
try {
|
|
13539
13704
|
const ttlDesc = (await this.dynamoDBClient.send(new DescribeTimeToLiveCommand({ TableName: physicalId }))).TimeToLiveDescription;
|
|
13540
13705
|
if (ttlDesc?.TimeToLiveStatus === "ENABLED" && ttlDesc.AttributeName) return {
|
|
@@ -13543,11 +13708,12 @@ var DynamoDBTableProvider = class {
|
|
|
13543
13708
|
};
|
|
13544
13709
|
return;
|
|
13545
13710
|
} catch (err) {
|
|
13711
|
+
if (strict) throw err;
|
|
13546
13712
|
this.logger.debug(`Could not read TimeToLive for ${physicalId}: ${describeAwsFailure(err).detail}`);
|
|
13547
13713
|
return;
|
|
13548
13714
|
}
|
|
13549
13715
|
}
|
|
13550
|
-
async readTableResourcePolicy(physicalId, tableArn) {
|
|
13716
|
+
async readTableResourcePolicy(physicalId, tableArn, strict = false) {
|
|
13551
13717
|
try {
|
|
13552
13718
|
const rpResp = await this.dynamoDBClient.send(new GetResourcePolicyCommand({ ResourceArn: tableArn }));
|
|
13553
13719
|
if (!rpResp.Policy) return void 0;
|
|
@@ -13557,11 +13723,12 @@ var DynamoDBTableProvider = class {
|
|
|
13557
13723
|
} catch {}
|
|
13558
13724
|
return { PolicyDocument: doc };
|
|
13559
13725
|
} catch (err) {
|
|
13726
|
+
if (strict && !(err instanceof ResourceNotFoundException$1) && !(err instanceof PolicyNotFoundException)) throw err;
|
|
13560
13727
|
if (!(err instanceof ResourceNotFoundException$1)) this.logger.debug(`Could not read ResourcePolicy for ${physicalId}: ${describeAwsFailure(err).detail}`);
|
|
13561
13728
|
return;
|
|
13562
13729
|
}
|
|
13563
13730
|
}
|
|
13564
|
-
async readKinesisStreamSpecification(physicalId) {
|
|
13731
|
+
async readKinesisStreamSpecification(physicalId, strict = false) {
|
|
13565
13732
|
try {
|
|
13566
13733
|
const active = ((await this.dynamoDBClient.send(new DescribeKinesisStreamingDestinationCommand({ TableName: physicalId }))).KinesisDataStreamDestinations ?? []).find((d) => d.DestinationStatus === "ACTIVE" || d.DestinationStatus === "ENABLING" || d.DestinationStatus === "UPDATING");
|
|
13567
13734
|
if (!active?.StreamArn) return void 0;
|
|
@@ -13569,15 +13736,17 @@ var DynamoDBTableProvider = class {
|
|
|
13569
13736
|
if (active.ApproximateCreationDateTimePrecision !== void 0) kspec["ApproximateCreationDateTimePrecision"] = active.ApproximateCreationDateTimePrecision;
|
|
13570
13737
|
return kspec;
|
|
13571
13738
|
} catch (err) {
|
|
13739
|
+
if (strict) throw err;
|
|
13572
13740
|
this.logger.debug(`Could not read KinesisStreamingDestination for ${physicalId}: ${describeAwsFailure(err).detail}`);
|
|
13573
13741
|
return;
|
|
13574
13742
|
}
|
|
13575
13743
|
}
|
|
13576
|
-
async readTableContributorInsights(physicalId) {
|
|
13744
|
+
async readTableContributorInsights(physicalId, strict = false) {
|
|
13577
13745
|
try {
|
|
13578
13746
|
const ciResp = await this.dynamoDBClient.send(new DescribeContributorInsightsCommand({ TableName: physicalId }));
|
|
13579
13747
|
return reverseMapTableContributorInsights(ciResp.ContributorInsightsStatus, ciResp.ContributorInsightsMode);
|
|
13580
13748
|
} catch (err) {
|
|
13749
|
+
if (strict) throw err;
|
|
13581
13750
|
this.logger.debug(`Could not read ContributorInsights for ${physicalId}: ${describeAwsFailure(err).detail}`);
|
|
13582
13751
|
return;
|
|
13583
13752
|
}
|
|
@@ -13701,6 +13870,22 @@ var DynamoDBTableProvider = class {
|
|
|
13701
13870
|
function isTransientStreamReadFailure(err) {
|
|
13702
13871
|
return isThrottlingError(err) || isTransientServerError(err) || isAmbiguousOutcomeError(err) || err instanceof ResourceNotFoundException$1;
|
|
13703
13872
|
}
|
|
13873
|
+
function projectIndexesOnto(live, recorded, desired) {
|
|
13874
|
+
if (!Array.isArray(live)) return void 0;
|
|
13875
|
+
const named = /* @__PURE__ */ new Set();
|
|
13876
|
+
for (const list of [recorded, desired]) {
|
|
13877
|
+
if (!Array.isArray(list)) continue;
|
|
13878
|
+
for (const entry of list) {
|
|
13879
|
+
const name = typeof entry === "object" && entry !== null ? entry["IndexName"] : void 0;
|
|
13880
|
+
if (typeof name === "string") named.add(name);
|
|
13881
|
+
}
|
|
13882
|
+
}
|
|
13883
|
+
const kept = live.filter((entry) => {
|
|
13884
|
+
const name = typeof entry === "object" && entry !== null ? entry["IndexName"] : void 0;
|
|
13885
|
+
return typeof name === "string" && named.has(name);
|
|
13886
|
+
});
|
|
13887
|
+
return kept.length > 0 ? kept : void 0;
|
|
13888
|
+
}
|
|
13704
13889
|
|
|
13705
13890
|
//#endregion
|
|
13706
13891
|
//#region src/provisioning/providers/logs-loggroup-provider.ts
|
|
@@ -18323,7 +18508,7 @@ var EC2Provider = class {
|
|
|
18323
18508
|
if (!Array.isArray(ingressRules) || ingressRules.length === 0) return;
|
|
18324
18509
|
await this.ec2Client.send(new AuthorizeSecurityGroupIngressCommand({
|
|
18325
18510
|
GroupId: groupId,
|
|
18326
|
-
IpPermissions: ingressRules.map((rule) => this.buildIpPermission(rule))
|
|
18511
|
+
IpPermissions: ingressRules.map((rule) => this.buildIpPermission(rule, "ingress", true))
|
|
18327
18512
|
}));
|
|
18328
18513
|
}
|
|
18329
18514
|
async applyInlineEgress(groupId, egressRules) {
|
|
@@ -19491,7 +19676,7 @@ var EC2Provider = class {
|
|
|
19491
19676
|
const raw = obj["CPUCredits"] ?? obj["CpuCredits"];
|
|
19492
19677
|
return typeof raw === "string" ? raw : void 0;
|
|
19493
19678
|
}
|
|
19494
|
-
buildIpPermission(properties, direction = "ingress") {
|
|
19679
|
+
buildIpPermission(properties, direction = "ingress", inline = false) {
|
|
19495
19680
|
const ipProtocol = properties["IpProtocol"] ?? "-1";
|
|
19496
19681
|
const fromPort = properties["FromPort"];
|
|
19497
19682
|
const toPort = properties["ToPort"];
|
|
@@ -19512,8 +19697,9 @@ var EC2Provider = class {
|
|
|
19512
19697
|
permission.Ipv6Ranges = [ipv6Range];
|
|
19513
19698
|
}
|
|
19514
19699
|
const peerGroupId = direction === "egress" ? properties["DestinationSecurityGroupId"] : properties["SourceSecurityGroupId"];
|
|
19515
|
-
|
|
19516
|
-
|
|
19700
|
+
const peerGroupName = inline && direction === "ingress" ? properties["SourceSecurityGroupName"] : void 0;
|
|
19701
|
+
if (peerGroupId || peerGroupName) {
|
|
19702
|
+
const groupPair = peerGroupId ? { GroupId: peerGroupId } : { GroupName: peerGroupName };
|
|
19517
19703
|
if (direction === "ingress") {
|
|
19518
19704
|
const peerOwnerId = properties["SourceSecurityGroupOwnerId"];
|
|
19519
19705
|
if (peerOwnerId) groupPair.UserId = peerOwnerId;
|
|
@@ -19534,6 +19720,7 @@ var EC2Provider = class {
|
|
|
19534
19720
|
const peerKey = direction === "egress" ? rule["DestinationSecurityGroupId"] : rule["SourceSecurityGroupId"];
|
|
19535
19721
|
const prefixKey = direction === "egress" ? rule["DestinationPrefixListId"] : rule["SourcePrefixListId"];
|
|
19536
19722
|
const peerOwner = direction === "ingress" ? rule["SourceSecurityGroupOwnerId"] : void 0;
|
|
19723
|
+
const peerName = direction === "ingress" ? rule["SourceSecurityGroupName"] : void 0;
|
|
19537
19724
|
return JSON.stringify({
|
|
19538
19725
|
p: sgProtocolKey(rule["IpProtocol"]),
|
|
19539
19726
|
f: rule["FromPort"] ?? null,
|
|
@@ -19541,6 +19728,7 @@ var EC2Provider = class {
|
|
|
19541
19728
|
c4: rule["CidrIp"] ?? null,
|
|
19542
19729
|
c6: rule["CidrIpv6"] ?? null,
|
|
19543
19730
|
peer: peerKey ?? null,
|
|
19731
|
+
peerName: peerKey ? null : peerName ?? null,
|
|
19544
19732
|
peerOwner: peerOwner ?? null,
|
|
19545
19733
|
pl: prefixKey ?? null,
|
|
19546
19734
|
d: rule["Description"] ?? null
|
|
@@ -19569,7 +19757,7 @@ var EC2Provider = class {
|
|
|
19569
19757
|
}));
|
|
19570
19758
|
else await this.ec2Client.send(new RevokeSecurityGroupIngressCommand({
|
|
19571
19759
|
GroupId: groupId,
|
|
19572
|
-
IpPermissions: [this.buildIpPermission(rule, "ingress")]
|
|
19760
|
+
IpPermissions: [this.buildIpPermission(rule, "ingress", true)]
|
|
19573
19761
|
}));
|
|
19574
19762
|
} catch (error) {
|
|
19575
19763
|
if (!this.isNotFoundError(error)) throw error;
|
|
@@ -19582,7 +19770,7 @@ var EC2Provider = class {
|
|
|
19582
19770
|
}));
|
|
19583
19771
|
else await this.ec2Client.send(new AuthorizeSecurityGroupIngressCommand({
|
|
19584
19772
|
GroupId: groupId,
|
|
19585
|
-
IpPermissions: [this.buildIpPermission(rule, "ingress")]
|
|
19773
|
+
IpPermissions: [this.buildIpPermission(rule, "ingress", true)]
|
|
19586
19774
|
}));
|
|
19587
19775
|
} catch (error) {
|
|
19588
19776
|
if (!(error instanceof Error && error.message.includes("already exists"))) throw error;
|
|
@@ -30866,6 +31054,18 @@ var DocDBSubnetGroupProvider = class {
|
|
|
30866
31054
|
function isZoneDisabledForMutationError(error) {
|
|
30867
31055
|
return error instanceof Error && error.message.includes("is marked disabled for mutation");
|
|
30868
31056
|
}
|
|
31057
|
+
function declaresAcceleratedRecovery(properties, acceptReadSideKey = false) {
|
|
31058
|
+
const features = properties["HostedZoneFeatures"];
|
|
31059
|
+
if (isTruthyCfnBoolean(features?.["EnableAcceleratedRecovery"])) return true;
|
|
31060
|
+
const legacyStatus = features?.["AcceleratedRecoveryStatus"];
|
|
31061
|
+
return acceptReadSideKey && features?.["EnableAcceleratedRecovery"] === void 0 && typeof legacyStatus === "string" && ACCELERATED_RECOVERY_ON_STATUSES.has(legacyStatus);
|
|
31062
|
+
}
|
|
31063
|
+
const ACCELERATED_RECOVERY_ON_STATUSES = /* @__PURE__ */ new Set([
|
|
31064
|
+
"ENABLED",
|
|
31065
|
+
"ENABLING",
|
|
31066
|
+
"ENABLING_HOSTED_ZONE_LOCKED",
|
|
31067
|
+
"DISABLE_FAILED"
|
|
31068
|
+
]);
|
|
30869
31069
|
var HostedZoneNameNotFoundError = class HostedZoneNameNotFoundError extends ProvisioningError {
|
|
30870
31070
|
constructor(message, resourceType, logicalId, physicalId, cause) {
|
|
30871
31071
|
super(message, resourceType, logicalId, physicalId, cause);
|
|
@@ -31081,26 +31281,29 @@ var Route53Provider = class {
|
|
|
31081
31281
|
}
|
|
31082
31282
|
await this.applyHostedZoneTags(zoneId, properties, logicalId, void 0, mask);
|
|
31083
31283
|
await this.applyQueryLoggingConfig(zoneId, properties, logicalId);
|
|
31084
|
-
if (properties
|
|
31085
|
-
await this.getClient().send(new UpdateHostedZoneFeaturesCommand({
|
|
31086
|
-
HostedZoneId: zoneId,
|
|
31087
|
-
EnableAcceleratedRecovery: true
|
|
31088
|
-
}));
|
|
31089
|
-
} catch (uhfError) {
|
|
31090
|
-
this.logger.error(`UpdateHostedZoneFeatures failed for ${zoneId} after CreateHostedZone — rolling back the hosted zone to keep deploy retry idempotent`);
|
|
31284
|
+
if (declaresAcceleratedRecovery(properties)) {
|
|
31091
31285
|
try {
|
|
31092
|
-
await this.
|
|
31093
|
-
|
|
31094
|
-
|
|
31095
|
-
|
|
31096
|
-
} catch (
|
|
31097
|
-
|
|
31098
|
-
|
|
31099
|
-
|
|
31286
|
+
await this.getClient().send(new UpdateHostedZoneFeaturesCommand({
|
|
31287
|
+
HostedZoneId: zoneId,
|
|
31288
|
+
EnableAcceleratedRecovery: true
|
|
31289
|
+
}));
|
|
31290
|
+
} catch (uhfError) {
|
|
31291
|
+
this.logger.error(`UpdateHostedZoneFeatures failed for ${zoneId} after CreateHostedZone — rolling back the hosted zone to keep deploy retry idempotent`);
|
|
31292
|
+
try {
|
|
31293
|
+
await this.deleteQueryLoggingConfigForZone(zoneId, logicalId);
|
|
31294
|
+
await this.getClient().send(new DeleteHostedZoneCommand({ Id: zoneId }));
|
|
31295
|
+
zoneRolledBack = true;
|
|
31296
|
+
callerReferenceToken.release();
|
|
31297
|
+
} catch (deleteError) {
|
|
31298
|
+
const head = `Best-effort rollback DeleteHostedZone for ${zoneId} also failed: `;
|
|
31299
|
+
const m = maskerOrIdentity(mask);
|
|
31300
|
+
this.logger.warn(m(`${head}${this.warnFailureText(head, deleteError, mask)} The operator may need to clean up the orphan zone.`));
|
|
31301
|
+
}
|
|
31302
|
+
const cause = uhfError instanceof Error ? uhfError : void 0;
|
|
31303
|
+
markAuxiliaryFailure(uhfError, logicalId);
|
|
31304
|
+
throw this.wrapCaughtError(mask, uhfError, (text) => new ProvisioningError(`Failed to enable Accelerated Recovery on hosted zone ${logicalId} (${zoneId}): ${text}`, resourceType, logicalId, zoneId, cause));
|
|
31100
31305
|
}
|
|
31101
|
-
|
|
31102
|
-
markAuxiliaryFailure(uhfError, logicalId);
|
|
31103
|
-
throw this.wrapCaughtError(mask, uhfError, (text) => new ProvisioningError(`Failed to enable Accelerated Recovery on hosted zone ${logicalId} (${zoneId}): ${text}`, resourceType, logicalId, zoneId, cause));
|
|
31306
|
+
await this.waitForAcceleratedRecoveryFeatureSettled(zoneId, logicalId, resourceType, true, true);
|
|
31104
31307
|
}
|
|
31105
31308
|
const nameServers = response.DelegationSet?.NameServers ?? [];
|
|
31106
31309
|
this.logger.debug(`Successfully created hosted zone ${logicalId}: ${zoneId}`);
|
|
@@ -31178,12 +31381,15 @@ var Route53Provider = class {
|
|
|
31178
31381
|
await this.applyHostedZoneTags(physicalId, properties, logicalId, previousProperties, mask);
|
|
31179
31382
|
await this.applyQueryLoggingConfig(physicalId, properties, logicalId, previousProperties);
|
|
31180
31383
|
await this.syncVPCAssociations(physicalId, properties, logicalId);
|
|
31181
|
-
const prevEnabled = previousProperties
|
|
31182
|
-
const nextEnabled = properties
|
|
31183
|
-
if (prevEnabled !== nextEnabled)
|
|
31184
|
-
|
|
31185
|
-
|
|
31186
|
-
|
|
31384
|
+
const prevEnabled = declaresAcceleratedRecovery(previousProperties, true);
|
|
31385
|
+
const nextEnabled = declaresAcceleratedRecovery(properties, context?.desiredFromAwsReadback === true);
|
|
31386
|
+
if (prevEnabled !== nextEnabled) {
|
|
31387
|
+
await this.getClient().send(new UpdateHostedZoneFeaturesCommand({
|
|
31388
|
+
HostedZoneId: physicalId,
|
|
31389
|
+
EnableAcceleratedRecovery: nextEnabled
|
|
31390
|
+
}));
|
|
31391
|
+
await this.waitForAcceleratedRecoveryFeatureSettled(physicalId, logicalId, resourceType, nextEnabled);
|
|
31392
|
+
}
|
|
31187
31393
|
const nameServers = (await this.getClient().send(new GetHostedZoneCommand({ Id: physicalId }))).DelegationSet?.NameServers ?? [];
|
|
31188
31394
|
this.logger.debug(`Successfully updated hosted zone ${logicalId}`);
|
|
31189
31395
|
if (context?.desiredFromAwsReadback !== true && declaresNoVpcs(properties["VPCs"]) && Array.isArray(previousProperties["VPCs"]) && previousProperties["VPCs"].length > 0) this.logger.warn(context?.replayingState ? safeMsg`${logicalId} (AWS::Route53::HostedZone): VPCs is absent from the state being restored, so the rollback leaves the zone's VPC associations in place. ${VPCS_KEPT_ON_REMOVAL_NOTE}` : safeMsg`${logicalId} (AWS::Route53::HostedZone): VPCs was removed from the template, and the zone keeps its current VPC associations, as CloudFormation leaves them. ${VPCS_KEPT_ON_REMOVAL_NOTE}`);
|
|
@@ -31438,25 +31644,43 @@ var Route53Provider = class {
|
|
|
31438
31644
|
throw this.wrapDeleteError(context?.maskSecrets, error, (text) => new ProvisioningError(`Failed to delete record set ${logicalId}: ${text}`, resourceType, logicalId, physicalId, cause));
|
|
31439
31645
|
}
|
|
31440
31646
|
}
|
|
31441
|
-
async
|
|
31647
|
+
async waitForAcceleratedRecoveryFeatureSettled(zoneId, logicalId, resourceType, enabled, freshZone = false) {
|
|
31648
|
+
const verb = enabled ? "enable" : "disable";
|
|
31649
|
+
await this.waitForAcceleratedRecoveryMutable(zoneId, logicalId, resourceType, {
|
|
31650
|
+
blocked: `the hosted zone ${logicalId} can be deployed`,
|
|
31651
|
+
retry: `after the ${verb} of Accelerated Recovery (hosted zone ${logicalId}); re-run the deploy once the transition settles`,
|
|
31652
|
+
settledAt: enabled ? "ENABLED" : "DISABLED",
|
|
31653
|
+
freshZone
|
|
31654
|
+
});
|
|
31655
|
+
}
|
|
31656
|
+
async waitForAcceleratedRecoveryMutable(zoneId, logicalId, resourceType, purpose = {
|
|
31657
|
+
blocked: `the record set ${logicalId} can be deleted`,
|
|
31658
|
+
retry: `(record set ${logicalId}); re-run the destroy once the transition settles`
|
|
31659
|
+
}) {
|
|
31442
31660
|
const client = this.getClient();
|
|
31443
31661
|
const parsedInterval = Number.parseInt(process.env["CDKD_R53_ACCEL_RECOVERY_POLL_INTERVAL_MS"] ?? "15000", 10);
|
|
31444
31662
|
const pollIntervalMs = Number.isFinite(parsedInterval) && parsedInterval > 0 ? parsedInterval : 15e3;
|
|
31445
31663
|
const parsedTimeout = Number.parseInt(process.env["CDKD_R53_ACCEL_RECOVERY_POLL_TIMEOUT_MS"] ?? "600000", 10);
|
|
31446
31664
|
const timeoutMs = Number.isFinite(parsedTimeout) && parsedTimeout > 0 ? parsedTimeout : 6e5;
|
|
31447
31665
|
const deadline = Date.now() + timeoutMs;
|
|
31448
|
-
const TERMINAL_FAILED =
|
|
31449
|
-
const MUTABLE =
|
|
31666
|
+
const TERMINAL_FAILED = new Set(purpose.settledAt === "ENABLED" ? ["ENABLE_FAILED"] : purpose.settledAt === "DISABLED" ? ["DISABLE_FAILED"] : ["ENABLE_FAILED", "DISABLE_FAILED"]);
|
|
31667
|
+
const MUTABLE = new Set(purpose.settledAt !== void 0 ? [purpose.settledAt] : ["ENABLED", "DISABLED"]);
|
|
31668
|
+
let sawTransition = purpose.settledAt === void 0 || purpose.freshZone === true;
|
|
31669
|
+
let lastStatus;
|
|
31450
31670
|
while (Date.now() < deadline) {
|
|
31451
31671
|
let status;
|
|
31452
31672
|
try {
|
|
31453
31673
|
status = (await client.send(new GetHostedZoneCommand({ Id: zoneId }))).HostedZone?.Features?.AcceleratedRecoveryStatus;
|
|
31454
31674
|
} catch (err) {
|
|
31455
|
-
if (err instanceof Error && err.name === "NoSuchHostedZone") return;
|
|
31675
|
+
if (err instanceof Error && err.name === "NoSuchHostedZone" && purpose.settledAt === void 0) return;
|
|
31456
31676
|
throw err;
|
|
31457
31677
|
}
|
|
31458
|
-
if (status === void 0
|
|
31459
|
-
|
|
31678
|
+
if (status === void 0) {
|
|
31679
|
+
if (purpose.settledAt !== "ENABLED") return;
|
|
31680
|
+
} else if (MUTABLE.has(status)) return;
|
|
31681
|
+
lastStatus = status;
|
|
31682
|
+
if (status?.includes("ING") === true) sawTransition = true;
|
|
31683
|
+
if (status !== void 0 && sawTransition && TERMINAL_FAILED.has(status)) throw new ProvisioningError(`Cannot mutate hosted zone ${zoneId}: AcceleratedRecoveryStatus is '${status}' — operator must resolve before ${purpose.blocked}`, resourceType, logicalId, zoneId);
|
|
31460
31684
|
this.logger.debug(`Polling AcceleratedRecoveryStatus for ${zoneId}: ${status} (waiting for a mutable state, will re-poll in ~${pollIntervalMs}ms)`);
|
|
31461
31685
|
const sliceEnd = Math.min(Date.now() + pollIntervalMs, deadline);
|
|
31462
31686
|
while (Date.now() < sliceEnd) {
|
|
@@ -31465,7 +31689,7 @@ var Route53Provider = class {
|
|
|
31465
31689
|
await new Promise((resolve) => setTimeout(resolve, tick));
|
|
31466
31690
|
}
|
|
31467
31691
|
}
|
|
31468
|
-
throw new ProvisioningError(`Timed out after ${timeoutMs}ms waiting for AcceleratedRecoveryStatus to reach a mutable state on hosted zone ${zoneId}
|
|
31692
|
+
throw new ProvisioningError(`Timed out after ${timeoutMs}ms waiting for AcceleratedRecoveryStatus to reach a mutable state on hosted zone ${zoneId} ${purpose.retry}${purpose.settledAt !== void 0 ? ` (last status: ${lastStatus ?? "none"})` : ""}`, resourceType, logicalId, zoneId);
|
|
31469
31693
|
}
|
|
31470
31694
|
buildResourceRecordSet(properties) {
|
|
31471
31695
|
const name = properties["Name"];
|
|
@@ -31773,7 +31997,8 @@ var Route53Provider = class {
|
|
|
31773
31997
|
const bare = resp.DelegationSet.Id.replace(/^\/delegationset\//, "");
|
|
31774
31998
|
result["DelegationSetId"] = properties?.["DelegationSetId"] === `/delegationset/${bare}` ? `/delegationset/${bare}` : bare;
|
|
31775
31999
|
}
|
|
31776
|
-
|
|
32000
|
+
const acceleratedRecoveryStatus = resp.HostedZone.Features?.AcceleratedRecoveryStatus;
|
|
32001
|
+
if (acceleratedRecoveryStatus !== void 0) result["HostedZoneFeatures"] = { EnableAcceleratedRecovery: ACCELERATED_RECOVERY_ON_STATUSES.has(acceleratedRecoveryStatus) };
|
|
31777
32002
|
if (resp.HostedZone.Config?.PrivateZone === true) result["VPCs"] = (resp.VPCs ?? []).map((v) => {
|
|
31778
32003
|
const out = {};
|
|
31779
32004
|
if (v.VPCId !== void 0) out["VPCId"] = v.VPCId;
|
|
@@ -33893,11 +34118,7 @@ var ElastiCacheProvider = class {
|
|
|
33893
34118
|
if (templateLowered && desiredCount !== void 0 && desiredCount < liveNodes.length) {
|
|
33894
34119
|
if (liveNodes.length !== previousCount) throw new ProvisioningError(safeMsg`Cannot update CacheCluster ${logicalId}: the template lowers NumCacheNodes from ${String(previousCount)} ` + safeMsg`to ${String(desiredCount)}, but the cluster has ${String(liveNodes.length)} nodes, so ` + "the removal would delete nodes the template change does not account for. Deploy NumCacheNodes set to the live count first, then lower it.", resourceType, logicalId, physicalId);
|
|
33895
34120
|
const plan = nodesToRemove(liveNodes, desiredCount, zones);
|
|
33896
|
-
if (plan === void 0) {
|
|
33897
|
-
const liveZones = liveNodes.map((n) => n.zone);
|
|
33898
|
-
const disjoint = zones !== void 0 && !zones.some((z) => liveZones.includes(z));
|
|
33899
|
-
throw new ProvisioningError(safeMsg`Cannot update CacheCluster ${logicalId}: lowering NumCacheNodes to ${String(desiredCount)} ` + "with this PreferredAvailabilityZones list needs a node removed and a node added in a zone no live node occupies, in one update, which ModifyCacheCluster cannot do. " + (disjoint ? `CloudFormation replaces the cluster for a move to disjoint zones; cdkd does not yet (issue #5458). ` : "") + `Replace the cluster (for example by changing its logical ID), or list only zones the kept nodes occupy.`, resourceType, logicalId, physicalId);
|
|
33900
|
-
}
|
|
34121
|
+
if (plan === void 0) throw new ProvisioningError(safeMsg`Cannot update CacheCluster ${logicalId}: lowering NumCacheNodes to ${String(desiredCount)} ` + "with this PreferredAvailabilityZones list needs a node removed and a node added in a zone no live node occupies, in one update, which ModifyCacheCluster cannot do. Replace the cluster (for example by changing its logical ID), or list only zones the kept nodes occupy.", resourceType, logicalId, physicalId);
|
|
33901
34122
|
removeIds = plan;
|
|
33902
34123
|
this.logger.info(safeMsg`CacheCluster ${logicalId}: NumCacheNodes ${String(previousProperties["NumCacheNodes"])} -> ${String(desiredCount)}, removing cache nodes ${removeIds.join(", ")}`);
|
|
33903
34124
|
}
|
|
@@ -38237,15 +38458,20 @@ function desiredGlueTags(raw, resourceType, logicalId, physicalId) {
|
|
|
38237
38458
|
const tags = refuseMalformedDesiredTags(tagMapAsList(raw), resourceType, logicalId, physicalId, "Tags", GLUE_TAGS_WHAT);
|
|
38238
38459
|
return tags.length > 0 ? Object.fromEntries(tags.map((t) => [t.Key, t.Value])) : void 0;
|
|
38239
38460
|
}
|
|
38240
|
-
async function applyGlueTagDiff(client, resourceArn, recorded, desired, resourceType, logicalId, warn
|
|
38461
|
+
async function applyGlueTagDiff(client, resourceArn, recorded, desired, resourceType, logicalId, warn, unsettled = {
|
|
38462
|
+
forceUpsert: false,
|
|
38463
|
+
beforeWrite: () => void 0
|
|
38464
|
+
}) {
|
|
38241
38465
|
const plan = planTagDiff(tagMapAsList(recorded), tagMapAsList(desired));
|
|
38242
38466
|
const warning = tagPlanWarning(plan, resourceType, logicalId);
|
|
38243
38467
|
if (warning !== void 0) warn(warning);
|
|
38244
|
-
|
|
38468
|
+
const toSet = unsettled.forceUpsert ? planTagDiff([], tagMapAsList(desired)).set : plan.set;
|
|
38469
|
+
if (toSet.size === 0 && plan.remove.length === 0) return;
|
|
38470
|
+
unsettled.beforeWrite();
|
|
38245
38471
|
const arn = await resourceArn();
|
|
38246
|
-
if (
|
|
38472
|
+
if (toSet.size > 0) await client.send(new TagResourceCommand$19({
|
|
38247
38473
|
ResourceArn: arn,
|
|
38248
|
-
TagsToAdd: Object.fromEntries(
|
|
38474
|
+
TagsToAdd: Object.fromEntries(toSet)
|
|
38249
38475
|
}));
|
|
38250
38476
|
if (plan.remove.length > 0) await client.send(new UntagResourceCommand$20({
|
|
38251
38477
|
ResourceArn: arn,
|
|
@@ -38280,6 +38506,28 @@ const crawlerLeftInPlaceWarning = (logicalId, names, caller) => {
|
|
|
38280
38506
|
const cfnKeeps = names.includes("LineageConfiguration") ? "" : `, as CloudFormation leaves ${one ? "it" : "them"}`;
|
|
38281
38507
|
return caller === "rollback" ? safeMsg`${logicalId} (AWS::Glue::Crawler): ${subject} ${names.join(", ")} ${one ? "is" : "are"} absent from the state being restored; UpdateCrawler keeps a setting it is not sent, so the rollback leaves the value the failed deploy applied in place.` : safeMsg`${logicalId} (AWS::Glue::Crawler): ${subject} ${names.join(", ")} ${one ? "was" : "were"} removed from the template and ${one ? "keeps its" : "keep their"} current AWS value${cfnKeeps}; UpdateCrawler keeps a setting it is not sent. Declare the intended value explicitly to change it.`;
|
|
38282
38508
|
};
|
|
38509
|
+
const CRAWLER_UPDATE_KEYS = [
|
|
38510
|
+
"Role",
|
|
38511
|
+
"Targets",
|
|
38512
|
+
"Classifiers",
|
|
38513
|
+
"Configuration",
|
|
38514
|
+
"CrawlerSecurityConfiguration",
|
|
38515
|
+
"DatabaseName",
|
|
38516
|
+
"Description",
|
|
38517
|
+
"LakeFormationConfiguration",
|
|
38518
|
+
"LineageConfiguration",
|
|
38519
|
+
"RecrawlPolicy",
|
|
38520
|
+
"Schedule",
|
|
38521
|
+
"SchemaChangePolicy",
|
|
38522
|
+
"TablePrefix"
|
|
38523
|
+
];
|
|
38524
|
+
const TRIGGER_UPDATE_KEYS = [
|
|
38525
|
+
"Description",
|
|
38526
|
+
"Schedule",
|
|
38527
|
+
"Actions",
|
|
38528
|
+
"Predicate",
|
|
38529
|
+
"EventBatchingCondition"
|
|
38530
|
+
];
|
|
38283
38531
|
var GlueCrawlerProvider = class {
|
|
38284
38532
|
client;
|
|
38285
38533
|
createClient;
|
|
@@ -38362,6 +38610,7 @@ var GlueCrawlerProvider = class {
|
|
|
38362
38610
|
const { value: v } = log;
|
|
38363
38611
|
log.debug(`Updating Glue Crawler ${logicalId}: ${v(physicalId)}`);
|
|
38364
38612
|
desiredGlueTags(properties["Tags"], resourceType, logicalId, physicalId);
|
|
38613
|
+
const markUnsettled = (key) => context?.markUnsettled?.(key);
|
|
38365
38614
|
try {
|
|
38366
38615
|
const updateInput = {
|
|
38367
38616
|
Name: physicalId,
|
|
@@ -38369,6 +38618,7 @@ var GlueCrawlerProvider = class {
|
|
|
38369
38618
|
...properties["Targets"] !== void 0 && { Targets: toSdkCrawlerTargets(properties["Targets"]) },
|
|
38370
38619
|
...buildCrawlerCommonFields(properties)
|
|
38371
38620
|
};
|
|
38621
|
+
for (const key of CRAWLER_UPDATE_KEYS) if (JSON.stringify(properties[key]) !== JSON.stringify(previousProperties[key])) markUnsettled(key);
|
|
38372
38622
|
try {
|
|
38373
38623
|
await this.getClient().send(new UpdateCrawlerCommand(updateInput));
|
|
38374
38624
|
} catch (err) {
|
|
@@ -38378,7 +38628,10 @@ var GlueCrawlerProvider = class {
|
|
|
38378
38628
|
await this.getClient().send(new UpdateCrawlerCommand(updateInput));
|
|
38379
38629
|
} else throw err;
|
|
38380
38630
|
}
|
|
38381
|
-
await applyGlueTagDiff(this.getClient(), () => this.resourceArn(physicalId), previousProperties["Tags"], properties["Tags"], resourceType, logicalId, log.warn
|
|
38631
|
+
await applyGlueTagDiff(this.getClient(), () => this.resourceArn(physicalId), previousProperties["Tags"], properties["Tags"], resourceType, logicalId, log.warn, {
|
|
38632
|
+
forceUpsert: context?.unsettledProperties?.has("Tags") === true,
|
|
38633
|
+
beforeWrite: () => markUnsettled("Tags")
|
|
38634
|
+
});
|
|
38382
38635
|
if (!context?.desiredFromAwsReadback) {
|
|
38383
38636
|
const removed = context?.removedProperties;
|
|
38384
38637
|
const leftInPlace = [];
|
|
@@ -38854,6 +39107,7 @@ var GlueTriggerProvider = class {
|
|
|
38854
39107
|
const { value: v } = log;
|
|
38855
39108
|
log.debug(`Updating Glue Trigger ${logicalId}: ${v(physicalId)}`);
|
|
38856
39109
|
desiredGlueTags(properties["Tags"], resourceType, logicalId, physicalId);
|
|
39110
|
+
const markUnsettled = (key) => context?.markUnsettled?.(key);
|
|
38857
39111
|
try {
|
|
38858
39112
|
let restart = false;
|
|
38859
39113
|
try {
|
|
@@ -38873,6 +39127,7 @@ var GlueTriggerProvider = class {
|
|
|
38873
39127
|
...properties["EventBatchingCondition"] !== void 0 && { EventBatchingCondition: properties["EventBatchingCondition"] }
|
|
38874
39128
|
};
|
|
38875
39129
|
let updateError;
|
|
39130
|
+
for (const key of TRIGGER_UPDATE_KEYS) if (JSON.stringify(properties[key]) !== JSON.stringify(previousProperties[key])) markUnsettled(key);
|
|
38876
39131
|
try {
|
|
38877
39132
|
await this.getClient().send(new UpdateTriggerCommand({
|
|
38878
39133
|
Name: physicalId,
|
|
@@ -38890,7 +39145,10 @@ var GlueTriggerProvider = class {
|
|
|
38890
39145
|
if (restartFailure.redacted) log.debug(`Failed to re-activate Glue Trigger ${v(physicalId)} after a failed update: ${restartFailure.detail}`);
|
|
38891
39146
|
}
|
|
38892
39147
|
if (updateError !== void 0) throw updateError;
|
|
38893
|
-
await applyGlueTagDiff(this.getClient(), () => this.resourceArn(physicalId), previousProperties["Tags"], properties["Tags"], resourceType, logicalId, log.warn
|
|
39148
|
+
await applyGlueTagDiff(this.getClient(), () => this.resourceArn(physicalId), previousProperties["Tags"], properties["Tags"], resourceType, logicalId, log.warn, {
|
|
39149
|
+
forceUpsert: context?.unsettledProperties?.has("Tags") === true,
|
|
39150
|
+
beforeWrite: () => markUnsettled("Tags")
|
|
39151
|
+
});
|
|
38894
39152
|
return {
|
|
38895
39153
|
physicalId,
|
|
38896
39154
|
wasReplaced: false
|
|
@@ -38900,6 +39158,14 @@ var GlueTriggerProvider = class {
|
|
|
38900
39158
|
throw this.wrapMaskedError(log.mask, error, (text) => new ProvisioningError(`Failed to update Glue Trigger ${logicalId}: ${text}`, resourceType, logicalId, physicalId, cause));
|
|
38901
39159
|
}
|
|
38902
39160
|
}
|
|
39161
|
+
async unsettledInTransition(physicalId, _logicalId, _resourceType, names) {
|
|
39162
|
+
try {
|
|
39163
|
+
const state = (await this.getClient().send(new GetTriggerCommand({ Name: physicalId }))).Trigger?.State;
|
|
39164
|
+
return state === "ACTIVATING" || state === "DEACTIVATING" || state === "CREATING" || state === "UPDATING" ? new Set([...names].filter((name) => name !== "Tags")) : /* @__PURE__ */ new Set();
|
|
39165
|
+
} catch {
|
|
39166
|
+
return names;
|
|
39167
|
+
}
|
|
39168
|
+
}
|
|
38903
39169
|
async waitForTriggerDeactivated(physicalId) {
|
|
38904
39170
|
for (let attempt = 0; attempt < TRIGGER_DEACTIVATE_MAX_ATTEMPTS; attempt++) {
|
|
38905
39171
|
try {
|
|
@@ -40655,6 +40921,7 @@ var KinesisStreamProvider = class {
|
|
|
40655
40921
|
const desiredRetention = readRetentionHours(properties["RetentionPeriodHours"], mask);
|
|
40656
40922
|
if (desiredRetention.kind === "unusable" && context?.replayingState !== true) throw new ProvisioningError(desiredRetention.reason, resourceType, logicalId, physicalId);
|
|
40657
40923
|
if (desiredRetention.kind === "unusable") warn(`${desiredRetention.reason}. Replaying a state record, so the retention period of ${physicalId} is left as it is rather than refusing the restore`);
|
|
40924
|
+
const markUnsettled = (key) => context?.markUnsettled?.(key);
|
|
40658
40925
|
const previousRetention = readRetentionHours(previousProperties["RetentionPeriodHours"], mask);
|
|
40659
40926
|
try {
|
|
40660
40927
|
const streamModeDetails = properties["StreamModeDetails"];
|
|
@@ -40664,6 +40931,7 @@ var KinesisStreamProvider = class {
|
|
|
40664
40931
|
if (modeChanged) {
|
|
40665
40932
|
const streamArn = await this.resolveStreamArn(physicalId);
|
|
40666
40933
|
this.logger.debug(`Switching stream mode for ${physicalId}: from ${oldStreamMode} to ${streamMode}`);
|
|
40934
|
+
markUnsettled("StreamModeDetails");
|
|
40667
40935
|
await this.getClient().send(new UpdateStreamModeCommand({
|
|
40668
40936
|
StreamARN: streamArn,
|
|
40669
40937
|
StreamModeDetails: { StreamMode: streamMode }
|
|
@@ -40672,9 +40940,10 @@ var KinesisStreamProvider = class {
|
|
|
40672
40940
|
}
|
|
40673
40941
|
if (streamMode === "PROVISIONED") {
|
|
40674
40942
|
const newShardCount = Number(properties["ShardCount"] ?? 1);
|
|
40675
|
-
const oldShardCount = modeChanged ? await this.getOpenShardCount(physicalId) : Number(previousProperties["ShardCount"] ?? 1);
|
|
40943
|
+
const oldShardCount = modeChanged || context?.unsettledProperties?.has("StreamModeDetails") === true ? await this.getOpenShardCount(physicalId) : Number(previousProperties["ShardCount"] ?? 1);
|
|
40676
40944
|
if (newShardCount !== oldShardCount) {
|
|
40677
40945
|
this.logger.debug(`Updating shard count for ${physicalId}: from ${oldShardCount} to ${newShardCount}`);
|
|
40946
|
+
markUnsettled("ShardCount");
|
|
40678
40947
|
await this.getClient().send(new UpdateShardCountCommand({
|
|
40679
40948
|
StreamName: physicalId,
|
|
40680
40949
|
TargetShardCount: newShardCount,
|
|
@@ -40687,6 +40956,7 @@ var KinesisStreamProvider = class {
|
|
|
40687
40956
|
const effectiveOldRetention = previousRetention.kind === "usable" ? previousRetention.hours ?? 24 : 24;
|
|
40688
40957
|
if (desiredRetention.kind !== "unusable" && effectiveNewRetention !== effectiveOldRetention) {
|
|
40689
40958
|
this.logger.debug(`Updating retention period for ${physicalId}: from ${effectiveOldRetention} to ${effectiveNewRetention}`);
|
|
40959
|
+
markUnsettled("RetentionPeriodHours");
|
|
40690
40960
|
if (effectiveNewRetention > effectiveOldRetention) await this.getClient().send(new IncreaseStreamRetentionPeriodCommand({
|
|
40691
40961
|
StreamName: physicalId,
|
|
40692
40962
|
RetentionPeriodHours: effectiveNewRetention
|
|
@@ -40697,7 +40967,10 @@ var KinesisStreamProvider = class {
|
|
|
40697
40967
|
}));
|
|
40698
40968
|
await this.waitForStreamActive(physicalId);
|
|
40699
40969
|
}
|
|
40700
|
-
await this.applyTagDiff(physicalId, resourceType, logicalId, previousProperties["Tags"], properties["Tags"]
|
|
40970
|
+
await this.applyTagDiff(physicalId, resourceType, logicalId, previousProperties["Tags"], properties["Tags"], {
|
|
40971
|
+
forceUpsert: context?.unsettledProperties?.has("Tags") === true,
|
|
40972
|
+
beforeWrite: () => markUnsettled("Tags")
|
|
40973
|
+
});
|
|
40701
40974
|
const newEncryption = properties["StreamEncryption"];
|
|
40702
40975
|
const oldEncryption = previousProperties["StreamEncryption"];
|
|
40703
40976
|
const oldIsKms = isKmsEncryption(oldEncryption);
|
|
@@ -40705,6 +40978,7 @@ var KinesisStreamProvider = class {
|
|
|
40705
40978
|
const oldKeyId = oldIsKms ? oldEncryption["KeyId"] : void 0;
|
|
40706
40979
|
const newKeyId = newIsKms ? newEncryption["KeyId"] : void 0;
|
|
40707
40980
|
if (oldIsKms !== newIsKms || oldIsKms && newIsKms && oldKeyId !== newKeyId) {
|
|
40981
|
+
markUnsettled("StreamEncryption");
|
|
40708
40982
|
if (oldIsKms) {
|
|
40709
40983
|
await this.getClient().send(new StopStreamEncryptionCommand({
|
|
40710
40984
|
StreamName: physicalId,
|
|
@@ -40728,13 +41002,14 @@ var KinesisStreamProvider = class {
|
|
|
40728
41002
|
const recordedMaxRecordSize = comparableRecordSize(previousProperties["MaxRecordSizeInKiB"], mask);
|
|
40729
41003
|
if (newMaxRecordSize !== void 0 && newMaxRecordSize !== (recordedMaxRecordSize ?? DEFAULT_MAX_RECORD_SIZE_KIB)) {
|
|
40730
41004
|
this.logger.debug(`Updating max record size for ${physicalId}: from ${recordedMaxRecordSize ?? "no value"} to ${newMaxRecordSize}`);
|
|
41005
|
+
markUnsettled("MaxRecordSizeInKiB");
|
|
40731
41006
|
await this.getClient().send(new UpdateMaxRecordSizeCommand({
|
|
40732
41007
|
StreamARN: await this.resolveStreamArn(physicalId),
|
|
40733
41008
|
MaxRecordSizeInKiB: newMaxRecordSize
|
|
40734
41009
|
}));
|
|
40735
41010
|
await this.waitForStreamActive(physicalId);
|
|
40736
41011
|
}
|
|
40737
|
-
await this.reconcileDistributionStrategy(physicalId, streamMode, properties, previousProperties, mask, warn);
|
|
41012
|
+
await this.reconcileDistributionStrategy(physicalId, streamMode, properties, previousProperties, mask, warn, markUnsettled);
|
|
40738
41013
|
const desiredRead = readShardLevelMetrics(properties["DesiredShardLevelMetrics"], mask);
|
|
40739
41014
|
let desiredMetrics;
|
|
40740
41015
|
if (desiredRead.kind === "unusable") warn(`${desiredRead.reason}. Leaving the shard-level metrics on ${physicalId} unchanged rather than disabling the live ones; the same value is REFUSED on a template-path create`);
|
|
@@ -40743,7 +41018,9 @@ var KinesisStreamProvider = class {
|
|
|
40743
41018
|
const desiredSet = desiredRead.kind === "usable" ? desiredRead.metrics : [];
|
|
40744
41019
|
const previousSet = previousMetricNames(previousProperties["DesiredShardLevelMetrics"]);
|
|
40745
41020
|
const toDisable = previousSet.filter((m) => !desiredSet.includes(m));
|
|
41021
|
+
if (context?.unsettledProperties?.has("DesiredShardLevelMetrics") === true) await this.warnUndeclaredLiveMetrics(physicalId, [...previousSet, ...desiredSet], warn, mask);
|
|
40746
41022
|
const toEnable = desiredSet.filter((m) => !previousSet.includes(m));
|
|
41023
|
+
if (toDisable.length > 0 || toEnable.length > 0) markUnsettled("DesiredShardLevelMetrics");
|
|
40747
41024
|
if (toDisable.length > 0) {
|
|
40748
41025
|
this.logger.debug(`Disabling ${toDisable.length} shard-level metric(s) on ${physicalId}`);
|
|
40749
41026
|
await this.getClient().send(new DisableEnhancedMonitoringCommand({
|
|
@@ -40855,7 +41132,7 @@ var KinesisStreamProvider = class {
|
|
|
40855
41132
|
throw error;
|
|
40856
41133
|
}
|
|
40857
41134
|
}
|
|
40858
|
-
async reconcileDistributionStrategy(physicalId, streamMode, properties, previousProperties, mask, warn) {
|
|
41135
|
+
async reconcileDistributionStrategy(physicalId, streamMode, properties, previousProperties, mask, warn, markUnsettled) {
|
|
40859
41136
|
const desired = readDistributionStrategy(properties["RecordDistributionStrategy"], mask);
|
|
40860
41137
|
if (desired.kind === "unusable") {
|
|
40861
41138
|
warn(`${desired.reason}. Leaving the record distribution strategy on ${physicalId} unchanged; the same value is REFUSED on a template-path create`);
|
|
@@ -40873,6 +41150,7 @@ var KinesisStreamProvider = class {
|
|
|
40873
41150
|
target = DEFAULT_RECORD_DISTRIBUTION_STRATEGY;
|
|
40874
41151
|
}
|
|
40875
41152
|
this.logger.debug(mask(safeMsg`Updating record distribution strategy for ${physicalId}: from ${recorded ?? "no value"} to ${target}`));
|
|
41153
|
+
markUnsettled("RecordDistributionStrategy");
|
|
40876
41154
|
await this.getClient().send(new UpdateStreamRecordDistributionStrategyCommand({
|
|
40877
41155
|
StreamARN: await this.resolveStreamArn(physicalId),
|
|
40878
41156
|
RecordDistributionStrategy: target
|
|
@@ -40901,12 +41179,16 @@ var KinesisStreamProvider = class {
|
|
|
40901
41179
|
if (resourceType !== "AWS::Kinesis::Stream") return [];
|
|
40902
41180
|
return ["DesiredShardLevelMetrics"];
|
|
40903
41181
|
}
|
|
40904
|
-
async applyTagDiff(streamName, resourceType, logicalId, oldTagsRaw, newTagsRaw
|
|
41182
|
+
async applyTagDiff(streamName, resourceType, logicalId, oldTagsRaw, newTagsRaw, unsettled = {
|
|
41183
|
+
forceUpsert: false,
|
|
41184
|
+
beforeWrite: () => void 0
|
|
41185
|
+
}) {
|
|
40905
41186
|
const plan = planTagDiff(oldTagsRaw, newTagsRaw);
|
|
40906
41187
|
const tagWarning = tagPlanWarning(plan, resourceType, logicalId);
|
|
40907
41188
|
if (tagWarning !== void 0) this.logger.warn(tagWarning);
|
|
40908
|
-
const tagsToAdd = Object.fromEntries(plan.set);
|
|
41189
|
+
const tagsToAdd = Object.fromEntries(unsettled.forceUpsert ? planTagDiff(void 0, newTagsRaw).set : plan.set);
|
|
40909
41190
|
const tagsToRemove = plan.remove;
|
|
41191
|
+
if (tagsToRemove.length > 0 || Object.keys(tagsToAdd).length > 0) unsettled.beforeWrite();
|
|
40910
41192
|
if (tagsToRemove.length > 0) {
|
|
40911
41193
|
await this.getClient().send(new RemoveTagsFromStreamCommand({
|
|
40912
41194
|
StreamName: streamName,
|
|
@@ -40922,6 +41204,46 @@ var KinesisStreamProvider = class {
|
|
|
40922
41204
|
this.logger.debug(`Added/updated ${Object.keys(tagsToAdd).length} tag(s) on Kinesis stream ${streamName}`);
|
|
40923
41205
|
}
|
|
40924
41206
|
}
|
|
41207
|
+
async warnUndeclaredLiveMetrics(physicalId, named, warn, mask) {
|
|
41208
|
+
let live;
|
|
41209
|
+
try {
|
|
41210
|
+
live = ((await this.getClient().send(new DescribeStreamSummaryCommand({ StreamName: physicalId }))).StreamDescriptionSummary?.EnhancedMonitoring ?? []).flatMap((entry) => entry.ShardLevelMetrics ?? []);
|
|
41211
|
+
} catch {
|
|
41212
|
+
return;
|
|
41213
|
+
}
|
|
41214
|
+
const expandedLive = expandShardLevelMetrics(live);
|
|
41215
|
+
const undeclared = (Array.isArray(expandedLive) ? expandedLive : live).filter((metric) => metric !== "ALL" && !named.includes(metric));
|
|
41216
|
+
if (undeclared.length === 0) return;
|
|
41217
|
+
const secretDerived = mask(physicalId) !== physicalId;
|
|
41218
|
+
warn(`Kinesis stream ${physicalId} has shard-level metrics enabled that neither cdkd's record nor the template declares (${undeclared.join(", ")}), so cdkd left them enabled while converging the unsettled DesiredShardLevelMetrics (CloudFormation never disables a metric it did not record). Another tool may have enabled them, or an earlier failed cdkd update may have; cdkd cannot tell which. If they should be off, disable them ` + (secretDerived ? `with DisableEnhancedMonitoring for those metrics.` : `with: aws kinesis disable-enhanced-monitoring --stream-name ${physicalId} --shard-level-metrics ${undeclared.join(" ")} (in the stream's region)`));
|
|
41219
|
+
}
|
|
41220
|
+
async readUnsettled(physicalId, logicalId, resourceType, names, recordedProperties, desiredProperties) {
|
|
41221
|
+
const live = await this.readCurrentState(physicalId, logicalId, resourceType);
|
|
41222
|
+
if (typeof live !== "object" || live === null) return live;
|
|
41223
|
+
const out = { ...live };
|
|
41224
|
+
if (names.has("DesiredShardLevelMetrics") && Array.isArray(out["DesiredShardLevelMetrics"])) {
|
|
41225
|
+
const named = new Set([recordedProperties, desiredProperties].flatMap((bag) => {
|
|
41226
|
+
const expanded = expandShardLevelMetrics(bag?.["DesiredShardLevelMetrics"]);
|
|
41227
|
+
return isUsableMetricsList(expanded) ? expanded : [];
|
|
41228
|
+
}));
|
|
41229
|
+
const liveMetrics = expandShardLevelMetrics(out["DesiredShardLevelMetrics"]);
|
|
41230
|
+
out["DesiredShardLevelMetrics"] = (Array.isArray(liveMetrics) ? liveMetrics : []).filter((metric) => typeof metric === "string" && named.has(metric));
|
|
41231
|
+
}
|
|
41232
|
+
if (!names.has("ShardCount")) return out;
|
|
41233
|
+
return {
|
|
41234
|
+
...out,
|
|
41235
|
+
ShardCount: await this.getOpenShardCount(physicalId)
|
|
41236
|
+
};
|
|
41237
|
+
}
|
|
41238
|
+
async unsettledInTransition(physicalId, _logicalId, _resourceType, names) {
|
|
41239
|
+
try {
|
|
41240
|
+
const status = (await this.getClient().send(new DescribeStreamSummaryCommand({ StreamName: physicalId }))).StreamDescriptionSummary?.StreamStatus;
|
|
41241
|
+
if (status !== "UPDATING" && status !== "CREATING") return /* @__PURE__ */ new Set();
|
|
41242
|
+
return new Set([...names].filter((name) => name !== "Tags"));
|
|
41243
|
+
} catch {
|
|
41244
|
+
return names;
|
|
41245
|
+
}
|
|
41246
|
+
}
|
|
40925
41247
|
async readCurrentState(physicalId, _logicalId, resourceType, _properties) {
|
|
40926
41248
|
if (resourceType !== "AWS::Kinesis::Stream") return void 0;
|
|
40927
41249
|
let stream;
|
|
@@ -41687,6 +42009,13 @@ function pipeIdentityToken(name, arn, creationTime) {
|
|
|
41687
42009
|
return `${arn}@${Math.floor(ms / 1e3)}`;
|
|
41688
42010
|
}
|
|
41689
42011
|
const SETTLED_STATES = /* @__PURE__ */ new Set(["RUNNING", "STOPPED"]);
|
|
42012
|
+
const MOVING_STATES = /* @__PURE__ */ new Set([
|
|
42013
|
+
"CREATING",
|
|
42014
|
+
"UPDATING",
|
|
42015
|
+
"STARTING",
|
|
42016
|
+
"STOPPING",
|
|
42017
|
+
"DELETING"
|
|
42018
|
+
]);
|
|
41690
42019
|
const PIPE_POLL_INTERVAL_MS = 5e3;
|
|
41691
42020
|
const PIPE_SETTLE_MAX_WAIT_MS = 9e5;
|
|
41692
42021
|
const PIPE_DELETE_MAX_WAIT_MS = 6e5;
|
|
@@ -41980,13 +42309,19 @@ var PipesPipeProvider = class {
|
|
|
41980
42309
|
};
|
|
41981
42310
|
const sourceParameters = toUpdateSourceParameters(desired["SourceParameters"], previousProperties["SourceParameters"]);
|
|
41982
42311
|
if (sourceParameters !== void 0) input.SourceParameters = sourceParameters;
|
|
42312
|
+
for (const key of this.changedPipeFields(desired, previousProperties)) context?.markUnsettled?.(key);
|
|
41983
42313
|
const accepted = await this.getClient().send(new UpdatePipeCommand(input));
|
|
41984
42314
|
settled = await this.waitForSettled(physicalId, logicalId, resourceType, "update", mask, accepted.LastModifiedTime);
|
|
41985
42315
|
}
|
|
41986
|
-
const
|
|
42316
|
+
const recordedPlan = planTagDiff(tagMapAsList(previousProperties["Tags"]), tagMapAsList(desiredTags));
|
|
42317
|
+
const plan = context?.unsettledProperties?.has("Tags") === true ? {
|
|
42318
|
+
...recordedPlan,
|
|
42319
|
+
set: planTagDiff([], tagMapAsList(desiredTags)).set
|
|
42320
|
+
} : recordedPlan;
|
|
41987
42321
|
const warning = tagPlanWarning(plan, resourceType, logicalId);
|
|
41988
42322
|
if (warning) this.logger.warn(warning);
|
|
41989
42323
|
if (plan.set.size > 0 || plan.remove.length > 0) {
|
|
42324
|
+
context?.markUnsettled?.("Tags");
|
|
41990
42325
|
settled ??= await this.describe(physicalId);
|
|
41991
42326
|
const arn = settled.Arn;
|
|
41992
42327
|
if (!arn) throw new Error("DescribePipe returned no Arn, which tagging needs");
|
|
@@ -42146,10 +42481,30 @@ var PipesPipeProvider = class {
|
|
|
42146
42481
|
return value;
|
|
42147
42482
|
}
|
|
42148
42483
|
pipeFieldsChanged(desired, previous) {
|
|
42484
|
+
return this.changedPipeFields(desired, previous).length > 0;
|
|
42485
|
+
}
|
|
42486
|
+
changedPipeFields(desired, previous) {
|
|
42149
42487
|
const keys = /* @__PURE__ */ new Set([...Object.keys(desired), ...Object.keys(previous)]);
|
|
42150
42488
|
keys.delete("Tags");
|
|
42151
|
-
|
|
42152
|
-
|
|
42489
|
+
return [...keys].filter((key) => JSON.stringify(desired[key]) !== JSON.stringify(previous[key]));
|
|
42490
|
+
}
|
|
42491
|
+
async unsettledInTransition(physicalId, _logicalId, _resourceType, names) {
|
|
42492
|
+
try {
|
|
42493
|
+
const state = (await this.describe(physicalId)).CurrentState;
|
|
42494
|
+
if (state === void 0 || !MOVING_STATES.has(state)) return /* @__PURE__ */ new Set();
|
|
42495
|
+
return new Set([...names].filter((name) => name !== "Tags"));
|
|
42496
|
+
} catch {
|
|
42497
|
+
return names;
|
|
42498
|
+
}
|
|
42499
|
+
}
|
|
42500
|
+
async readUnsettled(physicalId, logicalId, resourceType, names) {
|
|
42501
|
+
const live = await this.readCurrentState(physicalId, logicalId, resourceType);
|
|
42502
|
+
if (typeof live !== "object" || live === null) return live;
|
|
42503
|
+
const state = (await this.describe(physicalId)).CurrentState;
|
|
42504
|
+
if (state === void 0 || !state.endsWith("_FAILED")) return live;
|
|
42505
|
+
const out = { ...live };
|
|
42506
|
+
for (const name of names) delete out[name];
|
|
42507
|
+
return out;
|
|
42153
42508
|
}
|
|
42154
42509
|
async readStateForDelete(name) {
|
|
42155
42510
|
try {
|
|
@@ -42312,6 +42667,7 @@ var EFSProvider = class {
|
|
|
42312
42667
|
providerRegion = ambientRegion();
|
|
42313
42668
|
logger = getLogger().child("EFSProvider");
|
|
42314
42669
|
unconfirmedCreationTokens = /* @__PURE__ */ new Map();
|
|
42670
|
+
removalDefaults = /* @__PURE__ */ new Map([["AWS::EFS::FileSystem", /* @__PURE__ */ new Map([["BackupPolicy", { Status: "DISABLED" }], ["FileSystemProtection", { ReplicationOverwriteProtection: "ENABLED" }]])]]);
|
|
42315
42671
|
handledProperties = /* @__PURE__ */ new Map([
|
|
42316
42672
|
["AWS::EFS::FileSystem", /* @__PURE__ */ new Set([
|
|
42317
42673
|
"FileSystemTags",
|
|
@@ -42383,13 +42739,56 @@ var EFSProvider = class {
|
|
|
42383
42739
|
}
|
|
42384
42740
|
update(logicalId, physicalId, resourceType, properties, previousProperties, context) {
|
|
42385
42741
|
const log = createMaskedLogSinks(this.logger, context?.maskSecrets);
|
|
42742
|
+
properties = withRemovalDefaults(this.removalDefaults, resourceType, properties, previousProperties, context);
|
|
42386
42743
|
switch (resourceType) {
|
|
42387
42744
|
case "AWS::EFS::FileSystem": return this.updateFileSystem(logicalId, physicalId, resourceType, properties, previousProperties, log);
|
|
42388
42745
|
case "AWS::EFS::MountTarget": return this.updateMountTarget(logicalId, physicalId, resourceType, properties, log);
|
|
42389
|
-
case "AWS::EFS::AccessPoint": return
|
|
42746
|
+
case "AWS::EFS::AccessPoint": return this.updateAccessPoint(logicalId, physicalId, resourceType, properties, previousProperties, log);
|
|
42390
42747
|
default: throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId, physicalId);
|
|
42391
42748
|
}
|
|
42392
42749
|
}
|
|
42750
|
+
async applyTagDiff(resourceId, resourceType, logicalId, recorded, desired, log) {
|
|
42751
|
+
const plan = planTagDiff(recorded, desired);
|
|
42752
|
+
const warning = tagPlanWarning(plan, resourceType, logicalId);
|
|
42753
|
+
if (warning !== void 0) log.warn(warning);
|
|
42754
|
+
if (plan.remove.length > 0) await this.retryOnTransientControlPlane(() => this.getClient().send(new UntagResourceCommand$24({
|
|
42755
|
+
ResourceId: resourceId,
|
|
42756
|
+
TagKeys: plan.remove
|
|
42757
|
+
})), `UntagResource ${resourceId}`, log);
|
|
42758
|
+
if (plan.set.size > 0) await this.retryOnTransientControlPlane(() => this.getClient().send(new TagResourceCommand$23({
|
|
42759
|
+
ResourceId: resourceId,
|
|
42760
|
+
Tags: [...plan.set].map(([Key, Value]) => ({
|
|
42761
|
+
Key,
|
|
42762
|
+
Value
|
|
42763
|
+
}))
|
|
42764
|
+
})), `TagResource ${resourceId}`, log);
|
|
42765
|
+
}
|
|
42766
|
+
async updateAccessPoint(logicalId, physicalId, resourceType, properties, previousProperties, log) {
|
|
42767
|
+
const isPlainObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
42768
|
+
const sameExceptSecretLeaves = (desired, recorded) => {
|
|
42769
|
+
if (desired !== void 0 && typeof recorded === "string" && holdsSecretDerivedEntry(recorded)) return true;
|
|
42770
|
+
if (Array.isArray(desired) && Array.isArray(recorded)) return desired.length === recorded.length && desired.every((d, i) => sameExceptSecretLeaves(d, recorded[i]));
|
|
42771
|
+
if (isPlainObject(desired) && isPlainObject(recorded)) return [.../* @__PURE__ */ new Set([...Object.keys(desired), ...Object.keys(recorded)])].every((k) => sameExceptSecretLeaves(desired[k], recorded[k]));
|
|
42772
|
+
return isDeepStrictEqual(desired, recorded);
|
|
42773
|
+
};
|
|
42774
|
+
const keys = /* @__PURE__ */ new Set([...Object.keys(properties), ...Object.keys(previousProperties)]);
|
|
42775
|
+
for (const key of keys) {
|
|
42776
|
+
if (key === "AccessPointTags") continue;
|
|
42777
|
+
if (!sameExceptSecretLeaves(properties[key], previousProperties[key])) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `AWS EFS AccessPoint ${key} changed or was removed, and it is immutable on AWS — there is no UpdateAccessPoint command, and only AccessPointTags can change in place; any other property change requires DeleteAccessPoint + CreateAccessPoint. Re-deploy with cdkd deploy --replace, or destroy + redeploy the stack.`);
|
|
42778
|
+
}
|
|
42779
|
+
refuseMalformedDesiredTags(properties["AccessPointTags"], resourceType, logicalId, physicalId, "AccessPointTags");
|
|
42780
|
+
try {
|
|
42781
|
+
await this.applyTagDiff(physicalId, resourceType, logicalId, previousProperties["AccessPointTags"], properties["AccessPointTags"], log);
|
|
42782
|
+
return {
|
|
42783
|
+
physicalId,
|
|
42784
|
+
wasReplaced: false
|
|
42785
|
+
};
|
|
42786
|
+
} catch (error) {
|
|
42787
|
+
if (error instanceof ProvisioningError) throw error;
|
|
42788
|
+
const cause = error instanceof Error ? error : void 0;
|
|
42789
|
+
throw this.wrapMaskedError(log, error, (text) => new ProvisioningError(`Failed to update EFS AccessPoint ${logicalId}: ${text}`, resourceType, logicalId, physicalId, cause));
|
|
42790
|
+
}
|
|
42791
|
+
}
|
|
42393
42792
|
async updateFileSystem(logicalId, physicalId, resourceType, properties, previousProperties, log) {
|
|
42394
42793
|
for (const key of [
|
|
42395
42794
|
"Encrypted",
|
|
@@ -42413,7 +42812,9 @@ var EFSProvider = class {
|
|
|
42413
42812
|
const backupChanged = changed("BackupPolicy");
|
|
42414
42813
|
const policyChanged = changed("FileSystemPolicy") || changed("BypassPolicyLockoutSafetyCheck");
|
|
42415
42814
|
const protectionChanged = changed("FileSystemProtection");
|
|
42416
|
-
|
|
42815
|
+
const tagsChanged = changed("FileSystemTags");
|
|
42816
|
+
if (tagsChanged) refuseMalformedDesiredTags(properties["FileSystemTags"], resourceType, logicalId, physicalId, "FileSystemTags");
|
|
42817
|
+
if (!throughputModeChanged && !provisionedChanged && !lifecycleChanged && !backupChanged && !policyChanged && !protectionChanged && !tagsChanged) {
|
|
42417
42818
|
log.debug(`No mutable diff for EFS FileSystem ${logicalId}, skipping update`);
|
|
42418
42819
|
return {
|
|
42419
42820
|
physicalId,
|
|
@@ -42432,8 +42833,12 @@ var EFSProvider = class {
|
|
|
42432
42833
|
}
|
|
42433
42834
|
if (lifecycleChanged) await this.applyLifecyclePolicies(physicalId, properties["LifecyclePolicies"], log, previousProperties["LifecyclePolicies"]);
|
|
42434
42835
|
if (backupChanged) await this.applyBackupPolicy(physicalId, properties["BackupPolicy"], log);
|
|
42435
|
-
if (policyChanged)
|
|
42836
|
+
if (policyChanged) {
|
|
42837
|
+
if (properties["FileSystemPolicy"] === void 0 && previousProperties["FileSystemPolicy"] !== void 0) await this.deleteFileSystemPolicy(physicalId, log);
|
|
42838
|
+
else await this.applyFileSystemPolicy(physicalId, properties["FileSystemPolicy"], properties["BypassPolicyLockoutSafetyCheck"], log);
|
|
42839
|
+
}
|
|
42436
42840
|
if (protectionChanged) await this.applyFileSystemProtection(physicalId, properties["FileSystemProtection"], log);
|
|
42841
|
+
if (tagsChanged) await this.applyTagDiff(physicalId, resourceType, logicalId, previousProperties["FileSystemTags"], properties["FileSystemTags"], log);
|
|
42437
42842
|
log.debug(`Successfully updated EFS FileSystem ${logicalId}`);
|
|
42438
42843
|
return {
|
|
42439
42844
|
physicalId,
|
|
@@ -42641,6 +43046,10 @@ var EFSProvider = class {
|
|
|
42641
43046
|
})), `set FileSystemPolicy on ${fileSystemId}`, log);
|
|
42642
43047
|
log.debug(`Set FileSystemPolicy on EFS FileSystem ${fileSystemId}`);
|
|
42643
43048
|
}
|
|
43049
|
+
async deleteFileSystemPolicy(fileSystemId, log) {
|
|
43050
|
+
await this.retryOnTransientControlPlane(() => this.getClient().send(new DeleteFileSystemPolicyCommand({ FileSystemId: fileSystemId })), `delete FileSystemPolicy on ${fileSystemId}`, log);
|
|
43051
|
+
log.debug(`Deleted FileSystemPolicy on EFS FileSystem ${fileSystemId}`);
|
|
43052
|
+
}
|
|
42644
43053
|
async applyFileSystemProtection(fileSystemId, spec, log) {
|
|
42645
43054
|
if (spec === void 0 || spec === null) return;
|
|
42646
43055
|
const protection = spec.ReplicationOverwriteProtection;
|
|
@@ -43149,6 +43558,23 @@ const routeTableDelta = (next, prev) => {
|
|
|
43149
43558
|
...remove.length > 0 && { remove }
|
|
43150
43559
|
};
|
|
43151
43560
|
};
|
|
43561
|
+
const STALE_FAILED_READS = 3;
|
|
43562
|
+
const ALIAS_NON_BLOCKING_ACTIONS = /* @__PURE__ */ new Set(["STORAGE_OPTIMIZATION", "IOPS_OPTIMIZATION"]);
|
|
43563
|
+
const runningAliasBlockingActions = (fs) => (fs.AdministrativeActions ?? []).filter((a) => (a.Status === "PENDING" || a.Status === "IN_PROGRESS") && !ALIAS_NON_BLOCKING_ACTIONS.has(a.AdministrativeActionType ?? "")).map((a) => a.AdministrativeActionType ?? "unknown");
|
|
43564
|
+
const isAdministrativeActionInProgress = (error) => error instanceof Error && error.name === "BadRequest" && /in progress/i.test(describeAwsFailure(error).detail);
|
|
43565
|
+
const isTransientFsxError = (error) => {
|
|
43566
|
+
const name = error instanceof Error ? error.name : "";
|
|
43567
|
+
return name === "ThrottlingException" || name === "ServiceLimitExceeded" || name === "InternalServerError" || name === "TimeoutError" || /rate exceeded|too many requests|timed? ?out|ECONNRESET|EPIPE|socket hang up/i.test(describeAwsFailure(error).detail);
|
|
43568
|
+
};
|
|
43569
|
+
const aliasDelta = (next, prev) => {
|
|
43570
|
+
const names = (value) => new Set((Array.isArray(value) ? value : []).filter((v) => typeof v === "string").map((v) => v.toLowerCase()));
|
|
43571
|
+
const nextNames = names(next);
|
|
43572
|
+
const prevNames = names(prev);
|
|
43573
|
+
return {
|
|
43574
|
+
add: [...nextNames].filter((n) => !prevNames.has(n)),
|
|
43575
|
+
remove: [...prevNames].filter((n) => !nextNames.has(n))
|
|
43576
|
+
};
|
|
43577
|
+
};
|
|
43152
43578
|
const TOP_LEVEL_IMMUTABLE_PROPS = [
|
|
43153
43579
|
"FileSystemType",
|
|
43154
43580
|
"SubnetIds",
|
|
@@ -43551,11 +43977,16 @@ var FSxFileSystemProvider = class {
|
|
|
43551
43977
|
if (JSON.stringify(next ?? null) !== JSON.stringify(prev ?? null)) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `AWS FSx FileSystem ${key} is immutable on AWS — UpdateFileSystem does not accept ${key}; the property is fixed at creation. Re-deploy with cdkd deploy --replace --force-stateful-recreation (the type is in cdkd's stateful-recreate guard set, so a bare --replace is refused a second time with STATEFUL_REPLACE_BLOCKED), or destroy + redeploy the stack.`);
|
|
43552
43978
|
}
|
|
43553
43979
|
const variantConfigKey = this.detectVariantConfigKey(properties, previousProperties);
|
|
43554
|
-
const { diff: variantDiff, hasMutableDiff: variantHasMutableDiff, leftInPlace } = variantConfigKey ? this.computeVariantConfigDiff(resourceType, logicalId, variantConfigKey, properties[variantConfigKey] ?? {}, previousProperties[variantConfigKey] ?? {}) : {
|
|
43980
|
+
const { diff: variantDiff, hasMutableDiff: variantHasMutableDiff, leftInPlace, aliases } = variantConfigKey ? this.computeVariantConfigDiff(resourceType, logicalId, variantConfigKey, properties[variantConfigKey] ?? {}, previousProperties[variantConfigKey] ?? {}) : {
|
|
43555
43981
|
diff: {},
|
|
43556
43982
|
hasMutableDiff: false,
|
|
43557
|
-
leftInPlace: []
|
|
43983
|
+
leftInPlace: [],
|
|
43984
|
+
aliases: {
|
|
43985
|
+
add: [],
|
|
43986
|
+
remove: []
|
|
43987
|
+
}
|
|
43558
43988
|
};
|
|
43989
|
+
const aliasesChanged = aliases.add.length > 0 || aliases.remove.length > 0;
|
|
43559
43990
|
const leftInPlaceNames = [...TOP_LEVEL_LEFT_IN_PLACE_PROPS.filter((key) => properties[key] === void 0 && previousProperties[key] !== void 0), ...leftInPlace.map((key) => `${variantConfigKey}.${key}`)];
|
|
43560
43991
|
const warnLeftInPlace = () => {
|
|
43561
43992
|
if (leftInPlaceNames.length === 0 || context?.desiredFromAwsReadback) return;
|
|
@@ -43576,7 +44007,7 @@ var FSxFileSystemProvider = class {
|
|
|
43576
44007
|
const typeVersionChanged = sendsChange("FileSystemTypeVersion");
|
|
43577
44008
|
const networkTypeChanged = sendsChange("NetworkType");
|
|
43578
44009
|
const tagsChanged = changed("Tags");
|
|
43579
|
-
if (!variantHasMutableDiff && !storageCapacityChanged && !storageTypeChanged && !typeVersionChanged && !networkTypeChanged && !tagsChanged) {
|
|
44010
|
+
if (!variantHasMutableDiff && !storageCapacityChanged && !storageTypeChanged && !typeVersionChanged && !networkTypeChanged && !aliasesChanged && !tagsChanged) {
|
|
43580
44011
|
this.logger.debug(`No mutable diff for FSx FileSystem ${logicalId}, skipping update`);
|
|
43581
44012
|
warnLeftInPlace();
|
|
43582
44013
|
return {
|
|
@@ -43586,6 +44017,7 @@ var FSxFileSystemProvider = class {
|
|
|
43586
44017
|
}
|
|
43587
44018
|
this.logger.debug(`Updating FSx FileSystem ${logicalId}: ${physicalId}`);
|
|
43588
44019
|
try {
|
|
44020
|
+
const deadline = Date.now() + this.maxWaitMs;
|
|
43589
44021
|
const needsUpdateCall = variantHasMutableDiff || storageCapacityChanged || storageTypeChanged || typeVersionChanged || networkTypeChanged;
|
|
43590
44022
|
let updatedFs;
|
|
43591
44023
|
if (needsUpdateCall) {
|
|
@@ -43600,8 +44032,9 @@ var FSxFileSystemProvider = class {
|
|
|
43600
44032
|
}))).FileSystem?.AdministrativeActions ?? []).filter((a) => a.AdministrativeActionType === "FILE_SYSTEM_UPDATE" && (a.Status === "PENDING" || a.Status === "IN_PROGRESS"));
|
|
43601
44033
|
const requestTimes = respPendingActions.map((a) => a.RequestTime?.getTime()).filter((t) => t !== void 0);
|
|
43602
44034
|
const actionThresholdMs = requestTimes.length > 0 ? Math.min(...requestTimes) : callTimeMs - 6e4;
|
|
43603
|
-
updatedFs = await this.waitForUpdateActionComplete(physicalId, logicalId, resourceType, actionThresholdMs, respPendingActions.length > 0, context?.maskSecrets);
|
|
44035
|
+
updatedFs = await this.waitForUpdateActionComplete(physicalId, logicalId, resourceType, actionThresholdMs, respPendingActions.length > 0, deadline, context?.maskSecrets);
|
|
43604
44036
|
}
|
|
44037
|
+
if (aliasesChanged) await this.applyAliasDelta(physicalId, logicalId, resourceType, aliases, deadline);
|
|
43605
44038
|
if (tagsChanged) await this.applyTagDiff(physicalId, resourceType, logicalId, properties["Tags"], previousProperties["Tags"]);
|
|
43606
44039
|
if (!updatedFs) try {
|
|
43607
44040
|
updatedFs = (await this.getClient().send(new DescribeFileSystemsCommand$1({ FileSystemIds: [physicalId] }))).FileSystems?.[0];
|
|
@@ -43629,12 +44062,20 @@ var FSxFileSystemProvider = class {
|
|
|
43629
44062
|
const keys = /* @__PURE__ */ new Set([...Object.keys(next), ...Object.keys(prev)]);
|
|
43630
44063
|
const diff = {};
|
|
43631
44064
|
const leftInPlace = [];
|
|
44065
|
+
let aliases = {
|
|
44066
|
+
add: [],
|
|
44067
|
+
remove: []
|
|
44068
|
+
};
|
|
43632
44069
|
let hasMutableDiff = false;
|
|
43633
44070
|
for (const key of keys) {
|
|
43634
44071
|
const nextVal = next[key];
|
|
43635
44072
|
const prevVal = prev[key];
|
|
43636
44073
|
if (JSON.stringify(nextVal) === JSON.stringify(prevVal)) continue;
|
|
43637
44074
|
if (configKey === "OpenZFSConfiguration" && key === "Options") continue;
|
|
44075
|
+
if (configKey === "WindowsConfiguration" && key === "Aliases") {
|
|
44076
|
+
aliases = aliasDelta(nextVal, prevVal);
|
|
44077
|
+
continue;
|
|
44078
|
+
}
|
|
43638
44079
|
if (!mutable.has(key)) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `AWS FSx FileSystem ${configKey}.${key} is immutable on AWS — UpdateFileSystem cannot change it after creation. Re-deploy with cdkd deploy --replace --force-stateful-recreation (the type is in cdkd's stateful-recreate guard set, so a bare --replace is refused a second time with STATEFUL_REPLACE_BLOCKED), or destroy + redeploy the stack.`);
|
|
43639
44080
|
if (nextVal === void 0 && key !== "RouteTableIds") {
|
|
43640
44081
|
leftInPlace.push(key);
|
|
@@ -43650,7 +44091,8 @@ var FSxFileSystemProvider = class {
|
|
|
43650
44091
|
return {
|
|
43651
44092
|
diff,
|
|
43652
44093
|
hasMutableDiff,
|
|
43653
|
-
leftInPlace
|
|
44094
|
+
leftInPlace,
|
|
44095
|
+
aliases
|
|
43654
44096
|
};
|
|
43655
44097
|
}
|
|
43656
44098
|
unmappedMutableSubprop(ctx, key) {
|
|
@@ -43782,6 +44224,104 @@ var FSxFileSystemProvider = class {
|
|
|
43782
44224
|
}
|
|
43783
44225
|
return true;
|
|
43784
44226
|
}
|
|
44227
|
+
async applyAliasDelta(physicalId, logicalId, resourceType, delta, deadline) {
|
|
44228
|
+
await this.waitForNoAdministrativeAction(physicalId, logicalId, resourceType, deadline);
|
|
44229
|
+
const live = new Map((await this.describeAliases(physicalId)).map((a) => [a.Name?.toLowerCase(), a.Lifecycle]));
|
|
44230
|
+
const retryAdd = delta.add.filter((n) => {
|
|
44231
|
+
const lifecycle = live.get(n);
|
|
44232
|
+
return lifecycle === "CREATE_FAILED" || lifecycle === "DELETING" || lifecycle === "DELETE_FAILED";
|
|
44233
|
+
});
|
|
44234
|
+
const awaitGone = [...delta.remove, ...retryAdd];
|
|
44235
|
+
const sendRemove = awaitGone.filter((n) => live.has(n) && live.get(n) !== "DELETING");
|
|
44236
|
+
const sendAdd = delta.add.filter((n) => live.get(n) !== "AVAILABLE" && live.get(n) !== "CREATING");
|
|
44237
|
+
if (sendRemove.length > 0) await this.sendAliasCall(physicalId, logicalId, resourceType, () => new DisassociateFileSystemAliasesCommand({
|
|
44238
|
+
FileSystemId: physicalId,
|
|
44239
|
+
Aliases: sendRemove
|
|
44240
|
+
}), deadline);
|
|
44241
|
+
if (awaitGone.length > 0) await this.waitForAliases(physicalId, logicalId, resourceType, awaitGone, "gone", deadline);
|
|
44242
|
+
if (sendAdd.length > 0) await this.sendAliasCall(physicalId, logicalId, resourceType, () => new AssociateFileSystemAliasesCommand({
|
|
44243
|
+
FileSystemId: physicalId,
|
|
44244
|
+
Aliases: sendAdd
|
|
44245
|
+
}), deadline);
|
|
44246
|
+
if (delta.add.length > 0) await this.waitForAliases(physicalId, logicalId, resourceType, delta.add, "AVAILABLE", deadline);
|
|
44247
|
+
}
|
|
44248
|
+
async describeAliases(physicalId) {
|
|
44249
|
+
const aliases = [];
|
|
44250
|
+
let nextToken;
|
|
44251
|
+
do {
|
|
44252
|
+
const resp = await this.getClient().send(new DescribeFileSystemAliasesCommand({
|
|
44253
|
+
FileSystemId: physicalId,
|
|
44254
|
+
NextToken: nextToken
|
|
44255
|
+
}));
|
|
44256
|
+
aliases.push(...resp.Aliases ?? []);
|
|
44257
|
+
nextToken = resp.NextToken;
|
|
44258
|
+
} while (nextToken);
|
|
44259
|
+
return aliases;
|
|
44260
|
+
}
|
|
44261
|
+
async waitForNoAdministrativeAction(physicalId, logicalId, resourceType, deadline) {
|
|
44262
|
+
const transientState = { count: 0 };
|
|
44263
|
+
let running = [];
|
|
44264
|
+
while (Date.now() < deadline) {
|
|
44265
|
+
const fs = await this.describeForPoll(physicalId, transientState);
|
|
44266
|
+
if (fs) {
|
|
44267
|
+
running = runningAliasBlockingActions(fs);
|
|
44268
|
+
if (running.length === 0) return;
|
|
44269
|
+
this.logger.debug(safeMsg`FSx FileSystem ${physicalId}: waiting for ${running.join(", ")} to finish before changing DNS aliases...`);
|
|
44270
|
+
}
|
|
44271
|
+
await new Promise((resolve) => setTimeout(resolve, this.pollIntervalMs));
|
|
44272
|
+
}
|
|
44273
|
+
throw new ProvisioningError(safeMsg`Timed out waiting for FSx FileSystem ${physicalId} administrative actions (${running.join(", ") || "unknown"}) to finish before changing its DNS aliases (${Math.round(this.maxWaitMs / 6e4)} min). Re-deploy once they complete.`, resourceType, logicalId, physicalId);
|
|
44274
|
+
}
|
|
44275
|
+
async sendAliasCall(physicalId, logicalId, resourceType, command, deadline) {
|
|
44276
|
+
for (;;) try {
|
|
44277
|
+
const call = command();
|
|
44278
|
+
if (call instanceof AssociateFileSystemAliasesCommand) await this.getClient().send(call);
|
|
44279
|
+
else await this.getClient().send(call);
|
|
44280
|
+
return;
|
|
44281
|
+
} catch (error) {
|
|
44282
|
+
if (!isAdministrativeActionInProgress(error)) throw error;
|
|
44283
|
+
if (Date.now() >= deadline) {
|
|
44284
|
+
let running = [];
|
|
44285
|
+
try {
|
|
44286
|
+
running = ((await this.describeForPoll(physicalId, { count: 0 }))?.AdministrativeActions ?? []).filter((a) => a.Status === "PENDING" || a.Status === "IN_PROGRESS").map((a) => a.AdministrativeActionType ?? "unknown");
|
|
44287
|
+
} catch {}
|
|
44288
|
+
throw new ProvisioningError(safeMsg`Timed out changing FSx FileSystem ${physicalId} DNS aliases: FSx kept refusing the call while an administrative action (${running.join(", ") || "unknown"}) is in progress (${Math.round(this.maxWaitMs / 6e4)} min). Re-deploy once it completes.`, resourceType, logicalId, physicalId, error);
|
|
44289
|
+
}
|
|
44290
|
+
this.logger.debug(safeMsg`FSx FileSystem ${physicalId}: DNS alias call refused while an administrative action is in progress, re-sending...`);
|
|
44291
|
+
await new Promise((resolve) => setTimeout(resolve, this.pollIntervalMs));
|
|
44292
|
+
}
|
|
44293
|
+
}
|
|
44294
|
+
async waitForAliases(physicalId, logicalId, resourceType, names, target, deadline) {
|
|
44295
|
+
const failedLifecycle = target === "AVAILABLE" ? "CREATE_FAILED" : "DELETE_FAILED";
|
|
44296
|
+
const transitionLifecycle = target === "AVAILABLE" ? "CREATING" : "DELETING";
|
|
44297
|
+
const seenTransition = /* @__PURE__ */ new Set();
|
|
44298
|
+
const failedReads = /* @__PURE__ */ new Map();
|
|
44299
|
+
let transient = 0;
|
|
44300
|
+
while (Date.now() < deadline) {
|
|
44301
|
+
let aliases;
|
|
44302
|
+
try {
|
|
44303
|
+
aliases = await this.describeAliases(physicalId);
|
|
44304
|
+
transient = 0;
|
|
44305
|
+
} catch (error) {
|
|
44306
|
+
if (!isTransientFsxError(error) || transient >= 5) throw error;
|
|
44307
|
+
transient += 1;
|
|
44308
|
+
await new Promise((resolve) => setTimeout(resolve, this.pollIntervalMs));
|
|
44309
|
+
continue;
|
|
44310
|
+
}
|
|
44311
|
+
const byName = new Map(aliases.map((a) => [a.Name?.toLowerCase(), a.Lifecycle]));
|
|
44312
|
+
for (const n of names) {
|
|
44313
|
+
const lifecycle = byName.get(n);
|
|
44314
|
+
if (lifecycle === transitionLifecycle) seenTransition.add(n);
|
|
44315
|
+
failedReads.set(n, lifecycle === failedLifecycle ? (failedReads.get(n) ?? 0) + 1 : 0);
|
|
44316
|
+
}
|
|
44317
|
+
const failed = names.filter((n) => byName.get(n) === failedLifecycle && (seenTransition.has(n) || (failedReads.get(n) ?? 0) >= STALE_FAILED_READS));
|
|
44318
|
+
if (failed.length > 0) throw new ProvisioningError(safeMsg`FSx FileSystem ${physicalId}: DNS alias ${failed.join(", ")} entered ${failedLifecycle}. Check the alias name and the file system's Active Directory, then re-deploy.`, resourceType, logicalId, physicalId);
|
|
44319
|
+
if (names.every((n) => target === "AVAILABLE" ? byName.get(n) === "AVAILABLE" : !byName.has(n))) return;
|
|
44320
|
+
this.logger.debug(safeMsg`FSx FileSystem ${physicalId}: waiting for DNS aliases ${names.join(", ")} to be ${target}...`);
|
|
44321
|
+
await new Promise((resolve) => setTimeout(resolve, this.pollIntervalMs));
|
|
44322
|
+
}
|
|
44323
|
+
throw new ProvisioningError(safeMsg`Timed out waiting for FSx FileSystem ${physicalId} DNS aliases ${names.join(", ")} to be ${target} (${Math.round(this.maxWaitMs / 6e4)} min)`, resourceType, logicalId, physicalId);
|
|
44324
|
+
}
|
|
43785
44325
|
async applyTagDiff(physicalId, resourceType, logicalId, nextTags, prevTags) {
|
|
43786
44326
|
const plan = planTagDiff(prevTags, nextTags);
|
|
43787
44327
|
const arn = (await this.getClient().send(new DescribeFileSystemsCommand$1({ FileSystemIds: [physicalId] }))).FileSystems?.[0]?.ResourceARN;
|
|
@@ -43793,11 +44333,11 @@ var FSxFileSystemProvider = class {
|
|
|
43793
44333
|
Value
|
|
43794
44334
|
}));
|
|
43795
44335
|
const toRemove = plan.remove;
|
|
43796
|
-
if (toSet.length > 0) await this.getClient().send(new TagResourceCommand$
|
|
44336
|
+
if (toSet.length > 0) await this.getClient().send(new TagResourceCommand$24({
|
|
43797
44337
|
ResourceARN: arn,
|
|
43798
44338
|
Tags: toSet
|
|
43799
44339
|
}));
|
|
43800
|
-
if (toRemove.length > 0) await this.getClient().send(new UntagResourceCommand$
|
|
44340
|
+
if (toRemove.length > 0) await this.getClient().send(new UntagResourceCommand$25({
|
|
43801
44341
|
ResourceARN: arn,
|
|
43802
44342
|
TagKeys: toRemove
|
|
43803
44343
|
}));
|
|
@@ -43863,9 +44403,8 @@ var FSxFileSystemProvider = class {
|
|
|
43863
44403
|
transientState.count = 0;
|
|
43864
44404
|
return response.FileSystems?.[0];
|
|
43865
44405
|
} catch (error) {
|
|
43866
|
-
const name = error instanceof Error ? error.name : "";
|
|
43867
44406
|
const msg = describeAwsFailure(error).detail;
|
|
43868
|
-
if ((
|
|
44407
|
+
if (isTransientFsxError(error) && transientState.count < maxConsecutiveTransient) {
|
|
43869
44408
|
transientState.count += 1;
|
|
43870
44409
|
this.logger.debug(`Transient DescribeFileSystems error while polling ${fileSystemId} (${transientState.count}/${maxConsecutiveTransient}): ${msg} — retrying`);
|
|
43871
44410
|
return;
|
|
@@ -43886,11 +44425,10 @@ var FSxFileSystemProvider = class {
|
|
|
43886
44425
|
}
|
|
43887
44426
|
throw new ProvisioningError(`Timed out waiting for FSx FileSystem ${fileSystemId} to become AVAILABLE (${Math.round(this.maxWaitMs / 6e4)} min)`, resourceType, logicalId, fileSystemId);
|
|
43888
44427
|
}
|
|
43889
|
-
async waitForUpdateActionComplete(fileSystemId, logicalId, resourceType, actionThresholdMs, requireActionObservation, mask) {
|
|
43890
|
-
const startTime = Date.now();
|
|
44428
|
+
async waitForUpdateActionComplete(fileSystemId, logicalId, resourceType, actionThresholdMs, requireActionObservation, deadline, mask) {
|
|
43891
44429
|
const transientState = { count: 0 };
|
|
43892
44430
|
let seenTrackedAction = false;
|
|
43893
|
-
while (Date.now()
|
|
44431
|
+
while (Date.now() < deadline) {
|
|
43894
44432
|
const fs = await this.describeForPoll(fileSystemId, transientState);
|
|
43895
44433
|
if (fs) {
|
|
43896
44434
|
const updateActions = (fs.AdministrativeActions ?? []).filter((a) => a.AdministrativeActionType === "FILE_SYSTEM_UPDATE" && (a.RequestTime === void 0 || a.RequestTime.getTime() >= actionThresholdMs));
|
|
@@ -44079,13 +44617,26 @@ var FSxFileSystemProvider = class {
|
|
|
44079
44617
|
canonicalizeDriftProperties(resourceType, properties) {
|
|
44080
44618
|
if (resourceType !== "AWS::FSx::FileSystem") return properties;
|
|
44081
44619
|
const lustre = properties["LustreConfiguration"];
|
|
44082
|
-
if (typeof lustre !== "object" || lustre === null || Array.isArray(lustre)) return properties;
|
|
44620
|
+
if (typeof lustre !== "object" || lustre === null || Array.isArray(lustre)) return this.canonicalizeWindowsAliases(properties);
|
|
44083
44621
|
const log = lustre["LogConfiguration"];
|
|
44084
|
-
if (typeof log !== "object" || log === null || Array.isArray(log) || JSON.stringify(log) !== JSON.stringify({ Level: "DISABLED" })) return properties;
|
|
44622
|
+
if (typeof log !== "object" || log === null || Array.isArray(log) || JSON.stringify(log) !== JSON.stringify({ Level: "DISABLED" })) return this.canonicalizeWindowsAliases(properties);
|
|
44085
44623
|
const { LogConfiguration: _disabled, ...rest } = lustre;
|
|
44086
|
-
return {
|
|
44624
|
+
return this.canonicalizeWindowsAliases({
|
|
44087
44625
|
...properties,
|
|
44088
44626
|
LustreConfiguration: rest
|
|
44627
|
+
});
|
|
44628
|
+
}
|
|
44629
|
+
canonicalizeWindowsAliases(properties) {
|
|
44630
|
+
const windows = properties["WindowsConfiguration"];
|
|
44631
|
+
if (typeof windows !== "object" || windows === null || Array.isArray(windows)) return properties;
|
|
44632
|
+
const aliases = windows["Aliases"];
|
|
44633
|
+
if (!Array.isArray(aliases) || aliases.every((a) => typeof a !== "string" || a === a.toLowerCase())) return properties;
|
|
44634
|
+
return {
|
|
44635
|
+
...properties,
|
|
44636
|
+
WindowsConfiguration: {
|
|
44637
|
+
...windows,
|
|
44638
|
+
Aliases: aliases.map((a) => typeof a === "string" ? a.toLowerCase() : a)
|
|
44639
|
+
}
|
|
44089
44640
|
};
|
|
44090
44641
|
}
|
|
44091
44642
|
getDriftUnknownPaths(resourceType) {
|
|
@@ -44226,6 +44777,12 @@ const toNumber$2 = (v) => {
|
|
|
44226
44777
|
const jsonEqual$2 = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
44227
44778
|
const addInstanceGroupsLatch = new AmbiguousCreateLatch("emr:AddInstanceGroups");
|
|
44228
44779
|
const groupsCreatedByThisProcess = new RecentIdSet();
|
|
44780
|
+
const MOVING_GROUP_STATES = /* @__PURE__ */ new Set([
|
|
44781
|
+
"PROVISIONING",
|
|
44782
|
+
"BOOTSTRAPPING",
|
|
44783
|
+
"RESIZING",
|
|
44784
|
+
"RECONFIGURING"
|
|
44785
|
+
]);
|
|
44229
44786
|
var EMRInstanceGroupConfigProvider = class {
|
|
44230
44787
|
disableCcApiFallback = true;
|
|
44231
44788
|
client;
|
|
@@ -44426,6 +44983,7 @@ var EMRInstanceGroupConfigProvider = class {
|
|
|
44426
44983
|
this.logger.debug(`Updating EMR instance group ${logicalId}: ${physicalId}`);
|
|
44427
44984
|
try {
|
|
44428
44985
|
if (instanceCountChanged) {
|
|
44986
|
+
context?.markUnsettled?.("InstanceCount");
|
|
44429
44987
|
await this.getClient().send(new ModifyInstanceGroupsCommand({
|
|
44430
44988
|
...jobFlowId && { ClusterId: jobFlowId },
|
|
44431
44989
|
InstanceGroups: [{
|
|
@@ -44438,6 +44996,7 @@ var EMRInstanceGroupConfigProvider = class {
|
|
|
44438
44996
|
if (autoScalingChanged) {
|
|
44439
44997
|
if (!jobFlowId) throw new ProvisioningError(`EMR InstanceGroupConfig ${logicalId} AutoScalingPolicy update needs JobFlowId (the cluster id), which is absent`, resourceType, logicalId, physicalId);
|
|
44440
44998
|
const policy = properties["AutoScalingPolicy"];
|
|
44999
|
+
context?.markUnsettled?.("AutoScalingPolicy");
|
|
44441
45000
|
if (policy) await this.getClient().send(new PutAutoScalingPolicyCommand({
|
|
44442
45001
|
ClusterId: jobFlowId,
|
|
44443
45002
|
InstanceGroupId: physicalId,
|
|
@@ -44521,6 +45080,27 @@ var EMRInstanceGroupConfigProvider = class {
|
|
|
44521
45080
|
}
|
|
44522
45081
|
throw new ProvisioningError(`Timed out waiting for EMR instance group ${groupId} to reach RUNNING with ${expectedCount} instance(s) (${Math.round(this.maxWaitMs / 6e4)} min)`, resourceType, logicalId, groupId);
|
|
44523
45082
|
}
|
|
45083
|
+
async readUnsettled(physicalId, logicalId, resourceType, _names, recordedProperties) {
|
|
45084
|
+
const jobFlowId = recordedProperties?.["JobFlowId"];
|
|
45085
|
+
if (typeof jobFlowId !== "string" || jobFlowId === "") throw new ProvisioningError(`EMR InstanceGroupConfig ${logicalId} has no JobFlowId (the cluster id) recorded, so cdkd cannot read the group to converge what an earlier failed update left unsettled`, resourceType, logicalId, physicalId);
|
|
45086
|
+
const group = await this.findGroupForPoll(jobFlowId, physicalId, { count: 0 }, 0);
|
|
45087
|
+
if (group === void 0) return void 0;
|
|
45088
|
+
return {
|
|
45089
|
+
...group.RunningInstanceCount !== void 0 && { InstanceCount: group.RunningInstanceCount },
|
|
45090
|
+
...group.AutoScalingPolicy !== void 0 && { AutoScalingPolicy: group.AutoScalingPolicy }
|
|
45091
|
+
};
|
|
45092
|
+
}
|
|
45093
|
+
async unsettledInTransition(physicalId, _logicalId, _resourceType, names, recordedProperties) {
|
|
45094
|
+
if (!names.has("InstanceCount")) return /* @__PURE__ */ new Set();
|
|
45095
|
+
const jobFlowId = recordedProperties?.["JobFlowId"];
|
|
45096
|
+
if (typeof jobFlowId !== "string" || jobFlowId === "") return /* @__PURE__ */ new Set();
|
|
45097
|
+
try {
|
|
45098
|
+
const state = (await this.findGroupForPoll(jobFlowId, physicalId, { count: 0 }, 0))?.Status?.State;
|
|
45099
|
+
return state !== void 0 && MOVING_GROUP_STATES.has(state) ? /* @__PURE__ */ new Set(["InstanceCount"]) : /* @__PURE__ */ new Set();
|
|
45100
|
+
} catch {
|
|
45101
|
+
return /* @__PURE__ */ new Set(["InstanceCount"]);
|
|
45102
|
+
}
|
|
45103
|
+
}
|
|
44524
45104
|
async findGroupForPoll(clusterId, groupId, transientState, maxConsecutiveTransient = 5) {
|
|
44525
45105
|
try {
|
|
44526
45106
|
let marker;
|
|
@@ -45941,6 +46521,9 @@ function liveEncryptionAsCfn(live) {
|
|
|
45941
46521
|
}
|
|
45942
46522
|
const ENCRYPTION_POLL_INTERVAL_MS = 5e3;
|
|
45943
46523
|
const ENCRYPTION_POLL_MAX_ATTEMPTS = 120;
|
|
46524
|
+
const ACTIVE_POLL_INTERVAL_MS = 5e3;
|
|
46525
|
+
const ACTIVE_POLL_MAX_ATTEMPTS = 360;
|
|
46526
|
+
const ACTIVE_DEADLINE_MARGIN_MS = 2e3;
|
|
45944
46527
|
const terminalEncryptionFailures = /* @__PURE__ */ new WeakSet();
|
|
45945
46528
|
function isReadableTagList(value) {
|
|
45946
46529
|
if (value === void 0 || value === null) return true;
|
|
@@ -46158,7 +46741,7 @@ var FirehoseProvider = class {
|
|
|
46158
46741
|
createdStreamName = physicalId;
|
|
46159
46742
|
const arn = response.DeliveryStreamARN;
|
|
46160
46743
|
this.logger.debug(`Successfully created Firehose delivery stream ${logicalId}: ${physicalId}`);
|
|
46161
|
-
await this.waitForActive(physicalId, logicalId);
|
|
46744
|
+
await this.waitForActive(physicalId, logicalId, resourceType, maskerOrIdentity(context?.maskSecrets));
|
|
46162
46745
|
return {
|
|
46163
46746
|
physicalId,
|
|
46164
46747
|
attributes: { Arn: arn }
|
|
@@ -46182,7 +46765,7 @@ var FirehoseProvider = class {
|
|
|
46182
46765
|
async applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, context) {
|
|
46183
46766
|
this.logger.debug(`Updating Firehose delivery stream ${logicalId}: ${physicalId}`);
|
|
46184
46767
|
const desiredEncryption = readEncryptionInput(properties[ENCRYPTION_KEY], context?.desiredFromAwsReadback === true);
|
|
46185
|
-
const encryptionChanged = !sameEncryptionInput(properties[ENCRYPTION_KEY], desiredEncryption, previousProperties[ENCRYPTION_KEY]);
|
|
46768
|
+
const encryptionChanged = !sameEncryptionInput(properties[ENCRYPTION_KEY], desiredEncryption, previousProperties[ENCRYPTION_KEY]) || context?.unsettledProperties?.has(ENCRYPTION_KEY) === true && desiredEncryption.kind !== "unusable";
|
|
46186
46769
|
let encryptionSkipped = false;
|
|
46187
46770
|
if (encryptionChanged && desiredEncryption.kind === "unusable") {
|
|
46188
46771
|
const message = `${ENCRYPTION_KEY} of Firehose delivery stream ${logicalId} is not an object with a string KeyType (and a string KeyARN, if any)`;
|
|
@@ -46251,7 +46834,7 @@ var FirehoseProvider = class {
|
|
|
46251
46834
|
const prevDest = previousProperties[activeDest] ?? {};
|
|
46252
46835
|
if (JSON.stringify(nextDest) !== JSON.stringify(prevDest)) await this.applySnowflakeDestinationUpdate(logicalId, physicalId, nextDest);
|
|
46253
46836
|
}
|
|
46254
|
-
if (encryptionChanged && desiredEncryption.kind !== "unusable") await this.applyEncryptionUpdate(logicalId, physicalId, resourceType, desiredEncryption, maskerOrIdentity(context?.maskSecrets));
|
|
46837
|
+
if (encryptionChanged && desiredEncryption.kind !== "unusable") await this.applyEncryptionUpdate(logicalId, physicalId, resourceType, desiredEncryption, maskerOrIdentity(context?.maskSecrets), context?.markUnsettled);
|
|
46255
46838
|
const description = await this.getClient().send(new DescribeDeliveryStreamCommand({ DeliveryStreamName: physicalId }));
|
|
46256
46839
|
this.warnUnappliedS3BackupMode(logicalId, properties, unappliedS3BackupModeDestination(properties, previousProperties, destKey, context?.changedProperties), description.DeliveryStreamDescription);
|
|
46257
46840
|
const desc = description.DeliveryStreamDescription;
|
|
@@ -46332,7 +46915,7 @@ var FirehoseProvider = class {
|
|
|
46332
46915
|
}))
|
|
46333
46916
|
}));
|
|
46334
46917
|
}
|
|
46335
|
-
async applyEncryptionUpdate(logicalId, physicalId, resourceType, desired, mask) {
|
|
46918
|
+
async applyEncryptionUpdate(logicalId, physicalId, resourceType, desired, mask, markUnsettled) {
|
|
46336
46919
|
const settled = await this.waitForEncryption(logicalId, physicalId, resourceType, mask, {
|
|
46337
46920
|
what: "settle",
|
|
46338
46921
|
done: (enc) => enc?.Status !== "ENABLING" && enc?.Status !== "DISABLING"
|
|
@@ -46340,8 +46923,9 @@ var FirehoseProvider = class {
|
|
|
46340
46923
|
if (desired.kind === "absent") {
|
|
46341
46924
|
if (settled?.Status !== "ENABLED" && settled?.Status !== "DISABLING_FAILED") return;
|
|
46342
46925
|
this.refuseToStartTransition(logicalId, physicalId, resourceType, "disable");
|
|
46926
|
+
markUnsettled?.(ENCRYPTION_KEY);
|
|
46343
46927
|
await this.getClient().send(new StopDeliveryStreamEncryptionCommand({ DeliveryStreamName: physicalId }));
|
|
46344
|
-
await this.warnIfUnfinished(logicalId, "StopDeliveryStreamEncryption", () => this.waitForEncryption(logicalId, physicalId, resourceType, mask, {
|
|
46928
|
+
await this.warnIfUnfinished(logicalId, "StopDeliveryStreamEncryption", markUnsettled, () => this.waitForEncryption(logicalId, physicalId, resourceType, mask, {
|
|
46345
46929
|
what: "disable",
|
|
46346
46930
|
done: (enc) => enc === void 0 || enc.Status === "DISABLED",
|
|
46347
46931
|
inProgress: "DISABLING",
|
|
@@ -46352,6 +46936,7 @@ var FirehoseProvider = class {
|
|
|
46352
46936
|
}
|
|
46353
46937
|
if (encryptionMatches(settled, desired)) return;
|
|
46354
46938
|
this.refuseToStartTransition(logicalId, physicalId, resourceType, "enable");
|
|
46939
|
+
markUnsettled?.(ENCRYPTION_KEY);
|
|
46355
46940
|
await this.getClient().send(new StartDeliveryStreamEncryptionCommand({
|
|
46356
46941
|
DeliveryStreamName: physicalId,
|
|
46357
46942
|
DeliveryStreamEncryptionConfigurationInput: {
|
|
@@ -46359,7 +46944,7 @@ var FirehoseProvider = class {
|
|
|
46359
46944
|
...desired.keyArn !== void 0 && { KeyARN: desired.keyArn }
|
|
46360
46945
|
}
|
|
46361
46946
|
}));
|
|
46362
|
-
await this.warnIfUnfinished(logicalId, "StartDeliveryStreamEncryption", () => this.waitForEncryption(logicalId, physicalId, resourceType, mask, {
|
|
46947
|
+
await this.warnIfUnfinished(logicalId, "StartDeliveryStreamEncryption", markUnsettled, () => this.waitForEncryption(logicalId, physicalId, resourceType, mask, {
|
|
46363
46948
|
what: "enable",
|
|
46364
46949
|
done: (enc) => encryptionMatches(enc, desired),
|
|
46365
46950
|
inProgress: "ENABLING",
|
|
@@ -46367,12 +46952,12 @@ var FirehoseProvider = class {
|
|
|
46367
46952
|
staleFailure: settled?.Status === "ENABLING_FAILED"
|
|
46368
46953
|
}));
|
|
46369
46954
|
}
|
|
46370
|
-
async warnIfUnfinished(logicalId, call, wait) {
|
|
46955
|
+
async warnIfUnfinished(logicalId, call, markUnsettled, wait) {
|
|
46371
46956
|
try {
|
|
46372
46957
|
return await wait();
|
|
46373
46958
|
} catch (error) {
|
|
46374
46959
|
const outcome = typeof error === "object" && error !== null && terminalEncryptionFailures.has(error) ? "AWS reported the change failed, so the stream may no longer match" : "the stream may still finish the change, so it may no longer match";
|
|
46375
|
-
this.logger.warn(safeMsg`Firehose delivery stream ${logicalId}: ${call} was sent but the encryption change did not finish; ${outcome} the previous setting cdkd keeps recorded. Run 'cdkd drift' to compare, then 'cdkd drift --revert' to apply the recorded setting or 'cdkd drift --accept' to record the stream's.`);
|
|
46960
|
+
this.logger.warn(safeMsg`Firehose delivery stream ${logicalId}: ${call} was sent but the encryption change did not finish; ${outcome} the previous setting cdkd keeps recorded. `.concat(markUnsettled === void 0 ? "Run 'cdkd drift' to compare, then 'cdkd drift --revert' to apply the recorded setting or 'cdkd drift --accept' to record the stream's." : `cdkd records ${ENCRYPTION_KEY} as unsettled, so the next 'cdkd deploy' reads the stream and applies the template's setting. To keep the stream as it ends up instead, run 'cdkd drift --accept' once the stream no longer reads ENABLING or DISABLING (an accept during the transition keeps the key unsettled).`));
|
|
46376
46961
|
throw error;
|
|
46377
46962
|
}
|
|
46378
46963
|
}
|
|
@@ -46790,6 +47375,15 @@ var FirehoseProvider = class {
|
|
|
46790
47375
|
if (config["CloudWatchLoggingOptions"] !== void 0) result.CloudWatchLoggingOptions = config["CloudWatchLoggingOptions"];
|
|
46791
47376
|
return result;
|
|
46792
47377
|
}
|
|
47378
|
+
async unsettledInTransition(physicalId, _logicalId, _resourceType, names) {
|
|
47379
|
+
if (!names.has(ENCRYPTION_KEY)) return /* @__PURE__ */ new Set();
|
|
47380
|
+
try {
|
|
47381
|
+
const status = (await this.getClient().send(new DescribeDeliveryStreamCommand({ DeliveryStreamName: physicalId }))).DeliveryStreamDescription?.DeliveryStreamEncryptionConfiguration?.Status;
|
|
47382
|
+
return status === "ENABLING" || status === "DISABLING" ? /* @__PURE__ */ new Set([ENCRYPTION_KEY]) : /* @__PURE__ */ new Set();
|
|
47383
|
+
} catch {
|
|
47384
|
+
return /* @__PURE__ */ new Set([ENCRYPTION_KEY]);
|
|
47385
|
+
}
|
|
47386
|
+
}
|
|
46793
47387
|
async readCurrentState(physicalId, _logicalId, _resourceType) {
|
|
46794
47388
|
let desc;
|
|
46795
47389
|
try {
|
|
@@ -46846,18 +47440,59 @@ var FirehoseProvider = class {
|
|
|
46846
47440
|
}
|
|
46847
47441
|
return null;
|
|
46848
47442
|
}
|
|
46849
|
-
async waitForActive(streamName, logicalId) {
|
|
46850
|
-
const
|
|
46851
|
-
|
|
46852
|
-
|
|
46853
|
-
|
|
46854
|
-
|
|
46855
|
-
|
|
47443
|
+
async waitForActive(streamName, logicalId, resourceType, mask) {
|
|
47444
|
+
const watch = startInterruptWatch(`Firehose ${logicalId} create`);
|
|
47445
|
+
try {
|
|
47446
|
+
let last;
|
|
47447
|
+
let deadlineNear = false;
|
|
47448
|
+
for (let attempt = 1; attempt <= ACTIVE_POLL_MAX_ATTEMPTS; attempt++) {
|
|
47449
|
+
if (watch.isInterrupted()) throw watch.onInterrupted();
|
|
47450
|
+
if (enclosingDeadlineRemainingMs() <= ACTIVE_DEADLINE_MARGIN_MS) {
|
|
47451
|
+
deadlineNear = true;
|
|
47452
|
+
break;
|
|
47453
|
+
}
|
|
47454
|
+
const resp = await this.describeBeforeDeadline(streamName);
|
|
47455
|
+
if (resp === "deadline") {
|
|
47456
|
+
deadlineNear = true;
|
|
47457
|
+
break;
|
|
47458
|
+
}
|
|
47459
|
+
const description = resp.DeliveryStreamDescription;
|
|
47460
|
+
last = description?.DeliveryStreamStatus;
|
|
47461
|
+
if (last === "ACTIVE") {
|
|
47462
|
+
this.logger.debug(`Firehose ${logicalId} is ACTIVE`);
|
|
47463
|
+
return;
|
|
47464
|
+
}
|
|
47465
|
+
if (last !== void 0 && last.endsWith("_FAILED")) {
|
|
47466
|
+
const failure = description?.FailureDescription;
|
|
47467
|
+
throw markNonRetryable(new ProvisioningError(`Firehose delivery stream ${logicalId} did not become ACTIVE: AWS reports ${last}` + (failure ? ` (${mask(`${failure.Type ?? ""}: ${failure.Details ?? ""}`)})` : ""), resourceType, logicalId, streamName));
|
|
47468
|
+
}
|
|
47469
|
+
this.logger.debug(`Firehose ${logicalId} status: ${last} (attempt ${attempt}/${ACTIVE_POLL_MAX_ATTEMPTS})`);
|
|
47470
|
+
if (watch.isInterrupted()) throw watch.onInterrupted();
|
|
47471
|
+
if (enclosingDeadlineRemainingMs() <= 7e3) {
|
|
47472
|
+
deadlineNear = true;
|
|
47473
|
+
break;
|
|
47474
|
+
}
|
|
47475
|
+
await new Promise((resolve) => setTimeout(resolve, ACTIVE_POLL_INTERVAL_MS));
|
|
46856
47476
|
}
|
|
46857
|
-
|
|
46858
|
-
|
|
47477
|
+
throw markNonRetryable(new ProvisioningError((deadlineNear ? `The resource timeout would expire while waiting for Firehose delivery stream ${logicalId} to become ACTIVE ` : `Timed out waiting for Firehose delivery stream ${logicalId} to become ACTIVE `) + `(last status: ${last ?? "none reported"})`, resourceType, logicalId, streamName));
|
|
47478
|
+
} finally {
|
|
47479
|
+
watch.dispose();
|
|
47480
|
+
}
|
|
47481
|
+
}
|
|
47482
|
+
async describeBeforeDeadline(streamName) {
|
|
47483
|
+
const command = new DescribeDeliveryStreamCommand({ DeliveryStreamName: streamName });
|
|
47484
|
+
const remaining = enclosingDeadlineRemainingMs();
|
|
47485
|
+
if (!Number.isFinite(remaining)) return this.getClient().send(command);
|
|
47486
|
+
const abort = new AbortController();
|
|
47487
|
+
const timer = setTimeout(() => abort.abort(), Math.max(0, remaining - ACTIVE_DEADLINE_MARGIN_MS));
|
|
47488
|
+
try {
|
|
47489
|
+
return await this.getClient().send(command, { abortSignal: abort.signal });
|
|
47490
|
+
} catch (error) {
|
|
47491
|
+
if (abort.signal.aborted) return "deadline";
|
|
47492
|
+
throw error;
|
|
47493
|
+
} finally {
|
|
47494
|
+
clearTimeout(timer);
|
|
46859
47495
|
}
|
|
46860
|
-
this.logger.warn(`Firehose ${logicalId} did not reach ACTIVE after ${maxAttempts} attempts`);
|
|
46861
47496
|
}
|
|
46862
47497
|
};
|
|
46863
47498
|
function pickDefinedDeep(input) {
|
|
@@ -46985,6 +47620,77 @@ function resolveCloudWatchLogsPair(properties) {
|
|
|
46985
47620
|
roleArn: desiredRole
|
|
46986
47621
|
};
|
|
46987
47622
|
}
|
|
47623
|
+
function readListBlock(raw, path) {
|
|
47624
|
+
if (raw == null) return { kind: "absent" };
|
|
47625
|
+
try {
|
|
47626
|
+
return {
|
|
47627
|
+
kind: "list",
|
|
47628
|
+
value: requireConfigArray(raw, path)
|
|
47629
|
+
};
|
|
47630
|
+
} catch (error) {
|
|
47631
|
+
return {
|
|
47632
|
+
kind: "unusable",
|
|
47633
|
+
detail: describeAwsFailure(error).detail
|
|
47634
|
+
};
|
|
47635
|
+
}
|
|
47636
|
+
}
|
|
47637
|
+
function listOf(read) {
|
|
47638
|
+
return read.kind === "list" ? read.value : void 0;
|
|
47639
|
+
}
|
|
47640
|
+
function retainPreviousLists(desired, previous, keys, live) {
|
|
47641
|
+
const out = Object.fromEntries(Object.entries(desired).filter(([key]) => !keys.includes(key)));
|
|
47642
|
+
for (const key of keys) {
|
|
47643
|
+
const prev = previous[key];
|
|
47644
|
+
if (Array.isArray(prev)) out[key] = structuredClone(prev);
|
|
47645
|
+
else if (prev != null && Array.isArray(live?.[key])) out[key] = structuredClone(live[key]);
|
|
47646
|
+
}
|
|
47647
|
+
return out;
|
|
47648
|
+
}
|
|
47649
|
+
const UNORDERED_LIST_BLOCKS = ["AdvancedEventSelectors", "AggregationConfigurations"];
|
|
47650
|
+
function setKey(value) {
|
|
47651
|
+
if (value === void 0) return "undefined";
|
|
47652
|
+
if (Array.isArray(value)) return [
|
|
47653
|
+
"[",
|
|
47654
|
+
value.map(setKey).sort().join(","),
|
|
47655
|
+
"]"
|
|
47656
|
+
].join("");
|
|
47657
|
+
if (value !== null && typeof value === "object") {
|
|
47658
|
+
const bag = value;
|
|
47659
|
+
return [
|
|
47660
|
+
"{",
|
|
47661
|
+
Object.keys(bag).filter((k) => bag[k] !== void 0).sort().map((k) => [JSON.stringify(k), setKey(bag[k])].join(":")).join(","),
|
|
47662
|
+
"}"
|
|
47663
|
+
].join("");
|
|
47664
|
+
}
|
|
47665
|
+
return JSON.stringify(value) ?? "null";
|
|
47666
|
+
}
|
|
47667
|
+
function nonEmptyListOf(read) {
|
|
47668
|
+
return read.kind === "list" && read.value.length > 0 ? read.value : void 0;
|
|
47669
|
+
}
|
|
47670
|
+
function eventSelectorRequest(basic, advanced) {
|
|
47671
|
+
const hasBasic = basic !== void 0 && basic.length > 0;
|
|
47672
|
+
if (advanced !== void 0 && advanced.length > 0) return {
|
|
47673
|
+
members: {
|
|
47674
|
+
AdvancedEventSelectors: advanced,
|
|
47675
|
+
...hasBasic ? { EventSelectors: basic } : {}
|
|
47676
|
+
},
|
|
47677
|
+
isReset: false
|
|
47678
|
+
};
|
|
47679
|
+
if (hasBasic) return {
|
|
47680
|
+
members: { EventSelectors: basic },
|
|
47681
|
+
isReset: false
|
|
47682
|
+
};
|
|
47683
|
+
return {
|
|
47684
|
+
members: { EventSelectors: [...DEFAULT_EVENT_SELECTORS] },
|
|
47685
|
+
isReset: true
|
|
47686
|
+
};
|
|
47687
|
+
}
|
|
47688
|
+
function advancedSelectorsToCfn(selectors) {
|
|
47689
|
+
return selectors.map((s) => ({
|
|
47690
|
+
...s.Name !== void 0 && { Name: s.Name },
|
|
47691
|
+
FieldSelectors: (s.FieldSelectors ?? []).map((f) => Object.fromEntries(Object.entries(f).filter(([, v]) => v !== void 0)))
|
|
47692
|
+
}));
|
|
47693
|
+
}
|
|
46988
47694
|
function describeValue(value) {
|
|
46989
47695
|
if (value === null) return "null";
|
|
46990
47696
|
if (value === void 0) return "nothing";
|
|
@@ -47034,7 +47740,9 @@ var CloudTrailProvider = class {
|
|
|
47034
47740
|
"SnsTopicName",
|
|
47035
47741
|
"EventSelectors",
|
|
47036
47742
|
"InsightSelectors",
|
|
47037
|
-
"IsOrganizationTrail"
|
|
47743
|
+
"IsOrganizationTrail",
|
|
47744
|
+
"AdvancedEventSelectors",
|
|
47745
|
+
"AggregationConfigurations"
|
|
47038
47746
|
])]]);
|
|
47039
47747
|
getClient() {
|
|
47040
47748
|
if (!this.client) {
|
|
@@ -47071,6 +47779,9 @@ var CloudTrailProvider = class {
|
|
|
47071
47779
|
const isOrganizationTrail = properties["IsOrganizationTrail"];
|
|
47072
47780
|
const eventSelectors = properties["EventSelectors"];
|
|
47073
47781
|
const insightSelectors = properties["InsightSelectors"];
|
|
47782
|
+
const advancedEventSelectors = properties["AdvancedEventSelectors"] == null ? void 0 : requireConfigArray(properties["AdvancedEventSelectors"], "AWS::CloudTrail::Trail AdvancedEventSelectors", replayWarn(this.logger, context));
|
|
47783
|
+
const aggregationConfigurations = properties["AggregationConfigurations"] == null ? void 0 : requireConfigArray(properties["AggregationConfigurations"], "AWS::CloudTrail::Trail AggregationConfigurations", replayWarn(this.logger, context));
|
|
47784
|
+
const skippedOnReplay = [...properties["AdvancedEventSelectors"] != null && advancedEventSelectors === void 0 ? ["AdvancedEventSelectors"] : [], ...properties["AggregationConfigurations"] != null && aggregationConfigurations === void 0 ? ["AggregationConfigurations"] : []];
|
|
47074
47785
|
let trailCreated = false;
|
|
47075
47786
|
let createdTrailArn;
|
|
47076
47787
|
try {
|
|
@@ -47094,11 +47805,19 @@ var CloudTrailProvider = class {
|
|
|
47094
47805
|
trailCreated = true;
|
|
47095
47806
|
const trailArn = result.TrailARN;
|
|
47096
47807
|
createdTrailArn = result.TrailARN;
|
|
47097
|
-
|
|
47808
|
+
const basicForCreate = eventSelectors && eventSelectors.length > 0 ? eventSelectors : void 0;
|
|
47809
|
+
if (basicForCreate || advancedEventSelectors && advancedEventSelectors.length > 0) {
|
|
47098
47810
|
this.logger.debug(`Setting event selectors for CloudTrail Trail ${logicalId}`);
|
|
47099
47811
|
await this.getClient().send(new PutEventSelectorsCommand({
|
|
47100
47812
|
TrailName: trailArn,
|
|
47101
|
-
|
|
47813
|
+
...eventSelectorRequest(basicForCreate, advancedEventSelectors).members
|
|
47814
|
+
}));
|
|
47815
|
+
}
|
|
47816
|
+
if (aggregationConfigurations && aggregationConfigurations.length > 0) {
|
|
47817
|
+
this.logger.debug(safeMsg`Setting aggregation configurations for CloudTrail Trail ${logicalId}`);
|
|
47818
|
+
await this.getClient().send(new PutEventConfigurationCommand({
|
|
47819
|
+
TrailName: trailArn,
|
|
47820
|
+
AggregationConfigurations: aggregationConfigurations
|
|
47102
47821
|
}));
|
|
47103
47822
|
}
|
|
47104
47823
|
if (insightSelectors && insightSelectors.length > 0) {
|
|
@@ -47115,7 +47834,8 @@ var CloudTrailProvider = class {
|
|
|
47115
47834
|
this.logger.debug(`Successfully created CloudTrail Trail ${logicalId}: ${trailArn}`);
|
|
47116
47835
|
return {
|
|
47117
47836
|
physicalId: trailArn,
|
|
47118
|
-
attributes: { Arn: trailArn }
|
|
47837
|
+
attributes: { Arn: trailArn },
|
|
47838
|
+
...skippedOnReplay.length > 0 && { effectiveProperties: retainPreviousLists(properties, {}, skippedOnReplay) }
|
|
47119
47839
|
};
|
|
47120
47840
|
} catch (error) {
|
|
47121
47841
|
if (trailCreated) markAuxiliaryFailure(error, logicalId);
|
|
@@ -47126,6 +47846,7 @@ var CloudTrailProvider = class {
|
|
|
47126
47846
|
}
|
|
47127
47847
|
}
|
|
47128
47848
|
async update(logicalId, physicalId, resourceType, properties, previousProperties, context) {
|
|
47849
|
+
const desiredProperties = properties;
|
|
47129
47850
|
properties = withRemovalDefaults(this.removalDefaults, resourceType, properties, previousProperties, context);
|
|
47130
47851
|
this.logger.debug(`Updating CloudTrail Trail ${logicalId}: ${physicalId}`);
|
|
47131
47852
|
refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId);
|
|
@@ -47142,6 +47863,7 @@ var CloudTrailProvider = class {
|
|
|
47142
47863
|
const kmsKeyId = clearOnUpdateRemoval(emptyToUndefined(properties["KMSKeyId"]), emptyToUndefined(previousProperties["KMSKeyId"]), "");
|
|
47143
47864
|
const snsTopicName = clearOnUpdateRemoval(emptyToUndefined(properties["SnsTopicName"]), emptyToUndefined(previousProperties["SnsTopicName"]), "");
|
|
47144
47865
|
const isOrganizationTrail = properties["IsOrganizationTrail"];
|
|
47866
|
+
const appliedBeforeFailure = [];
|
|
47145
47867
|
try {
|
|
47146
47868
|
await this.getClient().send(new UpdateTrailCommand({
|
|
47147
47869
|
Name: physicalId,
|
|
@@ -47156,36 +47878,61 @@ var CloudTrailProvider = class {
|
|
|
47156
47878
|
SnsTopicName: snsTopicName,
|
|
47157
47879
|
IsOrganizationTrail: isOrganizationTrail
|
|
47158
47880
|
}));
|
|
47159
|
-
const
|
|
47160
|
-
|
|
47161
|
-
|
|
47162
|
-
|
|
47163
|
-
|
|
47164
|
-
|
|
47165
|
-
eventSelectorsUnusable = true;
|
|
47166
|
-
this.logger.warn(`${describeAwsFailure(error).detail} The trail's existing event selectors are left untouched for this update rather than reset to the AWS default.`);
|
|
47167
|
-
}
|
|
47881
|
+
const basicRead = readListBlock(properties["EventSelectors"], "AWS::CloudTrail::Trail EventSelectors");
|
|
47882
|
+
const advancedRead = readListBlock(properties["AdvancedEventSelectors"], "AWS::CloudTrail::Trail AdvancedEventSelectors");
|
|
47883
|
+
for (const read of [basicRead, advancedRead]) if (read.kind === "unusable") this.logger.warn(safeMsg`${read.detail} The trail's existing event selectors are left untouched for this update rather than reset to the AWS default.`);
|
|
47884
|
+
const selectorsUnusable = basicRead.kind === "unusable" || advancedRead.kind === "unusable";
|
|
47885
|
+
const newEventSelectors = listOf(basicRead);
|
|
47886
|
+
const newAdvancedSelectors = listOf(advancedRead);
|
|
47168
47887
|
const oldEventSelectors = previousProperties["EventSelectors"];
|
|
47169
|
-
|
|
47170
|
-
|
|
47171
|
-
|
|
47888
|
+
const oldAdvancedSelectors = previousProperties["AdvancedEventSelectors"];
|
|
47889
|
+
const hadAdvancedSelectors = Array.isArray(oldAdvancedSelectors) && oldAdvancedSelectors.length > 0;
|
|
47890
|
+
const aggregationRead = readListBlock(properties["AggregationConfigurations"], "AWS::CloudTrail::Trail AggregationConfigurations");
|
|
47891
|
+
if (aggregationRead.kind === "unusable") this.logger.warn(safeMsg`${aggregationRead.detail} The trail's existing aggregation configurations are left untouched for this update rather than cleared.`);
|
|
47892
|
+
const newAggregation = listOf(aggregationRead);
|
|
47893
|
+
const aggregationChanged = aggregationRead.kind !== "unusable" && setKey(newAggregation) !== setKey(previousProperties["AggregationConfigurations"]);
|
|
47894
|
+
const aggregationCleared = aggregationChanged && nonEmptyListOf(aggregationRead) === void 0;
|
|
47895
|
+
const putAggregation = async () => {
|
|
47896
|
+
this.logger.debug(safeMsg`Updating aggregation configurations for CloudTrail Trail ${logicalId}`);
|
|
47897
|
+
await this.getClient().send(new PutEventConfigurationCommand({
|
|
47898
|
+
TrailName: physicalId,
|
|
47899
|
+
AggregationConfigurations: newAggregation ?? []
|
|
47900
|
+
}));
|
|
47901
|
+
};
|
|
47902
|
+
if (aggregationCleared) {
|
|
47903
|
+
await putAggregation();
|
|
47904
|
+
appliedBeforeFailure.push("AggregationConfigurations was cleared");
|
|
47905
|
+
}
|
|
47906
|
+
if (!selectorsUnusable && (JSON.stringify(newEventSelectors) !== JSON.stringify(oldEventSelectors) || setKey(newAdvancedSelectors) !== setKey(oldAdvancedSelectors))) {
|
|
47907
|
+
let basicToSend = newEventSelectors;
|
|
47908
|
+
let advancedToSend = newAdvancedSelectors;
|
|
47909
|
+
if (context?.desiredFromAwsReadback === true && nonEmptyListOf(basicRead) !== void 0 && nonEmptyListOf(advancedRead) !== void 0) {
|
|
47910
|
+
if (JSON.stringify(newEventSelectors) === JSON.stringify(oldEventSelectors)) basicToSend = void 0;
|
|
47911
|
+
else if (setKey(newAdvancedSelectors) === setKey(oldAdvancedSelectors)) advancedToSend = void 0;
|
|
47912
|
+
}
|
|
47913
|
+
const { members, isReset: isRemoval } = eventSelectorRequest(basicToSend, advancedToSend);
|
|
47172
47914
|
this.logger.debug(isRemoval ? `Resetting event selectors to the AWS default for CloudTrail Trail ${logicalId}` : `Updating event selectors for CloudTrail Trail ${logicalId}`);
|
|
47173
47915
|
try {
|
|
47174
47916
|
await this.getClient().send(new PutEventSelectorsCommand({
|
|
47175
47917
|
TrailName: physicalId,
|
|
47176
|
-
|
|
47918
|
+
...members
|
|
47177
47919
|
}));
|
|
47920
|
+
appliedBeforeFailure.push("the event selectors were updated");
|
|
47178
47921
|
} catch (error) {
|
|
47179
47922
|
const failure = describeAwsFailure(error);
|
|
47180
47923
|
const message = withoutTrailIdentifiers(failure.detail, physicalId);
|
|
47181
47924
|
const errorClass = error instanceof Error ? error.name : "";
|
|
47182
|
-
if (!isRemoval || ACCESS_DENIAL_CLASS.test(errorClass) || !ADVANCED_SELECTOR_PHRASE.test(message)) throw error;
|
|
47925
|
+
if (!isRemoval || hadAdvancedSelectors || ACCESS_DENIAL_CLASS.test(errorClass) || !ADVANCED_SELECTOR_PHRASE.test(message)) throw error;
|
|
47183
47926
|
const m = maskerOrIdentity(context?.maskSecrets);
|
|
47184
47927
|
const head = `CloudTrail Trail ${logicalId}: skipping the EventSelectors reset — the trail is using AdvancedEventSelectors, which AWS manages through a separate API, so there are no basic event selectors to clear (`;
|
|
47185
47928
|
if (failure.redacted) this.logger.debug(m(`${head}${m(failure.detail)})`));
|
|
47186
47929
|
this.logger.warn(m(`${head}${failure.redacted ? failure.summary : failure.detail})`));
|
|
47187
47930
|
}
|
|
47188
47931
|
}
|
|
47932
|
+
if (aggregationChanged && !aggregationCleared) {
|
|
47933
|
+
await putAggregation();
|
|
47934
|
+
appliedBeforeFailure.push("AggregationConfigurations was updated");
|
|
47935
|
+
}
|
|
47189
47936
|
const newInsightSelectors = properties["InsightSelectors"];
|
|
47190
47937
|
const oldInsightSelectors = previousProperties["InsightSelectors"];
|
|
47191
47938
|
if (JSON.stringify(newInsightSelectors) !== JSON.stringify(oldInsightSelectors)) {
|
|
@@ -47207,13 +47954,19 @@ var CloudTrailProvider = class {
|
|
|
47207
47954
|
}
|
|
47208
47955
|
await this.applyTagDiff(physicalId, resourceType, logicalId, previousProperties["Tags"], properties["Tags"]);
|
|
47209
47956
|
this.logger.debug(`Successfully updated CloudTrail Trail ${logicalId}`);
|
|
47210
|
-
|
|
47957
|
+
const skipped = [...selectorsUnusable ? ["EventSelectors", "AdvancedEventSelectors"] : [], ...aggregationRead.kind === "unusable" ? ["AggregationConfigurations"] : []];
|
|
47958
|
+
if (skipped.length === 0) return {
|
|
47211
47959
|
physicalId,
|
|
47212
47960
|
wasReplaced: false
|
|
47213
47961
|
};
|
|
47962
|
+
return {
|
|
47963
|
+
physicalId,
|
|
47964
|
+
wasReplaced: false,
|
|
47965
|
+
effectiveProperties: retainPreviousLists(desiredProperties, previousProperties, skipped, skipped.some((key) => previousProperties[key] != null && !Array.isArray(previousProperties[key])) ? await this.readLiveForRecord(physicalId, resourceType) : void 0)
|
|
47966
|
+
};
|
|
47214
47967
|
} catch (error) {
|
|
47215
47968
|
const cause = error instanceof Error ? error : void 0;
|
|
47216
|
-
throw this.wrapCaughtError(context?.maskSecrets, error, (text) => new ProvisioningError(`Failed to update CloudTrail Trail ${logicalId}: ${text}
|
|
47969
|
+
throw this.wrapCaughtError(context?.maskSecrets, error, (text) => new ProvisioningError(`Failed to update CloudTrail Trail ${logicalId}: ${text}` + (appliedBeforeFailure.length > 0 ? ` (selector/aggregation writes already applied before this failure: ${appliedBeforeFailure.join("; ")})` : ""), resourceType, logicalId, physicalId, cause));
|
|
47217
47970
|
}
|
|
47218
47971
|
}
|
|
47219
47972
|
async delete(logicalId, physicalId, resourceType, properties, context) {
|
|
@@ -47243,6 +47996,19 @@ var CloudTrailProvider = class {
|
|
|
47243
47996
|
throw stripped ? markDeleteStarted(notGone) : notGone;
|
|
47244
47997
|
}
|
|
47245
47998
|
}
|
|
47999
|
+
async readLiveForRecord(physicalId, resourceType) {
|
|
48000
|
+
try {
|
|
48001
|
+
const live = await this.readCurrentState(physicalId, "", resourceType);
|
|
48002
|
+
return live !== void 0 && live !== RESOURCE_NOT_FOUND ? live : void 0;
|
|
48003
|
+
} catch (error) {
|
|
48004
|
+
this.logger.debug(safeMsg`CloudTrail read-back for the record failed: ${describeAwsFailure(error).detail}`);
|
|
48005
|
+
return;
|
|
48006
|
+
}
|
|
48007
|
+
}
|
|
48008
|
+
getDriftUnorderedPaths(resourceType) {
|
|
48009
|
+
if (resourceType !== "AWS::CloudTrail::Trail") return [];
|
|
48010
|
+
return [...UNORDERED_LIST_BLOCKS];
|
|
48011
|
+
}
|
|
47246
48012
|
getAttribute(_physicalId, _resourceType, attributeName) {
|
|
47247
48013
|
return Promise.resolve(attributeName);
|
|
47248
48014
|
}
|
|
@@ -47301,7 +48067,9 @@ var CloudTrailProvider = class {
|
|
|
47301
48067
|
} catch {}
|
|
47302
48068
|
try {
|
|
47303
48069
|
const sel = await this.getClient().send(new GetEventSelectorsCommand({ TrailName: physicalId }));
|
|
47304
|
-
|
|
48070
|
+
const hasAdvanced = Array.isArray(sel.AdvancedEventSelectors) && sel.AdvancedEventSelectors.length > 0;
|
|
48071
|
+
if (!hasAdvanced) result["EventSelectors"] = (sel.EventSelectors ?? []).map((es) => es);
|
|
48072
|
+
result["AdvancedEventSelectors"] = hasAdvanced ? advancedSelectorsToCfn(sel.AdvancedEventSelectors ?? []) : [];
|
|
47305
48073
|
} catch {}
|
|
47306
48074
|
let insightSelectors = [];
|
|
47307
48075
|
try {
|
|
@@ -47316,6 +48084,14 @@ var CloudTrailProvider = class {
|
|
|
47316
48084
|
this.logger.debug(`CloudTrail ListTags(${trail.TrailARN}) failed: ${describeAwsFailure(err).detail}`);
|
|
47317
48085
|
}
|
|
47318
48086
|
result["Tags"] = tags;
|
|
48087
|
+
try {
|
|
48088
|
+
result["AggregationConfigurations"] = ((await this.getClient().send(new GetEventConfigurationCommand({ TrailName: physicalId }))).AggregationConfigurations ?? []).map((a) => ({
|
|
48089
|
+
...a.EventCategory !== void 0 && { EventCategory: a.EventCategory },
|
|
48090
|
+
...a.Templates !== void 0 && { Templates: a.Templates }
|
|
48091
|
+
}));
|
|
48092
|
+
} catch (err) {
|
|
48093
|
+
this.logger.debug(safeMsg`CloudTrail GetEventConfiguration(${physicalId}) failed: ${describeAwsFailure(err).detail}`);
|
|
48094
|
+
}
|
|
47319
48095
|
return result;
|
|
47320
48096
|
}
|
|
47321
48097
|
async import(input) {
|
|
@@ -48105,11 +48881,11 @@ var CodeCommitRepositoryProvider = class {
|
|
|
48105
48881
|
const repoArn = metadata?.Arn;
|
|
48106
48882
|
if (repoArn) {
|
|
48107
48883
|
const removedKeys = Object.keys(oldTagMap).filter((k) => !Object.hasOwn(newTagMap, k));
|
|
48108
|
-
if (removedKeys.length > 0) await this.getClient().send(new UntagResourceCommand$
|
|
48884
|
+
if (removedKeys.length > 0) await this.getClient().send(new UntagResourceCommand$26({
|
|
48109
48885
|
resourceArn: repoArn,
|
|
48110
48886
|
tagKeys: removedKeys
|
|
48111
48887
|
}));
|
|
48112
|
-
if (Object.keys(newTagMap).length > 0) await this.getClient().send(new TagResourceCommand$
|
|
48888
|
+
if (Object.keys(newTagMap).length > 0) await this.getClient().send(new TagResourceCommand$25({
|
|
48113
48889
|
resourceArn: repoArn,
|
|
48114
48890
|
tags: newTagMap
|
|
48115
48891
|
}));
|
|
@@ -48552,7 +49328,7 @@ var DLMLifecyclePolicyProvider = class {
|
|
|
48552
49328
|
if (tagsChanged && arn) {
|
|
48553
49329
|
const removedKeys = plan.remove;
|
|
48554
49330
|
if (removedKeys.length > 0) {
|
|
48555
|
-
await this.getClient().send(new UntagResourceCommand$
|
|
49331
|
+
await this.getClient().send(new UntagResourceCommand$27({
|
|
48556
49332
|
ResourceArn: arn,
|
|
48557
49333
|
TagKeys: removedKeys
|
|
48558
49334
|
}));
|
|
@@ -48560,7 +49336,7 @@ var DLMLifecyclePolicyProvider = class {
|
|
|
48560
49336
|
}
|
|
48561
49337
|
const tagsToAdd = Object.fromEntries(plan.set);
|
|
48562
49338
|
if (Object.keys(tagsToAdd).length > 0) {
|
|
48563
|
-
await this.getClient().send(new TagResourceCommand$
|
|
49339
|
+
await this.getClient().send(new TagResourceCommand$26({
|
|
48564
49340
|
ResourceArn: arn,
|
|
48565
49341
|
Tags: tagsToAdd
|
|
48566
49342
|
}));
|
|
@@ -48724,11 +49500,11 @@ var S3VectorsProvider = class {
|
|
|
48724
49500
|
}
|
|
48725
49501
|
if (!resourceArn) throw new ProvisioningError(`Could not resolve ARN for S3 VectorBucket ${logicalId} (${mask(physicalId)}); cannot apply tag update.`, resourceType, logicalId, physicalId);
|
|
48726
49502
|
try {
|
|
48727
|
-
if (Object.keys(toSet).length > 0) await this.getClient().send(new TagResourceCommand$
|
|
49503
|
+
if (Object.keys(toSet).length > 0) await this.getClient().send(new TagResourceCommand$27({
|
|
48728
49504
|
resourceArn,
|
|
48729
49505
|
tags: toSet
|
|
48730
49506
|
}));
|
|
48731
|
-
if (toRemove.length > 0) await this.getClient().send(new UntagResourceCommand$
|
|
49507
|
+
if (toRemove.length > 0) await this.getClient().send(new UntagResourceCommand$28({
|
|
48732
49508
|
resourceArn,
|
|
48733
49509
|
tagKeys: toRemove
|
|
48734
49510
|
}));
|
|
@@ -49011,12 +49787,12 @@ var S3DirectoryBucketProvider = class {
|
|
|
49011
49787
|
if (removedKeys.length > 0 || tagsToApply.length > 0) {
|
|
49012
49788
|
const accountId = await this.getAccountId();
|
|
49013
49789
|
const resourceArn = await this.buildBucketArn(physicalId, accountId);
|
|
49014
|
-
if (removedKeys.length > 0) await this.getS3ControlClient().send(new UntagResourceCommand$
|
|
49790
|
+
if (removedKeys.length > 0) await this.getS3ControlClient().send(new UntagResourceCommand$29({
|
|
49015
49791
|
AccountId: accountId,
|
|
49016
49792
|
ResourceArn: resourceArn,
|
|
49017
49793
|
TagKeys: removedKeys
|
|
49018
49794
|
}));
|
|
49019
|
-
if (tagsToApply.length > 0) await this.getS3ControlClient().send(new TagResourceCommand$
|
|
49795
|
+
if (tagsToApply.length > 0) await this.getS3ControlClient().send(new TagResourceCommand$28({
|
|
49020
49796
|
AccountId: accountId,
|
|
49021
49797
|
ResourceArn: resourceArn,
|
|
49022
49798
|
Tags: tagsToApply
|
|
@@ -49864,7 +50640,7 @@ var S3TablesProvider = class {
|
|
|
49864
50640
|
const resourceArn = await this.lookupTableArn(tableBucketARN, namespace, name);
|
|
49865
50641
|
if (!resourceArn) throw new ProvisioningError(safeMsg`applyTableTagsDiff: GetTable returned no tableARN for ${physicalId} — table is gone ` + `or state is out-of-sync. Refusing to silently drop the tag update. If the table was deleted out-of-band, drop just this resource's record with the command below, filling in the construct path the CDK app gave this resource — its aws:cdk:path Metadata entry in the synthesized template.\nClean up with: cdkd orphan ${commandHole("constructPath")}`, resourceType, logicalId, physicalId);
|
|
49866
50642
|
if (removedKeys.length > 0) try {
|
|
49867
|
-
await this.getClient().send(new UntagResourceCommand$
|
|
50643
|
+
await this.getClient().send(new UntagResourceCommand$30({
|
|
49868
50644
|
resourceArn,
|
|
49869
50645
|
tagKeys: removedKeys
|
|
49870
50646
|
}));
|
|
@@ -49873,7 +50649,7 @@ var S3TablesProvider = class {
|
|
|
49873
50649
|
throw this.wrapCaughtError(mask, err, (text) => new ProvisioningError(`applyTableTagsDiff: UntagResource failed for ${resourceArn} (keys: ${removedKeys.join(", ")}): ${sentence(text)} State has NOT been updated so the next deploy will retry the tag-diff.`, resourceType, logicalId, physicalId, cause));
|
|
49874
50650
|
}
|
|
49875
50651
|
if (Object.keys(upserts).length > 0) try {
|
|
49876
|
-
await this.getClient().send(new TagResourceCommand$
|
|
50652
|
+
await this.getClient().send(new TagResourceCommand$29({
|
|
49877
50653
|
resourceArn,
|
|
49878
50654
|
tags: upserts
|
|
49879
50655
|
}));
|
|
@@ -49891,7 +50667,7 @@ var S3TablesProvider = class {
|
|
|
49891
50667
|
if (removedKeys.length === 0 && Object.keys(upserts).length === 0) return;
|
|
49892
50668
|
const resourceArn = physicalId;
|
|
49893
50669
|
if (removedKeys.length > 0) try {
|
|
49894
|
-
await this.getClient().send(new UntagResourceCommand$
|
|
50670
|
+
await this.getClient().send(new UntagResourceCommand$30({
|
|
49895
50671
|
resourceArn,
|
|
49896
50672
|
tagKeys: removedKeys
|
|
49897
50673
|
}));
|
|
@@ -49900,7 +50676,7 @@ var S3TablesProvider = class {
|
|
|
49900
50676
|
throw this.wrapCaughtError(mask, err, (text) => new ProvisioningError(`applyTableBucketTagsDiff: UntagResource failed for ${resourceArn} (keys: ${removedKeys.join(", ")}): ${sentence(text)} State has NOT been updated so the next deploy will retry the tag-diff.`, resourceType, logicalId, physicalId, cause));
|
|
49901
50677
|
}
|
|
49902
50678
|
if (Object.keys(upserts).length > 0) try {
|
|
49903
|
-
await this.getClient().send(new TagResourceCommand$
|
|
50679
|
+
await this.getClient().send(new TagResourceCommand$29({
|
|
49904
50680
|
resourceArn,
|
|
49905
50681
|
tags: upserts
|
|
49906
50682
|
}));
|
|
@@ -51020,4 +51796,4 @@ var ACMCertificateProvider = class {
|
|
|
51020
51796
|
|
|
51021
51797
|
//#endregion
|
|
51022
51798
|
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 };
|
|
51023
|
-
//# sourceMappingURL=provider-classes-
|
|
51799
|
+
//# sourceMappingURL=provider-classes-KsrvwO_r.js.map
|