@go-to-k/cdkd 0.308.0 → 0.309.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-CsRMe_zh.js → asg-provider-DQoKGfKH.js} +3 -3
- package/dist/{asg-provider-CsRMe_zh.js.map → asg-provider-DQoKGfKH.js.map} +1 -1
- package/dist/cli.js +2 -2
- package/dist/{db-instance-modify-retry-DOJPkECL.js → db-instance-modify-retry-BUG7NMWS.js} +3 -3
- package/dist/{db-instance-modify-retry-DOJPkECL.js.map → db-instance-modify-retry-BUG7NMWS.js.map} +1 -1
- package/dist/{deploy-engine-DSpxEUjC.js → deploy-engine-tQ0aqZMo.js} +1418 -281
- package/dist/deploy-engine-tQ0aqZMo.js.map +1 -0
- package/dist/{iam-policy-targets-TFGunWmV.js → iam-policy-targets-D94wh05t.js} +5 -2
- package/dist/{iam-policy-targets-TFGunWmV.js.map → iam-policy-targets-D94wh05t.js.map} +1 -1
- package/dist/{iam-role-provider--eWrOXce.js → iam-role-provider-BI8Acvps.js} +3 -3
- package/dist/{iam-role-provider--eWrOXce.js.map → iam-role-provider-BI8Acvps.js.map} +1 -1
- package/dist/index.d.ts +15 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/{neptune-provider-p59T8CFv.js → neptune-provider-DmVmx69p.js} +11 -9
- package/dist/neptune-provider-DmVmx69p.js.map +1 -0
- package/dist/{program-DOPic-aS.js → program-Bnt3Yt0k.js} +121 -260
- package/dist/program-Bnt3Yt0k.js.map +1 -0
- package/dist/{provider-classes-d9K3vBVh.js → provider-classes-DYke4HKr.js} +1210 -194
- package/dist/provider-classes-DYke4HKr.js.map +1 -0
- package/dist/{rds-provider-BPs9JSk_.js → rds-provider-Qpf09VQv.js} +49 -20
- package/dist/rds-provider-Qpf09VQv.js.map +1 -0
- package/dist/{version-DzajQDkv.js → version-9LVuCtBU.js} +2 -2
- package/dist/{version-DzajQDkv.js.map → version-9LVuCtBU.js.map} +1 -1
- package/package.json +2 -2
- package/dist/deploy-engine-DSpxEUjC.js.map +0 -1
- package/dist/neptune-provider-p59T8CFv.js.map +0 -1
- package/dist/program-DOPic-aS.js.map +0 -1
- package/dist/provider-classes-d9K3vBVh.js.map +0 -1
- package/dist/rds-provider-BPs9JSk_.js.map +0 -1
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { r as getAwsClients, s as withApiGatewayPacing } from "./aws-clients-Bu9EMILF.js";
|
|
2
2
|
import { B as SECRET_REF_MAX_CODE_POINTS, C as generateResourceName, D as getCurrentStackInstanceId, J as displayStackName, K as displayIdent, M as recordedGeneratedNameKept, Q as safeMsg, T as generatedNameFor, Y as isPasteableIdent, Z as plainIdentOr, a as safeStringify, i as isAwsAuthoredFailure, k as isBeforeStateRead, n as describeAwsFailure, q as displaySafe, r as describeAwsStatusReason, s as getLogger, t as VERBOSE_POINTER, w as generateResourceNameWithFallback } from "./aws-failure-text-NSBdKPYK.js";
|
|
3
|
-
import { $ as 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
|
|
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-
|
|
8
|
-
import { t as modifyDbInstanceWhenAvailable } from "./db-instance-modify-retry-
|
|
9
|
-
import { RDSProvider } from "./rds-provider-
|
|
10
|
-
import { NeptuneProvider } from "./neptune-provider-
|
|
11
|
-
import { ASGProvider } from "./asg-provider-
|
|
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-tQ0aqZMo.js";
|
|
6
|
+
import { n as collectInlinePolicyNamesManagedBySiblings, r as IamCreateClientCache, t as IAMRoleProvider } from "./iam-role-provider-BI8Acvps.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-Bnt3Yt0k.js";
|
|
8
|
+
import { t as modifyDbInstanceWhenAvailable } from "./db-instance-modify-retry-BUG7NMWS.js";
|
|
9
|
+
import { RDSProvider } from "./rds-provider-Qpf09VQv.js";
|
|
10
|
+
import { NeptuneProvider } from "./neptune-provider-DmVmx69p.js";
|
|
11
|
+
import { ASGProvider } from "./asg-provider-DQoKGfKH.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";
|
|
@@ -16,7 +16,7 @@ import { CreateQueueCommand, DeleteQueueCommand, GetQueueAttributesCommand, GetQ
|
|
|
16
16
|
import { CreateTopicCommand, DeleteTopicCommand, GetSubscriptionAttributesCommand, GetTopicAttributesCommand, InvalidParameterException, ListSubscriptionsByTopicCommand, ListTagsForResourceCommand, ListTopicsCommand, NotFoundException, SNSClient, SetSubscriptionAttributesCommand, SetTopicAttributesCommand, SubscribeCommand, TagResourceCommand, UnsubscribeCommand, UntagResourceCommand } from "@aws-sdk/client-sns";
|
|
17
17
|
import { AddPermissionCommand, CreateEventSourceMappingCommand, CreateFunctionCommand, CreateFunctionUrlConfigCommand, DeleteEventSourceMappingCommand, DeleteFunctionCodeSigningConfigCommand, DeleteFunctionCommand, DeleteFunctionConcurrencyCommand, DeleteFunctionEventInvokeConfigCommand, DeleteFunctionUrlConfigCommand, DeleteLayerVersionCommand, GetEventSourceMappingCommand, GetFunctionCodeSigningConfigCommand, GetFunctionCommand, GetFunctionConcurrencyCommand, GetFunctionEventInvokeConfigCommand, GetFunctionRecursionConfigCommand, GetFunctionUrlConfigCommand, GetLayerVersionByArnCommand, GetPolicyCommand as GetPolicyCommand$1, GetRuntimeManagementConfigCommand, LambdaClient, ListEventSourceMappingsCommand, ListLayerVersionsCommand, ListTagsCommand, PublishLayerVersionCommand, PutFunctionCodeSigningConfigCommand, PutFunctionConcurrencyCommand, PutFunctionEventInvokeConfigCommand, PutFunctionRecursionConfigCommand, PutRuntimeManagementConfigCommand, RemovePermissionCommand, ResourceNotFoundException, TagResourceCommand as TagResourceCommand$1, UntagResourceCommand as UntagResourceCommand$1, UpdateEventSourceMappingCommand, UpdateFunctionCodeCommand, UpdateFunctionConfigurationCommand, UpdateFunctionUrlConfigCommand, waitUntilFunctionActiveV2, waitUntilFunctionUpdatedV2 } from "@aws-sdk/client-lambda";
|
|
18
18
|
import { GetCallerIdentityCommand, STSClient } from "@aws-sdk/client-sts";
|
|
19
|
-
import { AllocateAddressCommand, AssociateAddressCommand, AssociateIamInstanceProfileCommand, AssociateNatGatewayAddressCommand, AssociateRouteTableCommand, AttachInternetGatewayCommand, AttachVpnGatewayCommand, AuthorizeSecurityGroupEgressCommand, AuthorizeSecurityGroupIngressCommand, CreateInternetGatewayCommand, CreateNatGatewayCommand, CreateNetworkAclCommand, CreateNetworkAclEntryCommand, CreateRouteCommand, CreateRouteTableCommand, CreateSecurityGroupCommand, CreateSubnetCommand, CreateTagsCommand, CreateVpcCommand, DeleteInternetGatewayCommand, DeleteNatGatewayCommand, DeleteNetworkAclCommand, DeleteNetworkAclEntryCommand, DeleteNetworkInterfaceCommand, DeleteRouteCommand, DeleteRouteTableCommand, DeleteSecurityGroupCommand, DeleteSubnetCommand, DeleteTagsCommand, DeleteVpcCommand, DescribeAddressesCommand, DescribeAvailabilityZonesCommand, DescribeIamInstanceProfileAssociationsCommand, DescribeInstanceAttributeCommand, DescribeInstanceCreditSpecificationsCommand, DescribeInstancesCommand, DescribeInternetGatewaysCommand, DescribeNatGatewaysCommand, DescribeNetworkAclsCommand, DescribeNetworkInterfacesCommand, DescribeRouteTablesCommand, DescribeSecurityGroupRulesCommand, DescribeSecurityGroupsCommand, DescribeSubnetsCommand, DescribeVolumesCommand, DescribeVpcAttributeCommand, DescribeVpcsCommand, DescribeVpnGatewaysCommand, DetachInternetGatewayCommand, DetachVpnGatewayCommand, DisassociateAddressCommand, DisassociateNatGatewayAddressCommand, DisassociateRouteTableCommand, EC2Client, ModifyInstanceAttributeCommand, ModifyInstanceCreditSpecificationCommand, ModifyInstanceMetadataOptionsCommand, ModifySubnetAttributeCommand, ModifyVpcAttributeCommand, MonitorInstancesCommand, ReleaseAddressCommand, ReplaceNetworkAclAssociationCommand, ReplaceNetworkAclEntryCommand, ReplaceRouteCommand, RevokeSecurityGroupEgressCommand, RevokeSecurityGroupIngressCommand, RunInstancesCommand, TerminateInstancesCommand, UnmonitorInstancesCommand, waitUntilInstanceRunning, waitUntilInstanceTerminated, waitUntilNatGatewayAvailable, waitUntilNatGatewayDeleted } from "@aws-sdk/client-ec2";
|
|
19
|
+
import { AllocateAddressCommand, AssociateAddressCommand, AssociateIamInstanceProfileCommand, AssociateNatGatewayAddressCommand, AssociateRouteTableCommand, AttachInternetGatewayCommand, AttachVpnGatewayCommand, AuthorizeSecurityGroupEgressCommand, AuthorizeSecurityGroupIngressCommand, CreateInternetGatewayCommand, CreateNatGatewayCommand, CreateNetworkAclCommand, CreateNetworkAclEntryCommand, CreateRouteCommand, CreateRouteTableCommand, CreateSecurityGroupCommand, CreateSubnetCommand, CreateTagsCommand, CreateVpcCommand, DeleteInternetGatewayCommand, DeleteNatGatewayCommand, DeleteNetworkAclCommand, DeleteNetworkAclEntryCommand, DeleteNetworkInterfaceCommand, DeleteRouteCommand, DeleteRouteTableCommand, DeleteSecurityGroupCommand, DeleteSubnetCommand, DeleteTagsCommand, DeleteVpcCommand, DescribeAddressesCommand, DescribeAvailabilityZonesCommand, DescribeIamInstanceProfileAssociationsCommand, DescribeInstanceAttributeCommand, DescribeInstanceCreditSpecificationsCommand, DescribeInstancesCommand, DescribeInternetGatewaysCommand, DescribeNatGatewaysCommand, DescribeNetworkAclsCommand, DescribeNetworkInterfacesCommand, DescribeRouteTablesCommand, DescribeSecurityGroupRulesCommand, DescribeSecurityGroupsCommand, DescribeSubnetsCommand, DescribeVolumesCommand, DescribeVpcAttributeCommand, DescribeVpcsCommand, DescribeVpnGatewaysCommand, DetachInternetGatewayCommand, DetachVpnGatewayCommand, DisassociateAddressCommand, DisassociateIamInstanceProfileCommand, DisassociateNatGatewayAddressCommand, DisassociateRouteTableCommand, EC2Client, ModifyInstanceAttributeCommand, ModifyInstanceCreditSpecificationCommand, ModifyInstanceMetadataOptionsCommand, ModifySubnetAttributeCommand, ModifyVpcAttributeCommand, ModifyVpcTenancyCommand, MonitorInstancesCommand, ReleaseAddressCommand, ReplaceIamInstanceProfileAssociationCommand, ReplaceNetworkAclAssociationCommand, ReplaceNetworkAclEntryCommand, ReplaceRouteCommand, RevokeSecurityGroupEgressCommand, RevokeSecurityGroupIngressCommand, RunInstancesCommand, StartInstancesCommand, StopInstancesCommand, TerminateInstancesCommand, UnmonitorInstancesCommand, waitUntilInstanceRunning, waitUntilInstanceTerminated, waitUntilNatGatewayAvailable, waitUntilNatGatewayDeleted } from "@aws-sdk/client-ec2";
|
|
20
20
|
import { CreateTableCommand, DeleteResourcePolicyCommand, DeleteTableCommand, DescribeContinuousBackupsCommand, DescribeContributorInsightsCommand, DescribeKinesisStreamingDestinationCommand, DescribeTableCommand, DescribeTimeToLiveCommand, DisableKinesisStreamingDestinationCommand, DynamoDBClient, EnableKinesisStreamingDestinationCommand, GetResourcePolicyCommand, ListTagsOfResourceCommand, PolicyNotFoundException, PutResourcePolicyCommand, ResourceNotFoundException as ResourceNotFoundException$1, TagResourceCommand as TagResourceCommand$2, UntagResourceCommand as UntagResourceCommand$2, UpdateContinuousBackupsCommand, UpdateContributorInsightsCommand, UpdateKinesisStreamingDestinationCommand, UpdateTableCommand, UpdateTimeToLiveCommand } from "@aws-sdk/client-dynamodb";
|
|
21
21
|
import { APIGatewayClient, CreateAuthorizerCommand, CreateDeploymentCommand, CreateResourceCommand, CreateStageCommand, DeleteAuthorizerCommand, DeleteDeploymentCommand, DeleteIntegrationCommand, DeleteIntegrationResponseCommand, DeleteMethodCommand, DeleteMethodResponseCommand, DeleteResourceCommand, DeleteStageCommand, GetAccountCommand, GetAuthorizerCommand, GetAuthorizersCommand, GetDeploymentCommand, GetDeploymentsCommand, GetMethodCommand, GetResourceCommand, GetStageCommand, NotFoundException as NotFoundException$1, PutIntegrationCommand, PutIntegrationResponseCommand, PutMethodCommand, PutMethodResponseCommand, TagResourceCommand as TagResourceCommand$3, UntagResourceCommand as UntagResourceCommand$3, UpdateAccountCommand, UpdateAuthorizerCommand, UpdateDeploymentCommand, UpdateMethodCommand, UpdateStageCommand } from "@aws-sdk/client-api-gateway";
|
|
22
22
|
import { CreateEventBusCommand, DeleteEventBusCommand, DeleteRuleCommand, DescribeEventBusCommand, DescribeRuleCommand, EventBridgeClient, ListRulesCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$1, ListTargetsByRuleCommand, PutPermissionCommand, PutRuleCommand, PutTargetsCommand, RemoveTargetsCommand, ResourceNotFoundException as ResourceNotFoundException$2, TagResourceCommand as TagResourceCommand$4, UntagResourceCommand as UntagResourceCommand$4, UpdateEventBusCommand } from "@aws-sdk/client-eventbridge";
|
|
@@ -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
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";
|
|
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 }));
|
|
@@ -12228,7 +12285,8 @@ var DynamoDBTableProvider = class {
|
|
|
12228
12285
|
await this.applyPointInTimeRecovery(tableName, properties["PointInTimeRecoverySpecification"], void 0, maskSecrets);
|
|
12229
12286
|
await this.applyTimeToLive(tableName, properties["TimeToLiveSpecification"], void 0, "create", {
|
|
12230
12287
|
logicalId,
|
|
12231
|
-
resourceType
|
|
12288
|
+
resourceType,
|
|
12289
|
+
maskSecrets
|
|
12232
12290
|
});
|
|
12233
12291
|
await this.applyKinesisStreamingDestination(tableName, properties["KinesisStreamSpecification"], void 0, maskSecrets);
|
|
12234
12292
|
await this.applyContributorInsights(tableName, properties["ContributorInsightsSpecification"], void 0, maskSecrets);
|
|
@@ -12266,6 +12324,7 @@ var DynamoDBTableProvider = class {
|
|
|
12266
12324
|
}
|
|
12267
12325
|
}
|
|
12268
12326
|
async update(logicalId, physicalId, resourceType, properties, previousProperties, context) {
|
|
12327
|
+
const markUnsettled = (key) => context?.markUnsettled?.(key);
|
|
12269
12328
|
const maskSecrets = context?.maskSecrets ?? ((text) => text);
|
|
12270
12329
|
const warn = (message) => this.logger.warn(maskSecrets(message));
|
|
12271
12330
|
const debug = (message) => this.logger.debug(maskSecrets(message));
|
|
@@ -12309,7 +12368,10 @@ var DynamoDBTableProvider = class {
|
|
|
12309
12368
|
warn(`${lsiMessage}; the LocalSecondaryIndexes change was not applied`);
|
|
12310
12369
|
}
|
|
12311
12370
|
let latestStreamArn = table?.LatestStreamArn;
|
|
12312
|
-
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
|
+
});
|
|
12313
12375
|
const normalizeTableClass = (v) => typeof v === "string" && v.length > 0 ? v : "STANDARD";
|
|
12314
12376
|
const tableClassChanged = normalizeTableClass(properties["TableClass"]) !== normalizeTableClass(previousProperties["TableClass"]);
|
|
12315
12377
|
const liveBillingMode = table?.BillingModeSummary?.BillingMode ?? "PROVISIONED";
|
|
@@ -12368,6 +12430,7 @@ var DynamoDBTableProvider = class {
|
|
|
12368
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.`);
|
|
12369
12431
|
} else if (removable.length > 0) {
|
|
12370
12432
|
debug(`Deleting GSI(s) ${removable.join(", ")} on DynamoDB table ${physicalId} before the BillingMode flip to PROVISIONED`);
|
|
12433
|
+
markUnsettled("GlobalSecondaryIndexes");
|
|
12371
12434
|
await this.runGsiOps(physicalId, removable.map((name) => ({ Delete: { IndexName: name } })), void 0, maskSecrets);
|
|
12372
12435
|
for (const name of removable) preFlipDeletedIndexNames.add(name);
|
|
12373
12436
|
}
|
|
@@ -12414,6 +12477,10 @@ var DynamoDBTableProvider = class {
|
|
|
12414
12477
|
if (indexUpdates.length > 0) updateInput.GlobalSecondaryIndexUpdates = indexUpdates;
|
|
12415
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.`);
|
|
12416
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");
|
|
12417
12484
|
await this.dynamoDBClient.send(new UpdateTableCommand(updateInput));
|
|
12418
12485
|
if (billingMode !== liveBillingMode) await this.waitForTableAndIndexesActive(physicalId, BILLING_FLIP_ACTIVE_WAIT_ATTEMPTS);
|
|
12419
12486
|
else await this.waitForTableActiveAfterUpdate(physicalId, 60);
|
|
@@ -12424,6 +12491,7 @@ var DynamoDBTableProvider = class {
|
|
|
12424
12491
|
if (properties["OnDemandThroughput"] || ceilingRemovals.length > 0) {
|
|
12425
12492
|
const declaredForSend = properties["OnDemandThroughput"] ? this.coerceOnDemandCeilingsForSend(`AWS::DynamoDB::Table ${logicalId}`, properties["OnDemandThroughput"], maskSecrets) : {};
|
|
12426
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");
|
|
12427
12495
|
await this.dynamoDBClient.send(new UpdateTableCommand({
|
|
12428
12496
|
TableName: physicalId,
|
|
12429
12497
|
OnDemandThroughput: withOnDemandCeilingRemovals(declaredForSend, ceilingRemovals)
|
|
@@ -12436,6 +12504,7 @@ var DynamoDBTableProvider = class {
|
|
|
12436
12504
|
this.warnRefusedWarmThroughput(`AWS::DynamoDB::Table ${logicalId}`, properties["WarmThroughput"], maskSecrets);
|
|
12437
12505
|
const warmThroughputToSend = this.coerceWarmThroughputForSend(`AWS::DynamoDB::Table ${logicalId}`, properties["WarmThroughput"], maskSecrets);
|
|
12438
12506
|
if (warmThroughputToSend !== void 0 && !this.skipWarmThroughputDecrease(logicalId, physicalId, warmThroughputToSend, table?.WarmThroughput, maskSecrets)) {
|
|
12507
|
+
markUnsettled("WarmThroughput");
|
|
12439
12508
|
await this.dynamoDBClient.send(new UpdateTableCommand({
|
|
12440
12509
|
TableName: physicalId,
|
|
12441
12510
|
WarmThroughput: warmThroughputToSend
|
|
@@ -12451,6 +12520,7 @@ var DynamoDBTableProvider = class {
|
|
|
12451
12520
|
if (liveSseStatus === "UPDATING" || liveSseStatus === "ENABLING" || liveSseStatus === "DISABLING") liveTable = await this.waitForTableSseSettled(physicalId, maskSecrets);
|
|
12452
12521
|
const sseUpdate = sseSpecificationToSend(properties["SSESpecification"], previousProperties["SSESpecification"], liveTable?.SSEDescription, liveTable !== void 0);
|
|
12453
12522
|
if (sseUpdate !== void 0) {
|
|
12523
|
+
markUnsettled("SSESpecification");
|
|
12454
12524
|
await this.dynamoDBClient.send(new UpdateTableCommand({
|
|
12455
12525
|
TableName: physicalId,
|
|
12456
12526
|
SSESpecification: sseUpdate
|
|
@@ -12464,6 +12534,7 @@ var DynamoDBTableProvider = class {
|
|
|
12464
12534
|
const desiredDeletionProtection = rawDeletionProtection === void 0 ? false : coerceCfnBoolean(rawDeletionProtection);
|
|
12465
12535
|
if (desiredDeletionProtection === void 0) warn(`AWS::DynamoDB::Table ${logicalId}: DeletionProtectionEnabled is not a boolean, so it was not applied`);
|
|
12466
12536
|
else if (table?.DeletionProtectionEnabled !== desiredDeletionProtection) {
|
|
12537
|
+
markUnsettled("DeletionProtectionEnabled");
|
|
12467
12538
|
await this.dynamoDBClient.send(new UpdateTableCommand({
|
|
12468
12539
|
TableName: physicalId,
|
|
12469
12540
|
DeletionProtectionEnabled: desiredDeletionProtection
|
|
@@ -12473,6 +12544,7 @@ var DynamoDBTableProvider = class {
|
|
|
12473
12544
|
}
|
|
12474
12545
|
}
|
|
12475
12546
|
if (JSON.stringify(properties["StreamSpecification"]) !== JSON.stringify(previousProperties["StreamSpecification"])) {
|
|
12547
|
+
markUnsettled("StreamSpecification");
|
|
12476
12548
|
const newViewType = this.extractStreamViewType(properties["StreamSpecification"]);
|
|
12477
12549
|
const prevViewType = this.extractStreamViewType(previousProperties["StreamSpecification"]);
|
|
12478
12550
|
const liveStream = table?.StreamSpecification;
|
|
@@ -12520,22 +12592,38 @@ var DynamoDBTableProvider = class {
|
|
|
12520
12592
|
}
|
|
12521
12593
|
if (newViewType) await this.applyStreamMembers(logicalId, resourceType, physicalId, latestStreamArn, properties["StreamSpecification"], previousProperties["StreamSpecification"], mintedStream, maskSecrets, mintedStream ? preUpdateStreamArn : void 0, contentsUnknown);
|
|
12522
12594
|
}
|
|
12523
|
-
if (
|
|
12524
|
-
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
|
+
}
|
|
12525
12604
|
if (JSON.stringify(properties["TimeToLiveSpecification"]) !== JSON.stringify(previousProperties["TimeToLiveSpecification"])) {
|
|
12526
12605
|
this.assertNoActiveTtlAttributeNameChange(logicalId, resourceType, physicalId, properties["TimeToLiveSpecification"], previousProperties["TimeToLiveSpecification"]);
|
|
12606
|
+
markUnsettled("TimeToLiveSpecification");
|
|
12527
12607
|
await this.applyTimeToLive(physicalId, properties["TimeToLiveSpecification"], previousProperties["TimeToLiveSpecification"], "update", {
|
|
12528
12608
|
logicalId,
|
|
12529
|
-
resourceType
|
|
12609
|
+
resourceType,
|
|
12610
|
+
maskSecrets
|
|
12530
12611
|
});
|
|
12531
12612
|
}
|
|
12532
12613
|
if (JSON.stringify(properties["ResourcePolicy"]) !== JSON.stringify(previousProperties["ResourcePolicy"])) {
|
|
12533
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");
|
|
12534
12616
|
await this.applyResourcePolicy(table.TableArn, properties["ResourcePolicy"], previousProperties["ResourcePolicy"]);
|
|
12535
12617
|
}
|
|
12536
|
-
if (JSON.stringify(properties["KinesisStreamSpecification"]) !== JSON.stringify(previousProperties["KinesisStreamSpecification"]))
|
|
12537
|
-
|
|
12538
|
-
|
|
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"));
|
|
12539
12627
|
return {
|
|
12540
12628
|
physicalId,
|
|
12541
12629
|
wasReplaced: false,
|
|
@@ -12673,15 +12761,19 @@ var DynamoDBTableProvider = class {
|
|
|
12673
12761
|
throw error instanceof Error && error.name.includes("NotFound") ? markNotGone(thrown) : thrown;
|
|
12674
12762
|
}
|
|
12675
12763
|
}
|
|
12676
|
-
async applyTagDiff(tableArn, resourceType, logicalId, oldTagsRaw, newTagsRaw
|
|
12764
|
+
async applyTagDiff(tableArn, resourceType, logicalId, oldTagsRaw, newTagsRaw, unsettled = {
|
|
12765
|
+
forceUpsert: false,
|
|
12766
|
+
beforeWrite: () => void 0
|
|
12767
|
+
}) {
|
|
12677
12768
|
const plan = planTagDiff(oldTagsRaw, newTagsRaw);
|
|
12678
12769
|
const tagWarning = tagPlanWarning(plan, resourceType, logicalId);
|
|
12679
12770
|
if (tagWarning !== void 0) this.logger.warn(tagWarning);
|
|
12680
|
-
const tagsToAdd = [...plan.set].map(([k, v]) => ({
|
|
12771
|
+
const tagsToAdd = [...unsettled.forceUpsert ? planTagDiff(void 0, newTagsRaw).set : plan.set].map(([k, v]) => ({
|
|
12681
12772
|
Key: k,
|
|
12682
12773
|
Value: v
|
|
12683
12774
|
}));
|
|
12684
12775
|
const tagsToRemove = plan.remove;
|
|
12776
|
+
if (tagsToRemove.length > 0 || tagsToAdd.length > 0) unsettled.beforeWrite();
|
|
12685
12777
|
if (tagsToRemove.length > 0) {
|
|
12686
12778
|
await this.dynamoDBClient.send(new UntagResourceCommand$2({
|
|
12687
12779
|
ResourceArn: tableArn,
|
|
@@ -12732,6 +12824,7 @@ var DynamoDBTableProvider = class {
|
|
|
12732
12824
|
const retryLine = `Transient error on "${label}" (attempt ${attempt}/${maxAttempts}): ${msg} — retrying in ${delayMs}ms`;
|
|
12733
12825
|
this.logger.debug(options.maskSecrets ? options.maskSecrets(retryLine) : retryLine);
|
|
12734
12826
|
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
12827
|
+
if (options.stopAtDeadline && enclosingDeadlineRemainingMs() <= 0) throw error;
|
|
12735
12828
|
delayMs = Math.min(delayMs * 2, 3e4);
|
|
12736
12829
|
}
|
|
12737
12830
|
}
|
|
@@ -12746,10 +12839,10 @@ var DynamoDBTableProvider = class {
|
|
|
12746
12839
|
let attributeName;
|
|
12747
12840
|
if (plan.kind === "none") return;
|
|
12748
12841
|
if (plan.kind === "disable-live") {
|
|
12749
|
-
const live = (await this.retryOnTransientControlPlane(() => this.dynamoDBClient.send(new DescribeTimeToLiveCommand({ TableName: tableName })), `read TTL on ${tableName}
|
|
12842
|
+
const live = (await this.retryOnTransientControlPlane(() => this.dynamoDBClient.send(new DescribeTimeToLiveCommand({ TableName: tableName })), `read TTL on ${tableName}`, void 0, { maskSecrets: ids.maskSecrets })).TimeToLiveDescription;
|
|
12750
12843
|
const status = live?.TimeToLiveStatus;
|
|
12751
12844
|
if (status !== "ENABLED" && status !== "ENABLING" || !live?.AttributeName) {
|
|
12752
|
-
this.logger.debug(`TimeToLive already ${status ?? "DISABLED"} on DynamoDB table ${tableName}; nothing to disable`);
|
|
12845
|
+
this.logger.debug(ids.maskSecrets(`TimeToLive already ${status ?? "DISABLED"} on DynamoDB table ${tableName}; nothing to disable`));
|
|
12753
12846
|
return;
|
|
12754
12847
|
}
|
|
12755
12848
|
enabled = false;
|
|
@@ -12759,22 +12852,28 @@ var DynamoDBTableProvider = class {
|
|
|
12759
12852
|
attributeName = plan.attributeName;
|
|
12760
12853
|
}
|
|
12761
12854
|
try {
|
|
12762
|
-
await this.retryOnTransientControlPlane(() => this.dynamoDBClient.send(new UpdateTimeToLiveCommand({
|
|
12855
|
+
await sendTtlWaitingOutRateLimit(() => this.retryOnTransientControlPlane(() => this.dynamoDBClient.send(new UpdateTimeToLiveCommand({
|
|
12763
12856
|
TableName: tableName,
|
|
12764
12857
|
TimeToLiveSpecification: {
|
|
12765
12858
|
Enabled: enabled,
|
|
12766
12859
|
AttributeName: attributeName
|
|
12767
12860
|
}
|
|
12768
|
-
})), `${enabled ? "set" : "disable"} TTL on ${tableName}
|
|
12861
|
+
})), `${enabled ? "set" : "disable"} TTL on ${tableName}`, void 0, {
|
|
12862
|
+
maskSecrets: ids.maskSecrets,
|
|
12863
|
+
stopAtDeadline: true
|
|
12864
|
+
}), {
|
|
12865
|
+
what: ids.maskSecrets(`DynamoDB TimeToLive rate-limit wait on ${tableName}`),
|
|
12866
|
+
announce: () => this.logger.info(ids.maskSecrets(`DynamoDB table ${ids.logicalId}: TimeToLive was changed recently, and AWS refuses another change until its rate-limit interval passes (up to about an hour). Retrying every minute, like CloudFormation, within the resource timeout.`))
|
|
12867
|
+
});
|
|
12769
12868
|
} catch (error) {
|
|
12770
12869
|
if (!enabled && isTtlAlreadyDisabled(describeAwsFailure(error).detail)) {
|
|
12771
|
-
this.logger.debug(`TimeToLive already disabled on DynamoDB table ${tableName}`);
|
|
12870
|
+
this.logger.debug(ids.maskSecrets(`TimeToLive already disabled on DynamoDB table ${tableName}`));
|
|
12772
12871
|
return;
|
|
12773
12872
|
}
|
|
12774
|
-
if (describeAwsFailure(error).detail
|
|
12873
|
+
if (isTtlRateLimited(describeAwsFailure(error).detail)) throw new ProvisioningError(`DynamoDB table ${ids.logicalId}: AWS refused to ${enabled ? "enable" : "disable"} TimeToLive because it was already modified within DynamoDB's rate-limit interval, and kept refusing until the resource timeout ran out. Redeploy once the interval has passed (up to about an hour), or raise --resource-timeout.`, ids.resourceType, ids.logicalId, tableName, error instanceof Error ? error : void 0);
|
|
12775
12874
|
throw error;
|
|
12776
12875
|
}
|
|
12777
|
-
this.logger.debug(`Set TimeToLive Enabled=${enabled} AttributeName=${attributeName} on DynamoDB table ${tableName}`);
|
|
12876
|
+
this.logger.debug(ids.maskSecrets(`Set TimeToLive Enabled=${enabled} AttributeName=${attributeName} on DynamoDB table ${tableName}`));
|
|
12778
12877
|
}
|
|
12779
12878
|
extractResourcePolicyDocument(spec) {
|
|
12780
12879
|
if (spec === void 0 || spec === null) return void 0;
|
|
@@ -12987,12 +13086,15 @@ var DynamoDBTableProvider = class {
|
|
|
12987
13086
|
if (op === void 0) return;
|
|
12988
13087
|
await this.sendContributorInsightsOp(tableName, op, maskSecrets);
|
|
12989
13088
|
}
|
|
12990
|
-
async applyIndexContributorInsights(tableName, desiredIndexes, previousIndexes, maskSecrets) {
|
|
13089
|
+
async applyIndexContributorInsights(tableName, desiredIndexes, previousIndexes, maskSecrets, beforeSend = () => void 0) {
|
|
12991
13090
|
const warn = (message) => this.logger.warn(maskSecrets(message));
|
|
12992
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.`));
|
|
12993
13092
|
if (ops.length === 0) return;
|
|
12994
13093
|
await this.waitForTableAndIndexesActive(tableName);
|
|
12995
|
-
for (const op of ops)
|
|
13094
|
+
for (const op of ops) {
|
|
13095
|
+
beforeSend();
|
|
13096
|
+
await this.sendContributorInsightsOp(tableName, op, maskSecrets);
|
|
13097
|
+
}
|
|
12996
13098
|
}
|
|
12997
13099
|
async sendContributorInsightsOp(tableName, op, maskSecrets) {
|
|
12998
13100
|
const debug = (message) => this.logger.debug(maskSecrets(message));
|
|
@@ -13144,6 +13246,21 @@ var DynamoDBTableProvider = class {
|
|
|
13144
13246
|
indexScope(indexName, logicalId, maskSecrets) {
|
|
13145
13247
|
return `GSI ${typeof indexName === "string" ? maskSecrets(indexName) : "<unnamed>"} on AWS::DynamoDB::Table ${logicalId}`;
|
|
13146
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
|
+
}
|
|
13147
13264
|
indexScopeAt(indexName, physicalId, maskSecrets) {
|
|
13148
13265
|
return `GSI ${typeof indexName === "string" ? maskSecrets(indexName) : "<unnamed>"} on DynamoDB table ${physicalId}`;
|
|
13149
13266
|
}
|
|
@@ -13430,6 +13547,62 @@ var DynamoDBTableProvider = class {
|
|
|
13430
13547
|
aws
|
|
13431
13548
|
};
|
|
13432
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
|
+
}
|
|
13433
13606
|
async readCurrentState(physicalId, _logicalId, _resourceType, properties, context) {
|
|
13434
13607
|
try {
|
|
13435
13608
|
const table = (await this.dynamoDBClient.send(new DescribeTableCommand({ TableName: physicalId }))).Table;
|
|
@@ -13512,7 +13685,7 @@ var DynamoDBTableProvider = class {
|
|
|
13512
13685
|
throw err;
|
|
13513
13686
|
}
|
|
13514
13687
|
}
|
|
13515
|
-
async readPointInTimeRecovery(physicalId) {
|
|
13688
|
+
async readPointInTimeRecovery(physicalId, strict = false) {
|
|
13516
13689
|
try {
|
|
13517
13690
|
const pitrDesc = (await this.dynamoDBClient.send(new DescribeContinuousBackupsCommand({ TableName: physicalId }))).ContinuousBackupsDescription?.PointInTimeRecoveryDescription;
|
|
13518
13691
|
const pitrStatus = pitrDesc?.PointInTimeRecoveryStatus;
|
|
@@ -13521,11 +13694,12 @@ var DynamoDBTableProvider = class {
|
|
|
13521
13694
|
if (pitrStatus === "ENABLED" && pitrDesc?.RecoveryPeriodInDays !== void 0) pitr["RecoveryPeriodInDays"] = pitrDesc.RecoveryPeriodInDays;
|
|
13522
13695
|
return pitr;
|
|
13523
13696
|
} catch (err) {
|
|
13697
|
+
if (strict) throw err;
|
|
13524
13698
|
this.logger.debug(`Could not read PointInTimeRecovery for ${physicalId}: ${describeAwsFailure(err).detail}`);
|
|
13525
13699
|
return;
|
|
13526
13700
|
}
|
|
13527
13701
|
}
|
|
13528
|
-
async readTimeToLive(physicalId) {
|
|
13702
|
+
async readTimeToLive(physicalId, strict = false) {
|
|
13529
13703
|
try {
|
|
13530
13704
|
const ttlDesc = (await this.dynamoDBClient.send(new DescribeTimeToLiveCommand({ TableName: physicalId }))).TimeToLiveDescription;
|
|
13531
13705
|
if (ttlDesc?.TimeToLiveStatus === "ENABLED" && ttlDesc.AttributeName) return {
|
|
@@ -13534,11 +13708,12 @@ var DynamoDBTableProvider = class {
|
|
|
13534
13708
|
};
|
|
13535
13709
|
return;
|
|
13536
13710
|
} catch (err) {
|
|
13711
|
+
if (strict) throw err;
|
|
13537
13712
|
this.logger.debug(`Could not read TimeToLive for ${physicalId}: ${describeAwsFailure(err).detail}`);
|
|
13538
13713
|
return;
|
|
13539
13714
|
}
|
|
13540
13715
|
}
|
|
13541
|
-
async readTableResourcePolicy(physicalId, tableArn) {
|
|
13716
|
+
async readTableResourcePolicy(physicalId, tableArn, strict = false) {
|
|
13542
13717
|
try {
|
|
13543
13718
|
const rpResp = await this.dynamoDBClient.send(new GetResourcePolicyCommand({ ResourceArn: tableArn }));
|
|
13544
13719
|
if (!rpResp.Policy) return void 0;
|
|
@@ -13548,11 +13723,12 @@ var DynamoDBTableProvider = class {
|
|
|
13548
13723
|
} catch {}
|
|
13549
13724
|
return { PolicyDocument: doc };
|
|
13550
13725
|
} catch (err) {
|
|
13726
|
+
if (strict && !(err instanceof ResourceNotFoundException$1) && !(err instanceof PolicyNotFoundException)) throw err;
|
|
13551
13727
|
if (!(err instanceof ResourceNotFoundException$1)) this.logger.debug(`Could not read ResourcePolicy for ${physicalId}: ${describeAwsFailure(err).detail}`);
|
|
13552
13728
|
return;
|
|
13553
13729
|
}
|
|
13554
13730
|
}
|
|
13555
|
-
async readKinesisStreamSpecification(physicalId) {
|
|
13731
|
+
async readKinesisStreamSpecification(physicalId, strict = false) {
|
|
13556
13732
|
try {
|
|
13557
13733
|
const active = ((await this.dynamoDBClient.send(new DescribeKinesisStreamingDestinationCommand({ TableName: physicalId }))).KinesisDataStreamDestinations ?? []).find((d) => d.DestinationStatus === "ACTIVE" || d.DestinationStatus === "ENABLING" || d.DestinationStatus === "UPDATING");
|
|
13558
13734
|
if (!active?.StreamArn) return void 0;
|
|
@@ -13560,15 +13736,17 @@ var DynamoDBTableProvider = class {
|
|
|
13560
13736
|
if (active.ApproximateCreationDateTimePrecision !== void 0) kspec["ApproximateCreationDateTimePrecision"] = active.ApproximateCreationDateTimePrecision;
|
|
13561
13737
|
return kspec;
|
|
13562
13738
|
} catch (err) {
|
|
13739
|
+
if (strict) throw err;
|
|
13563
13740
|
this.logger.debug(`Could not read KinesisStreamingDestination for ${physicalId}: ${describeAwsFailure(err).detail}`);
|
|
13564
13741
|
return;
|
|
13565
13742
|
}
|
|
13566
13743
|
}
|
|
13567
|
-
async readTableContributorInsights(physicalId) {
|
|
13744
|
+
async readTableContributorInsights(physicalId, strict = false) {
|
|
13568
13745
|
try {
|
|
13569
13746
|
const ciResp = await this.dynamoDBClient.send(new DescribeContributorInsightsCommand({ TableName: physicalId }));
|
|
13570
13747
|
return reverseMapTableContributorInsights(ciResp.ContributorInsightsStatus, ciResp.ContributorInsightsMode);
|
|
13571
13748
|
} catch (err) {
|
|
13749
|
+
if (strict) throw err;
|
|
13572
13750
|
this.logger.debug(`Could not read ContributorInsights for ${physicalId}: ${describeAwsFailure(err).detail}`);
|
|
13573
13751
|
return;
|
|
13574
13752
|
}
|
|
@@ -13692,6 +13870,22 @@ var DynamoDBTableProvider = class {
|
|
|
13692
13870
|
function isTransientStreamReadFailure(err) {
|
|
13693
13871
|
return isThrottlingError(err) || isTransientServerError(err) || isAmbiguousOutcomeError(err) || err instanceof ResourceNotFoundException$1;
|
|
13694
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
|
+
}
|
|
13695
13889
|
|
|
13696
13890
|
//#endregion
|
|
13697
13891
|
//#region src/provisioning/providers/logs-loggroup-provider.ts
|
|
@@ -16131,6 +16325,46 @@ const EC2_VPC_GATEWAY_ATTACHMENT_ID_FORMAT = {
|
|
|
16131
16325
|
segments: ["gatewayId", "vpcId"]
|
|
16132
16326
|
};
|
|
16133
16327
|
const VPN_GATEWAY_ATTACHMENT_WAIT_MS = 6e5;
|
|
16328
|
+
const INSTANCE_STATE_WAIT_CAP_MS = 9e5;
|
|
16329
|
+
const INSTANCE_STATE_POLL_MS = 5e3;
|
|
16330
|
+
const STOPPED_AFTER_START_READS = 3;
|
|
16331
|
+
const PROFILE_DISASSOCIATING_POLLS = 15;
|
|
16332
|
+
const PROFILE_DISASSOCIATING_DELAY_MS = 2e3;
|
|
16333
|
+
function refusedBeforeApplying(error) {
|
|
16334
|
+
return markRefusedBeforeApplying(markNonRetryable(error));
|
|
16335
|
+
}
|
|
16336
|
+
const STOPPABLE_INSTANCE_STATES = /* @__PURE__ */ new Set([
|
|
16337
|
+
"pending",
|
|
16338
|
+
"running",
|
|
16339
|
+
"stopping",
|
|
16340
|
+
"stopped"
|
|
16341
|
+
]);
|
|
16342
|
+
const instancesLeftStoppedByCdkd = /* @__PURE__ */ new Set();
|
|
16343
|
+
const instanceStoppedAfterStart = /* @__PURE__ */ new WeakSet();
|
|
16344
|
+
function isRecordedStandIn$1(value) {
|
|
16345
|
+
if (Array.isArray(value)) return value.some(isRecordedStandIn$1);
|
|
16346
|
+
if (value !== null && typeof value === "object") return Object.values(value).some(isRecordedStandIn$1);
|
|
16347
|
+
return typeof value === "string" && (value === "***" || dynamicReferenceTokens(value).length > 0);
|
|
16348
|
+
}
|
|
16349
|
+
function instanceProfileKey(value) {
|
|
16350
|
+
const fromArn = (arn) => arn.slice(arn.lastIndexOf("/") + 1);
|
|
16351
|
+
if (typeof value === "string") {
|
|
16352
|
+
const v = value.trim();
|
|
16353
|
+
if (v === "") return void 0;
|
|
16354
|
+
return v.startsWith("arn:") ? fromArn(v) : v;
|
|
16355
|
+
}
|
|
16356
|
+
if (value !== null && typeof value === "object") {
|
|
16357
|
+
const obj = value;
|
|
16358
|
+
if (typeof obj["Name"] === "string" && obj["Name"] !== "") return obj["Name"];
|
|
16359
|
+
if (typeof obj["Arn"] === "string" && obj["Arn"] !== "") return fromArn(obj["Arn"]);
|
|
16360
|
+
}
|
|
16361
|
+
}
|
|
16362
|
+
function sameStringSet(a, b) {
|
|
16363
|
+
if (!Array.isArray(a) || !Array.isArray(b)) return a === b;
|
|
16364
|
+
const sa = new Set(a.map(String));
|
|
16365
|
+
const sb = new Set(b.map(String));
|
|
16366
|
+
return sa.size === sb.size && [...sa].every((x) => sb.has(x));
|
|
16367
|
+
}
|
|
16134
16368
|
const VPN_DETACH_IN_PROGRESS_ERRORS = /* @__PURE__ */ new Set(["IncorrectState"]);
|
|
16135
16369
|
const EC2_ROUTE_ID_FORMAT = {
|
|
16136
16370
|
label: "Route",
|
|
@@ -16723,19 +16957,19 @@ var EC2Provider = class {
|
|
|
16723
16957
|
switch (resourceType) {
|
|
16724
16958
|
case "AWS::EC2::VPC": return this.updateVpc(logicalId, physicalId, resourceType, properties, previousProperties, context);
|
|
16725
16959
|
case "AWS::EC2::Subnet": return this.updateSubnet(logicalId, physicalId, resourceType, properties, previousProperties, context);
|
|
16726
|
-
case "AWS::EC2::InternetGateway": return this.
|
|
16960
|
+
case "AWS::EC2::InternetGateway": return this.updateTagsOnly(logicalId, physicalId, resourceType, false, properties, previousProperties, context);
|
|
16727
16961
|
case "AWS::EC2::EIP": return this.updateEip(logicalId, physicalId, resourceType, properties, previousProperties, context);
|
|
16728
16962
|
case "AWS::EC2::VPCGatewayAttachment": return this.updateVpcGatewayAttachment(logicalId, physicalId, resourceType, properties, previousProperties, context);
|
|
16729
16963
|
case "AWS::EC2::NatGateway": return this.updateNatGateway(logicalId, physicalId, resourceType, properties, previousProperties, context);
|
|
16730
|
-
case "AWS::EC2::RouteTable":
|
|
16964
|
+
case "AWS::EC2::RouteTable":
|
|
16965
|
+
case "AWS::EC2::NetworkAcl": return this.updateTagsOnly(logicalId, physicalId, resourceType, true, properties, previousProperties, context);
|
|
16731
16966
|
case "AWS::EC2::Route": return this.updateRoute(logicalId, physicalId, resourceType, properties, previousProperties, context);
|
|
16732
16967
|
case "AWS::EC2::SubnetRouteTableAssociation": return this.updateSubnetRouteTableAssociation(logicalId, physicalId);
|
|
16733
16968
|
case "AWS::EC2::SecurityGroup": return this.updateSecurityGroup(logicalId, physicalId, resourceType, properties, previousProperties, context);
|
|
16734
16969
|
case "AWS::EC2::SecurityGroupIngress": return this.updateSecurityGroupIngress(logicalId, physicalId, resourceType, properties, previousProperties, context?.maskSecrets, context?.replayingState === true, context?.recordedAttributes);
|
|
16735
16970
|
case "AWS::EC2::Instance": return this.updateInstance(logicalId, physicalId, resourceType, properties, previousProperties, context);
|
|
16736
16971
|
case "AWS::EC2::NetworkAclEntry": return this.updateNetworkAclEntry(logicalId, physicalId, resourceType, properties, previousProperties, context);
|
|
16737
|
-
case "AWS::EC2::
|
|
16738
|
-
case "AWS::EC2::SubnetNetworkAclAssociation": throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "AWS provides no in-place Update API for this EC2 sub-resource type; every property change requires Delete + Create. Re-deploy with cdkd deploy --replace, or destroy + redeploy.");
|
|
16972
|
+
case "AWS::EC2::SubnetNetworkAclAssociation": throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "AWS provides no in-place Update API for this EC2 sub-resource type; every property change requires Delete + Create. Re-deploy with cdkd deploy --replace, or destroy + redeploy");
|
|
16739
16973
|
default: throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId, physicalId);
|
|
16740
16974
|
}
|
|
16741
16975
|
}
|
|
@@ -16976,6 +17210,10 @@ var EC2Provider = class {
|
|
|
16976
17210
|
this.logger.debug(`Updating VPC ${logicalId}: ${physicalId}`);
|
|
16977
17211
|
refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId);
|
|
16978
17212
|
try {
|
|
17213
|
+
const tenancyOf = (v) => v == null ? "default" : String(v);
|
|
17214
|
+
const newTenancy = tenancyOf(properties["InstanceTenancy"]);
|
|
17215
|
+
const oldTenancy = tenancyOf(previousProperties["InstanceTenancy"]);
|
|
17216
|
+
if (newTenancy !== oldTenancy && newTenancy !== "default") throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "destroy + redeploy the VPC (and the resources that depend on it). AWS changes InstanceTenancy in place only to default, and CloudFormation creates a new VPC for this change");
|
|
16979
17217
|
const asBool = (v) => {
|
|
16980
17218
|
if (v === void 0) return void 0;
|
|
16981
17219
|
return v === true || v === "true";
|
|
@@ -16992,6 +17230,10 @@ var EC2Provider = class {
|
|
|
16992
17230
|
VpcId: physicalId,
|
|
16993
17231
|
EnableDnsSupport: { Value: newDnsSupport }
|
|
16994
17232
|
}));
|
|
17233
|
+
if (newTenancy !== oldTenancy) await this.ec2Client.send(new ModifyVpcTenancyCommand({
|
|
17234
|
+
VpcId: physicalId,
|
|
17235
|
+
InstanceTenancy: "default"
|
|
17236
|
+
}));
|
|
16995
17237
|
await this.applyTagDiff(physicalId, resourceType, logicalId, previousProperties["Tags"], properties["Tags"], maskerOrIdentity(context?.maskSecrets));
|
|
16996
17238
|
this.logger.debug(`Successfully updated VPC ${logicalId}`);
|
|
16997
17239
|
return {
|
|
@@ -17003,6 +17245,7 @@ var EC2Provider = class {
|
|
|
17003
17245
|
}
|
|
17004
17246
|
};
|
|
17005
17247
|
} catch (error) {
|
|
17248
|
+
if (error instanceof CdkdError) throw error;
|
|
17006
17249
|
const cause = error instanceof Error ? error : void 0;
|
|
17007
17250
|
throw this.wrapCaughtError(maskerOrIdentity(context?.maskSecrets), error, (text) => new ProvisioningError(`Failed to update VPC ${logicalId}: ${text}`, resourceType, logicalId, physicalId, cause));
|
|
17008
17251
|
}
|
|
@@ -17272,8 +17515,20 @@ var EC2Provider = class {
|
|
|
17272
17515
|
throw this.wrapCaughtError(maskerOrIdentity(context?.maskSecrets), error, (text) => new ProvisioningError(`Failed to create InternetGateway ${logicalId}: ${text}`, resourceType, logicalId, void 0, cause));
|
|
17273
17516
|
}
|
|
17274
17517
|
}
|
|
17275
|
-
|
|
17276
|
-
|
|
17518
|
+
async updateTagsOnly(logicalId, physicalId, resourceType, vpcIdCreateOnly, properties, previousProperties, context) {
|
|
17519
|
+
const label = resourceType.slice(10);
|
|
17520
|
+
this.logger.debug(safeMsg`Updating ${label} ${logicalId}: ${physicalId}`);
|
|
17521
|
+
refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId);
|
|
17522
|
+
if (vpcIdCreateOnly) {
|
|
17523
|
+
const next = properties["VpcId"];
|
|
17524
|
+
const prev = previousProperties["VpcId"];
|
|
17525
|
+
if (next !== void 0 && prev !== void 0 && next !== prev) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `destroy + redeploy the ${label} (and the resources that depend on it). VpcId is immutable in AWS`);
|
|
17526
|
+
}
|
|
17527
|
+
await this.applyTagDiff(physicalId, resourceType, logicalId, previousProperties["Tags"], properties["Tags"], maskerOrIdentity(context?.maskSecrets));
|
|
17528
|
+
return {
|
|
17529
|
+
physicalId,
|
|
17530
|
+
wasReplaced: false
|
|
17531
|
+
};
|
|
17277
17532
|
}
|
|
17278
17533
|
async deleteInternetGateway(logicalId, physicalId, resourceType, context) {
|
|
17279
17534
|
this.logger.debug(`Deleting InternetGateway ${logicalId}: ${physicalId}`);
|
|
@@ -18019,9 +18274,6 @@ var EC2Provider = class {
|
|
|
18019
18274
|
throw this.wrapCaughtError(maskerOrIdentity(context?.maskSecrets), error, (text) => new ProvisioningError(`Failed to create RouteTable ${logicalId}: ${text}`, resourceType, logicalId, void 0, cause));
|
|
18020
18275
|
}
|
|
18021
18276
|
}
|
|
18022
|
-
updateRouteTable(logicalId, physicalId) {
|
|
18023
|
-
return Promise.reject(new ResourceUpdateNotSupportedError("AWS::EC2::RouteTable", logicalId, "destroy + redeploy the RouteTable (and its associated Routes / SubnetRouteTableAssociations). VpcId is immutable."));
|
|
18024
|
-
}
|
|
18025
18277
|
async deleteRouteTable(logicalId, physicalId, resourceType, context) {
|
|
18026
18278
|
this.logger.debug(`Deleting RouteTable ${logicalId}: ${physicalId}`);
|
|
18027
18279
|
try {
|
|
@@ -18180,7 +18432,7 @@ var EC2Provider = class {
|
|
|
18180
18432
|
}
|
|
18181
18433
|
}
|
|
18182
18434
|
updateSubnetRouteTableAssociation(logicalId, physicalId) {
|
|
18183
|
-
return Promise.reject(new ResourceUpdateNotSupportedError("AWS::EC2::SubnetRouteTableAssociation", logicalId, "destroy + redeploy the association. (SubnetId, RouteTableId) is immutable
|
|
18435
|
+
return Promise.reject(new ResourceUpdateNotSupportedError("AWS::EC2::SubnetRouteTableAssociation", logicalId, "destroy + redeploy the association. (SubnetId, RouteTableId) is immutable"));
|
|
18184
18436
|
}
|
|
18185
18437
|
async deleteSubnetRouteTableAssociation(logicalId, physicalId, resourceType, context) {
|
|
18186
18438
|
this.logger.debug(`Deleting SubnetRouteTableAssociation ${logicalId}: ${physicalId}`);
|
|
@@ -18256,7 +18508,7 @@ var EC2Provider = class {
|
|
|
18256
18508
|
if (!Array.isArray(ingressRules) || ingressRules.length === 0) return;
|
|
18257
18509
|
await this.ec2Client.send(new AuthorizeSecurityGroupIngressCommand({
|
|
18258
18510
|
GroupId: groupId,
|
|
18259
|
-
IpPermissions: ingressRules.map((rule) => this.buildIpPermission(rule))
|
|
18511
|
+
IpPermissions: ingressRules.map((rule) => this.buildIpPermission(rule, "ingress", true))
|
|
18260
18512
|
}));
|
|
18261
18513
|
}
|
|
18262
18514
|
async applyInlineEgress(groupId, egressRules) {
|
|
@@ -18902,9 +19154,12 @@ var EC2Provider = class {
|
|
|
18902
19154
|
this.logger.debug(`Updating EC2 Instance ${logicalId}: ${physicalId}`);
|
|
18903
19155
|
refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId);
|
|
18904
19156
|
this.guardTerminationProtectionRemoval(logicalId, physicalId, resourceType, properties, previousProperties, context);
|
|
19157
|
+
const memberPlan = this.planInstanceMemberUpdates(logicalId, physicalId, resourceType, properties, previousProperties, context);
|
|
18905
19158
|
try {
|
|
19159
|
+
await this.prepareInstanceMemberUpdates(logicalId, physicalId, resourceType, memberPlan);
|
|
18906
19160
|
await this.applyTagDiff(physicalId, resourceType, logicalId, previousProperties["Tags"], properties["Tags"], maskerOrIdentity(context?.maskSecrets));
|
|
18907
19161
|
await this.updateInstanceSecurityProps(physicalId, properties, previousProperties);
|
|
19162
|
+
await this.applyInstanceMemberUpdates(logicalId, physicalId, resourceType, memberPlan);
|
|
18908
19163
|
const instance = (await this.ec2Client.send(new DescribeInstancesCommand({ InstanceIds: [physicalId] }))).Reservations?.[0]?.Instances?.[0];
|
|
18909
19164
|
return {
|
|
18910
19165
|
physicalId,
|
|
@@ -18912,6 +19167,7 @@ var EC2Provider = class {
|
|
|
18912
19167
|
attributes: describedInstanceAttributes(physicalId, instance)
|
|
18913
19168
|
};
|
|
18914
19169
|
} catch (error) {
|
|
19170
|
+
if (error instanceof CdkdError || isInterruptedWaitError(error)) throw error;
|
|
18915
19171
|
const cause = error instanceof Error ? error : void 0;
|
|
18916
19172
|
throw this.wrapCaughtError(maskerOrIdentity(context?.maskSecrets), error, (text) => new ProvisioningError(`Failed to update EC2 Instance ${logicalId}: ${text}`, resourceType, logicalId, physicalId, cause));
|
|
18917
19173
|
}
|
|
@@ -18950,6 +19206,286 @@ var EC2Provider = class {
|
|
|
18950
19206
|
CpuCredits: newCpuCredits
|
|
18951
19207
|
}] }));
|
|
18952
19208
|
}
|
|
19209
|
+
planInstanceMemberUpdates(logicalId, physicalId, resourceType, properties, previousProperties, context) {
|
|
19210
|
+
const plan = {};
|
|
19211
|
+
const removed = (key) => context?.removedProperties !== void 0 ? context.removedProperties.has(key) : previousProperties[key] !== void 0 && properties[key] === void 0;
|
|
19212
|
+
const changed = (key, same) => {
|
|
19213
|
+
const before = previousProperties[key];
|
|
19214
|
+
const after = properties[key];
|
|
19215
|
+
if (after === void 0 && !removed(key)) return false;
|
|
19216
|
+
if (context?.changedProperties !== void 0 && !context.changedProperties.has(key)) return false;
|
|
19217
|
+
if (isDeepStrictEqual(before, after)) {
|
|
19218
|
+
if (context?.replayingState === true && isRecordedStandIn$1(after)) this.logger.warn(safeMsg`${logicalId} (${resourceType}): both sides of the rollback record ${key} as a stand-in (an unresolved {{resolve:...}} reference or the redaction mask), so cdkd cannot tell whether it changed; the rollback leaves ${key} at its current AWS value.`);
|
|
19219
|
+
return false;
|
|
19220
|
+
}
|
|
19221
|
+
return !(!isRecordedStandIn$1(before) && !isRecordedStandIn$1(after) && same(before, after));
|
|
19222
|
+
};
|
|
19223
|
+
const standInSkips = (key) => {
|
|
19224
|
+
if (!isRecordedStandIn$1(properties[key])) return false;
|
|
19225
|
+
if (context?.replayingState === true) {
|
|
19226
|
+
this.logger.warn(safeMsg`${logicalId} (${resourceType}): the state being restored records ${key} as a stand-in (an unresolved {{resolve:...}} reference or the redaction mask), not a value cdkd can send; the rollback leaves ${key} at its current AWS value.`);
|
|
19227
|
+
return true;
|
|
19228
|
+
}
|
|
19229
|
+
throw refusedBeforeApplying(new ProvisioningError(`${logicalId} (${resourceType}): ${key} holds a recorded stand-in (an unresolved {{resolve:...}} reference or the redaction mask), not a value cdkd can send. The instance was not updated; deploy from the template so the value resolves.`, resourceType, logicalId, physicalId));
|
|
19230
|
+
};
|
|
19231
|
+
if (changed("InstanceType", (a, b) => a === b)) {
|
|
19232
|
+
if (properties["InstanceType"] === void 0) {
|
|
19233
|
+
if (context?.replayingState === true) this.logger.warn(safeMsg`${logicalId} (${resourceType}): the state being restored does not declare InstanceType; the rollback leaves the instance type at its current AWS value.`);
|
|
19234
|
+
else throw refusedBeforeApplying(new ProvisioningError(safeMsg`${logicalId} (${resourceType}): InstanceType was removed from the template, and CloudFormation fails that update for an existing instance. Keep it declared (set it to the instance's current type to leave it unchanged). The instance was not updated.`, resourceType, logicalId, physicalId));
|
|
19235
|
+
} else if (!standInSkips("InstanceType")) plan.instanceType = requireConfigString(properties["InstanceType"], "", "AWS::EC2::Instance InstanceType");
|
|
19236
|
+
}
|
|
19237
|
+
if (changed("UserData", (a, b) => a === b)) {
|
|
19238
|
+
const userData = properties["UserData"];
|
|
19239
|
+
if (userData === void 0) plan.userData = /* @__PURE__ */ new Uint8Array(0);
|
|
19240
|
+
else if (!standInSkips("UserData")) {
|
|
19241
|
+
if (typeof userData !== "string") throw refusedBeforeApplying(new ProvisioningError(`${logicalId} (${resourceType}): UserData must be a base64 string (Fn::Base64), got a ${Array.isArray(userData) ? "list" : typeof userData}. The instance was not updated.`, resourceType, logicalId, physicalId));
|
|
19242
|
+
plan.userData = new Uint8Array(Buffer.from(userData, "base64"));
|
|
19243
|
+
}
|
|
19244
|
+
}
|
|
19245
|
+
if (changed("IamInstanceProfile", (a, b) => instanceProfileKey(a) === instanceProfileKey(b))) {
|
|
19246
|
+
if (properties["IamInstanceProfile"] === void 0) plan.profile = { kind: "remove" };
|
|
19247
|
+
else if (!standInSkips("IamInstanceProfile")) {
|
|
19248
|
+
const desired = this.normalizeIamInstanceProfile(properties["IamInstanceProfile"]);
|
|
19249
|
+
if (desired === void 0) throw refusedBeforeApplying(new ProvisioningError(`${logicalId} (${resourceType}): IamInstanceProfile is neither a profile name, an ARN, nor an {Arn,Name} object. The instance was not updated.`, resourceType, logicalId, physicalId));
|
|
19250
|
+
plan.profile = {
|
|
19251
|
+
kind: "set",
|
|
19252
|
+
...desired
|
|
19253
|
+
};
|
|
19254
|
+
}
|
|
19255
|
+
}
|
|
19256
|
+
if (changed("SecurityGroupIds", (a, b) => sameStringSet(a, b))) {
|
|
19257
|
+
const groups = properties["SecurityGroupIds"];
|
|
19258
|
+
if (groups === void 0) plan.securityGroups = { kind: "vpc-default" };
|
|
19259
|
+
else {
|
|
19260
|
+
const ids = Array.isArray(groups) ? groups : void 0;
|
|
19261
|
+
if (ids === void 0 || ids.length === 0 || !ids.every((g) => typeof g === "string" && g !== "")) throw refusedBeforeApplying(new ProvisioningError(`${logicalId} (${resourceType}): SecurityGroupIds must be a non-empty list of security group ids. The instance was not updated.`, resourceType, logicalId, physicalId));
|
|
19262
|
+
if (!standInSkips("SecurityGroupIds")) plan.securityGroups = {
|
|
19263
|
+
kind: "set",
|
|
19264
|
+
ids
|
|
19265
|
+
};
|
|
19266
|
+
}
|
|
19267
|
+
}
|
|
19268
|
+
const beforeBdm = previousProperties["BlockDeviceMappings"];
|
|
19269
|
+
const afterBdm = properties["BlockDeviceMappings"];
|
|
19270
|
+
if (afterBdm !== void 0 && (context?.changedProperties === void 0 || context.changedProperties.has("BlockDeviceMappings")) && blockDeviceMappingsDifferOnlyInDeleteOnTermination(beforeBdm, afterBdm)) {
|
|
19271
|
+
const flips = [];
|
|
19272
|
+
afterBdm.forEach((m, i) => {
|
|
19273
|
+
const before = beforeBdm[i];
|
|
19274
|
+
const read = (x) => {
|
|
19275
|
+
const ebs = x?.["Ebs"];
|
|
19276
|
+
if (ebs === void 0 || ebs === null) return void 0;
|
|
19277
|
+
return this.coerceBool(ebs["DeleteOnTermination"]) ?? true;
|
|
19278
|
+
};
|
|
19279
|
+
const want = read(m);
|
|
19280
|
+
if (want !== void 0 && want !== read(before) && typeof m["DeviceName"] === "string") flips.push({
|
|
19281
|
+
DeviceName: m["DeviceName"],
|
|
19282
|
+
DeleteOnTermination: want
|
|
19283
|
+
});
|
|
19284
|
+
});
|
|
19285
|
+
if (flips.length > 0) plan.deleteOnTermination = flips;
|
|
19286
|
+
}
|
|
19287
|
+
return plan;
|
|
19288
|
+
}
|
|
19289
|
+
async prepareInstanceMemberUpdates(logicalId, physicalId, resourceType, plan) {
|
|
19290
|
+
const needsStop = plan.instanceType !== void 0 || plan.userData !== void 0;
|
|
19291
|
+
const needsDefaultGroup = plan.securityGroups?.kind === "vpc-default";
|
|
19292
|
+
if (!needsStop && !needsDefaultGroup) return;
|
|
19293
|
+
const instance = (await this.ec2Client.send(new DescribeInstancesCommand({ InstanceIds: [physicalId] }))).Reservations?.[0]?.Instances?.[0];
|
|
19294
|
+
if (needsStop) {
|
|
19295
|
+
const members = [plan.instanceType !== void 0 ? "InstanceType" : "", plan.userData !== void 0 ? "UserData" : ""].filter(Boolean).join(" and ");
|
|
19296
|
+
if (instance?.RootDeviceType === "instance-store") throw markRefusedBeforeApplying(new ResourceUpdateNotSupportedError(resourceType, logicalId, `${members} can change only on a stopped instance, and an instance-store-backed instance cannot be stopped; CloudFormation replaces it. Re-deploy with cdkd deploy --replace.`));
|
|
19297
|
+
const state = instance?.State?.Name;
|
|
19298
|
+
if (!STOPPABLE_INSTANCE_STATES.has(state ?? "")) throw refusedBeforeApplying(new ProvisioningError(`${logicalId} (${resourceType}): instance ${physicalId} is ${state ?? "not returned by DescribeInstances"}, so its ${members} cannot be changed. The instance was not updated.`, resourceType, logicalId, physicalId));
|
|
19299
|
+
}
|
|
19300
|
+
if (needsDefaultGroup) plan.securityGroups = {
|
|
19301
|
+
kind: "set",
|
|
19302
|
+
ids: [await this.vpcDefaultSecurityGroupId(logicalId, physicalId, resourceType, instance?.VpcId)]
|
|
19303
|
+
};
|
|
19304
|
+
}
|
|
19305
|
+
async applyInstanceMemberUpdates(logicalId, physicalId, resourceType, plan) {
|
|
19306
|
+
const applied = [];
|
|
19307
|
+
if (plan.securityGroups?.kind === "set") {
|
|
19308
|
+
await this.ec2Client.send(new ModifyInstanceAttributeCommand({
|
|
19309
|
+
InstanceId: physicalId,
|
|
19310
|
+
Groups: plan.securityGroups.ids
|
|
19311
|
+
}));
|
|
19312
|
+
applied.push("the new SecurityGroupIds");
|
|
19313
|
+
}
|
|
19314
|
+
if (plan.profile !== void 0) {
|
|
19315
|
+
await this.applyInstanceProfileChange(logicalId, physicalId, plan.profile);
|
|
19316
|
+
applied.push(plan.profile.kind === "remove" ? "the IamInstanceProfile removed" : "the new IamInstanceProfile");
|
|
19317
|
+
}
|
|
19318
|
+
if (plan.deleteOnTermination !== void 0) {
|
|
19319
|
+
await this.ec2Client.send(new ModifyInstanceAttributeCommand({
|
|
19320
|
+
InstanceId: physicalId,
|
|
19321
|
+
BlockDeviceMappings: plan.deleteOnTermination.map((f) => ({
|
|
19322
|
+
DeviceName: f.DeviceName,
|
|
19323
|
+
Ebs: { DeleteOnTermination: f.DeleteOnTermination }
|
|
19324
|
+
}))
|
|
19325
|
+
}));
|
|
19326
|
+
applied.push("the new DeleteOnTermination");
|
|
19327
|
+
}
|
|
19328
|
+
if (plan.instanceType === void 0 && plan.userData === void 0) {
|
|
19329
|
+
if (instancesLeftStoppedByCdkd.has(physicalId)) {
|
|
19330
|
+
let state = await this.readInstanceState(physicalId);
|
|
19331
|
+
if (state === "stopping") state = await this.waitForInstanceState(logicalId, physicalId, resourceType, "stopped");
|
|
19332
|
+
if (state === "stopped") await this.ec2Client.send(new StartInstancesCommand({ InstanceIds: [physicalId] }));
|
|
19333
|
+
instancesLeftStoppedByCdkd.delete(physicalId);
|
|
19334
|
+
}
|
|
19335
|
+
return;
|
|
19336
|
+
}
|
|
19337
|
+
let state = await this.readInstanceState(physicalId);
|
|
19338
|
+
if (state === "pending") state = await this.waitForInstanceState(logicalId, physicalId, resourceType, "running");
|
|
19339
|
+
else if (state === "stopping") state = await this.waitForInstanceState(logicalId, physicalId, resourceType, "stopped");
|
|
19340
|
+
if (state !== "stopped" && state !== "running") throw markNonRetryable(new ProvisioningError(`${logicalId} (${resourceType}): instance ${physicalId} became ${state ?? "not returned by DescribeInstances"} during the update, so its InstanceType / UserData were not changed`, resourceType, logicalId, physicalId));
|
|
19341
|
+
const startAfter = state === "running" || instancesLeftStoppedByCdkd.has(physicalId);
|
|
19342
|
+
let phase = "stop";
|
|
19343
|
+
let stopIssued = false;
|
|
19344
|
+
try {
|
|
19345
|
+
if (state === "running") {
|
|
19346
|
+
this.logger.info(safeMsg`Stopping EC2 Instance ${logicalId} (${physicalId}) to change its ${plan.instanceType !== void 0 ? "InstanceType" : ""}${plan.instanceType !== void 0 && plan.userData !== void 0 ? " and " : ""}${plan.userData !== void 0 ? "UserData" : ""}; it is started again afterwards`);
|
|
19347
|
+
await this.ec2Client.send(new StopInstancesCommand({ InstanceIds: [physicalId] }));
|
|
19348
|
+
stopIssued = true;
|
|
19349
|
+
await this.waitForInstanceState(logicalId, physicalId, resourceType, "stopped");
|
|
19350
|
+
}
|
|
19351
|
+
phase = "modify";
|
|
19352
|
+
if (plan.instanceType !== void 0) {
|
|
19353
|
+
await this.ec2Client.send(new ModifyInstanceAttributeCommand({
|
|
19354
|
+
InstanceId: physicalId,
|
|
19355
|
+
InstanceType: { Value: plan.instanceType }
|
|
19356
|
+
}));
|
|
19357
|
+
applied.push("the new InstanceType");
|
|
19358
|
+
}
|
|
19359
|
+
if (plan.userData !== void 0) {
|
|
19360
|
+
await this.ec2Client.send(new ModifyInstanceAttributeCommand({
|
|
19361
|
+
InstanceId: physicalId,
|
|
19362
|
+
UserData: { Value: plan.userData }
|
|
19363
|
+
}));
|
|
19364
|
+
applied.push("the new UserData");
|
|
19365
|
+
}
|
|
19366
|
+
if (!startAfter) return;
|
|
19367
|
+
phase = "start";
|
|
19368
|
+
await this.ec2Client.send(new StartInstancesCommand({ InstanceIds: [physicalId] }));
|
|
19369
|
+
instancesLeftStoppedByCdkd.delete(physicalId);
|
|
19370
|
+
if (process.env["CDKD_NO_WAIT"] === "true") {
|
|
19371
|
+
this.logger.debug(safeMsg`Instance ${physicalId} started (skipping running-state wait per --no-wait)`);
|
|
19372
|
+
return;
|
|
19373
|
+
}
|
|
19374
|
+
phase = "wait";
|
|
19375
|
+
await this.waitForInstanceState(logicalId, physicalId, resourceType, "running", { stoppedIsTerminal: true });
|
|
19376
|
+
} catch (error) {
|
|
19377
|
+
const carries = applied.length === 0 ? "its previous settings" : `${applied.join(" and ")} already applied`;
|
|
19378
|
+
const startCommand = `aws ec2 start-instances --instance-ids ${physicalId}`;
|
|
19379
|
+
if (phase === "stop" && !stopIssued) throw error;
|
|
19380
|
+
if (phase === "wait") {
|
|
19381
|
+
if (instanceStoppedAfterStart.has(error)) {
|
|
19382
|
+
instancesLeftStoppedByCdkd.add(physicalId);
|
|
19383
|
+
this.logger.warn(safeMsg`${logicalId}: instance ${physicalId} stopped again right after cdkd started it, with ${carries}. Start it with: ${startCommand}`);
|
|
19384
|
+
}
|
|
19385
|
+
throw error;
|
|
19386
|
+
}
|
|
19387
|
+
if (!stopIssued && !startAfter) throw error;
|
|
19388
|
+
if (phase !== "start" && !isInterruptedWaitError(error) && !enclosingDeadlineExpired()) {
|
|
19389
|
+
let startFailure;
|
|
19390
|
+
try {
|
|
19391
|
+
await this.ec2Client.send(new StartInstancesCommand({ InstanceIds: [physicalId] }));
|
|
19392
|
+
} catch (e) {
|
|
19393
|
+
startFailure = e ?? /* @__PURE__ */ new Error("StartInstances failed");
|
|
19394
|
+
}
|
|
19395
|
+
if (startFailure === void 0) {
|
|
19396
|
+
instancesLeftStoppedByCdkd.delete(physicalId);
|
|
19397
|
+
this.logger.warn(safeMsg`${logicalId}: the InstanceType / UserData change failed after instance ${physicalId} was stopped; cdkd started it again, with ${carries}.`);
|
|
19398
|
+
} else {
|
|
19399
|
+
instancesLeftStoppedByCdkd.add(physicalId);
|
|
19400
|
+
this.logger.warn(safeMsg`${logicalId}: instance ${physicalId} was stopped for an InstanceType / UserData change that failed, and starting it again failed too (${describeAwsFailure(startFailure).summary}); it is stopped, with ${carries}. Start it with: ${startCommand}`);
|
|
19401
|
+
}
|
|
19402
|
+
throw error;
|
|
19403
|
+
}
|
|
19404
|
+
instancesLeftStoppedByCdkd.add(physicalId);
|
|
19405
|
+
this.logger.warn(phase === "stop" ? safeMsg`${logicalId}: instance ${physicalId} was being stopped for an InstanceType / UserData change that did not finish. Once it is stopped, start it with: ${startCommand}` : safeMsg`${logicalId}: instance ${physicalId} is stopped, with ${carries}; cdkd did not start it again. Start it with: ${startCommand}`);
|
|
19406
|
+
throw error;
|
|
19407
|
+
}
|
|
19408
|
+
}
|
|
19409
|
+
async readInstanceState(physicalId) {
|
|
19410
|
+
return (await this.ec2Client.send(new DescribeInstancesCommand({ InstanceIds: [physicalId] }))).Reservations?.[0]?.Instances?.[0]?.State?.Name;
|
|
19411
|
+
}
|
|
19412
|
+
async waitForInstanceState(logicalId, physicalId, resourceType, target, opts = {}) {
|
|
19413
|
+
const watch = startInterruptWatch(`EC2 Instance ${logicalId} ${target} wait`);
|
|
19414
|
+
const capAt = Date.now() + INSTANCE_STATE_WAIT_CAP_MS;
|
|
19415
|
+
let last;
|
|
19416
|
+
let stoppedReads = 0;
|
|
19417
|
+
try {
|
|
19418
|
+
for (;;) {
|
|
19419
|
+
if (watch.isInterrupted()) throw watch.onInterrupted();
|
|
19420
|
+
if (Math.min(enclosingDeadlineRemainingMs(), capAt - Date.now()) <= 0) throw markNonRetryable(new ProvisioningError(`${logicalId} (${resourceType}): timed out waiting for instance ${physicalId} to be ${target} (last state: ${last ?? "none reported"})`, resourceType, logicalId, physicalId));
|
|
19421
|
+
const previous = last;
|
|
19422
|
+
last = await this.readInstanceState(physicalId);
|
|
19423
|
+
if (last === target) return last;
|
|
19424
|
+
stoppedReads = last === "stopped" ? stoppedReads + 1 : 0;
|
|
19425
|
+
if (opts.stoppedIsTerminal === true && last === "stopped" && (previous === "pending" || stoppedReads >= STOPPED_AFTER_START_READS)) {
|
|
19426
|
+
const stopped = markNonRetryable(new ProvisioningError(`${logicalId} (${resourceType}): instance ${physicalId} stopped again right after it was started; run \`aws ec2 describe-instances --instance-ids ${physicalId}\` and read StateReason for AWS's cause`, resourceType, logicalId, physicalId));
|
|
19427
|
+
instanceStoppedAfterStart.add(stopped);
|
|
19428
|
+
throw stopped;
|
|
19429
|
+
}
|
|
19430
|
+
if (last === "terminated" || last === "shutting-down" || last === void 0) throw markNonRetryable(new ProvisioningError(`${logicalId} (${resourceType}): instance ${physicalId} is ${last ?? "no longer returned by DescribeInstances"} while cdkd waited for it to be ${target}`, resourceType, logicalId, physicalId));
|
|
19431
|
+
if (watch.isInterrupted()) throw watch.onInterrupted();
|
|
19432
|
+
await this.sleep(Math.max(0, Math.min(INSTANCE_STATE_POLL_MS, enclosingDeadlineRemainingMs())));
|
|
19433
|
+
}
|
|
19434
|
+
} finally {
|
|
19435
|
+
watch.dispose();
|
|
19436
|
+
}
|
|
19437
|
+
}
|
|
19438
|
+
async vpcDefaultSecurityGroupId(logicalId, physicalId, resourceType, vpcId) {
|
|
19439
|
+
const id = (vpcId === void 0 ? void 0 : await this.ec2Client.send(new DescribeSecurityGroupsCommand({ Filters: [{
|
|
19440
|
+
Name: "vpc-id",
|
|
19441
|
+
Values: [vpcId]
|
|
19442
|
+
}, {
|
|
19443
|
+
Name: "group-name",
|
|
19444
|
+
Values: ["default"]
|
|
19445
|
+
}] })))?.SecurityGroups?.[0]?.GroupId;
|
|
19446
|
+
if (id === void 0) throw refusedBeforeApplying(new ProvisioningError(`${logicalId} (${resourceType}): SecurityGroupIds was removed, and the default security group of instance ${physicalId}'s VPC (${vpcId ?? "unknown"}) could not be found to put in its place. The instance was not updated.`, resourceType, logicalId, physicalId));
|
|
19447
|
+
return id;
|
|
19448
|
+
}
|
|
19449
|
+
async applyInstanceProfileChange(logicalId, physicalId, change) {
|
|
19450
|
+
let assoc = await this.ec2Client.send(new DescribeIamInstanceProfileAssociationsCommand({ Filters: [{
|
|
19451
|
+
Name: "instance-id",
|
|
19452
|
+
Values: [physicalId]
|
|
19453
|
+
}] }));
|
|
19454
|
+
for (let poll = 1; poll <= PROFILE_DISASSOCIATING_POLLS && (assoc.IamInstanceProfileAssociations ?? []).some((a) => a.State === "disassociating"); poll++) {
|
|
19455
|
+
await this.sleep(PROFILE_DISASSOCIATING_DELAY_MS);
|
|
19456
|
+
assoc = await this.ec2Client.send(new DescribeIamInstanceProfileAssociationsCommand({ Filters: [{
|
|
19457
|
+
Name: "instance-id",
|
|
19458
|
+
Values: [physicalId]
|
|
19459
|
+
}] }));
|
|
19460
|
+
}
|
|
19461
|
+
const current = assoc.IamInstanceProfileAssociations?.find((a) => a.State === "associated" || a.State === "associating");
|
|
19462
|
+
if (change.kind === "remove") {
|
|
19463
|
+
if (current?.AssociationId === void 0) return;
|
|
19464
|
+
await this.ec2Client.send(new DisassociateIamInstanceProfileCommand({ AssociationId: current.AssociationId }));
|
|
19465
|
+
return;
|
|
19466
|
+
}
|
|
19467
|
+
const spec = change.arn !== void 0 ? { Arn: change.arn } : { Name: change.name };
|
|
19468
|
+
const maxAttempts = 10;
|
|
19469
|
+
for (let attempt = 1;; attempt++) try {
|
|
19470
|
+
if (current?.AssociationId !== void 0) await this.ec2Client.send(new ReplaceIamInstanceProfileAssociationCommand({
|
|
19471
|
+
AssociationId: current.AssociationId,
|
|
19472
|
+
IamInstanceProfile: spec
|
|
19473
|
+
}));
|
|
19474
|
+
else await this.ec2Client.send(new AssociateIamInstanceProfileCommand({
|
|
19475
|
+
InstanceId: physicalId,
|
|
19476
|
+
IamInstanceProfile: spec
|
|
19477
|
+
}));
|
|
19478
|
+
return;
|
|
19479
|
+
} catch (error) {
|
|
19480
|
+
const msg = describeAwsFailure(error).detail;
|
|
19481
|
+
if (this.isInstanceProfilePropagationError(msg) && attempt < maxAttempts) {
|
|
19482
|
+
this.logger.debug(safeMsg`IAM instance profile not yet propagated for ${logicalId} (${physicalId}) (attempt ${attempt}/${maxAttempts}: ${msg}), retrying in ${attempt}s...`);
|
|
19483
|
+
await this.sleep(attempt * 1e3);
|
|
19484
|
+
continue;
|
|
19485
|
+
}
|
|
19486
|
+
throw error;
|
|
19487
|
+
}
|
|
19488
|
+
}
|
|
18953
19489
|
shallowEqual(a, b) {
|
|
18954
19490
|
if (b === void 0) return false;
|
|
18955
19491
|
const ra = a;
|
|
@@ -19140,7 +19676,7 @@ var EC2Provider = class {
|
|
|
19140
19676
|
const raw = obj["CPUCredits"] ?? obj["CpuCredits"];
|
|
19141
19677
|
return typeof raw === "string" ? raw : void 0;
|
|
19142
19678
|
}
|
|
19143
|
-
buildIpPermission(properties, direction = "ingress") {
|
|
19679
|
+
buildIpPermission(properties, direction = "ingress", inline = false) {
|
|
19144
19680
|
const ipProtocol = properties["IpProtocol"] ?? "-1";
|
|
19145
19681
|
const fromPort = properties["FromPort"];
|
|
19146
19682
|
const toPort = properties["ToPort"];
|
|
@@ -19161,8 +19697,9 @@ var EC2Provider = class {
|
|
|
19161
19697
|
permission.Ipv6Ranges = [ipv6Range];
|
|
19162
19698
|
}
|
|
19163
19699
|
const peerGroupId = direction === "egress" ? properties["DestinationSecurityGroupId"] : properties["SourceSecurityGroupId"];
|
|
19164
|
-
|
|
19165
|
-
|
|
19700
|
+
const peerGroupName = inline && direction === "ingress" ? properties["SourceSecurityGroupName"] : void 0;
|
|
19701
|
+
if (peerGroupId || peerGroupName) {
|
|
19702
|
+
const groupPair = peerGroupId ? { GroupId: peerGroupId } : { GroupName: peerGroupName };
|
|
19166
19703
|
if (direction === "ingress") {
|
|
19167
19704
|
const peerOwnerId = properties["SourceSecurityGroupOwnerId"];
|
|
19168
19705
|
if (peerOwnerId) groupPair.UserId = peerOwnerId;
|
|
@@ -19183,6 +19720,7 @@ var EC2Provider = class {
|
|
|
19183
19720
|
const peerKey = direction === "egress" ? rule["DestinationSecurityGroupId"] : rule["SourceSecurityGroupId"];
|
|
19184
19721
|
const prefixKey = direction === "egress" ? rule["DestinationPrefixListId"] : rule["SourcePrefixListId"];
|
|
19185
19722
|
const peerOwner = direction === "ingress" ? rule["SourceSecurityGroupOwnerId"] : void 0;
|
|
19723
|
+
const peerName = direction === "ingress" ? rule["SourceSecurityGroupName"] : void 0;
|
|
19186
19724
|
return JSON.stringify({
|
|
19187
19725
|
p: sgProtocolKey(rule["IpProtocol"]),
|
|
19188
19726
|
f: rule["FromPort"] ?? null,
|
|
@@ -19190,6 +19728,7 @@ var EC2Provider = class {
|
|
|
19190
19728
|
c4: rule["CidrIp"] ?? null,
|
|
19191
19729
|
c6: rule["CidrIpv6"] ?? null,
|
|
19192
19730
|
peer: peerKey ?? null,
|
|
19731
|
+
peerName: peerKey ? null : peerName ?? null,
|
|
19193
19732
|
peerOwner: peerOwner ?? null,
|
|
19194
19733
|
pl: prefixKey ?? null,
|
|
19195
19734
|
d: rule["Description"] ?? null
|
|
@@ -19218,7 +19757,7 @@ var EC2Provider = class {
|
|
|
19218
19757
|
}));
|
|
19219
19758
|
else await this.ec2Client.send(new RevokeSecurityGroupIngressCommand({
|
|
19220
19759
|
GroupId: groupId,
|
|
19221
|
-
IpPermissions: [this.buildIpPermission(rule, "ingress")]
|
|
19760
|
+
IpPermissions: [this.buildIpPermission(rule, "ingress", true)]
|
|
19222
19761
|
}));
|
|
19223
19762
|
} catch (error) {
|
|
19224
19763
|
if (!this.isNotFoundError(error)) throw error;
|
|
@@ -19231,7 +19770,7 @@ var EC2Provider = class {
|
|
|
19231
19770
|
}));
|
|
19232
19771
|
else await this.ec2Client.send(new AuthorizeSecurityGroupIngressCommand({
|
|
19233
19772
|
GroupId: groupId,
|
|
19234
|
-
IpPermissions: [this.buildIpPermission(rule, "ingress")]
|
|
19773
|
+
IpPermissions: [this.buildIpPermission(rule, "ingress", true)]
|
|
19235
19774
|
}));
|
|
19236
19775
|
} catch (error) {
|
|
19237
19776
|
if (!(error instanceof Error && error.message.includes("already exists"))) throw error;
|
|
@@ -19364,7 +19903,7 @@ var EC2Provider = class {
|
|
|
19364
19903
|
const egress = properties["Egress"] ?? false;
|
|
19365
19904
|
const parts = physicalId.split("|");
|
|
19366
19905
|
if (parts.length !== 3) throw new ProvisioningError(compositeIdFormatMessage(EC2_NETWORK_ACL_ENTRY_ID_FORMAT, logicalId, physicalId), resourceType, logicalId, physicalId);
|
|
19367
|
-
if (typeof networkAclId !== "string" || ruleNumber === void 0 || parts[0] !== networkAclId || parts[1] !== String(ruleNumber) || parts[2] !== String(egress)) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "NetworkAclId, RuleNumber and Egress identify the entry and are createOnly; a change to any of them requires a new entry. Re-deploy with cdkd deploy --replace, or destroy + redeploy
|
|
19906
|
+
if (typeof networkAclId !== "string" || ruleNumber === void 0 || parts[0] !== networkAclId || parts[1] !== String(ruleNumber) || parts[2] !== String(egress)) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "NetworkAclId, RuleNumber and Egress identify the entry and are createOnly; a change to any of them requires a new entry. Re-deploy with cdkd deploy --replace, or destroy + redeploy");
|
|
19368
19907
|
if (properties["Protocol"] == null || !properties["RuleAction"]) throw new ProvisioningError(`Protocol and RuleAction are required for NetworkAclEntry ${logicalId}`, resourceType, logicalId, physicalId);
|
|
19369
19908
|
const ruleParams = networkAclEntryRuleParams(properties, properties["Icmp"] !== void 0 && properties["IcmpTypeCode"] !== void 0 && JSON.stringify(properties["Icmp"]) === JSON.stringify(previousProperties["Icmp"]) && JSON.stringify(properties["IcmpTypeCode"]) !== JSON.stringify(previousProperties["IcmpTypeCode"]));
|
|
19370
19909
|
if (context?.desiredFromAwsReadback === true && ruleParams.CidrBlock !== void 0 && ruleParams.Ipv6CidrBlock !== void 0) {
|
|
@@ -24558,6 +25097,8 @@ function camelToPascalCaseKeys(value, preserveKeys) {
|
|
|
24558
25097
|
|
|
24559
25098
|
//#endregion
|
|
24560
25099
|
//#region src/provisioning/providers/agentcore-runtime-provider.ts
|
|
25100
|
+
const CFN_MAP_KEYS = /* @__PURE__ */ new Set(["Tags", "AdvertisedScopeMapping"]);
|
|
25101
|
+
const SDK_MAP_KEYS = /* @__PURE__ */ new Set(["tags", "advertisedScopeMapping"]);
|
|
24561
25102
|
var AgentCoreRuntimeProvider = class {
|
|
24562
25103
|
client;
|
|
24563
25104
|
logger = getLogger().child("AgentCoreRuntimeProvider");
|
|
@@ -24595,16 +25136,16 @@ var AgentCoreRuntimeProvider = class {
|
|
|
24595
25136
|
agentRuntimeName,
|
|
24596
25137
|
roleArn
|
|
24597
25138
|
};
|
|
24598
|
-
if (properties["AgentRuntimeArtifact"] !== void 0) input["agentRuntimeArtifact"] = pascalToCamelCaseKeys(properties["AgentRuntimeArtifact"]);
|
|
24599
|
-
if (properties["NetworkConfiguration"] !== void 0) input["networkConfiguration"] = pascalToCamelCaseKeys(properties["NetworkConfiguration"]);
|
|
25139
|
+
if (properties["AgentRuntimeArtifact"] !== void 0) input["agentRuntimeArtifact"] = pascalToCamelCaseKeys(properties["AgentRuntimeArtifact"], CFN_MAP_KEYS);
|
|
25140
|
+
if (properties["NetworkConfiguration"] !== void 0) input["networkConfiguration"] = pascalToCamelCaseKeys(properties["NetworkConfiguration"], CFN_MAP_KEYS);
|
|
24600
25141
|
if (properties["Description"] !== void 0) input["description"] = properties["Description"];
|
|
24601
|
-
if (properties["AuthorizerConfiguration"] !== void 0) input["authorizerConfiguration"] = pascalToCamelCaseKeys(properties["AuthorizerConfiguration"]);
|
|
25142
|
+
if (properties["AuthorizerConfiguration"] !== void 0) input["authorizerConfiguration"] = pascalToCamelCaseKeys(properties["AuthorizerConfiguration"], CFN_MAP_KEYS);
|
|
24602
25143
|
if (properties["ProtocolConfiguration"] !== void 0) {
|
|
24603
25144
|
const proto = properties["ProtocolConfiguration"];
|
|
24604
25145
|
if (typeof proto === "string") input["protocolConfiguration"] = { serverProtocol: proto };
|
|
24605
|
-
else input["protocolConfiguration"] = pascalToCamelCaseKeys(proto);
|
|
25146
|
+
else input["protocolConfiguration"] = pascalToCamelCaseKeys(proto, CFN_MAP_KEYS);
|
|
24606
25147
|
}
|
|
24607
|
-
if (properties["LifecycleConfiguration"] !== void 0 && typeof properties["LifecycleConfiguration"] === "object" && properties["LifecycleConfiguration"] !== null && Object.keys(properties["LifecycleConfiguration"]).length > 0) input["lifecycleConfiguration"] = pascalToCamelCaseKeys(properties["LifecycleConfiguration"]);
|
|
25148
|
+
if (properties["LifecycleConfiguration"] !== void 0 && typeof properties["LifecycleConfiguration"] === "object" && properties["LifecycleConfiguration"] !== null && Object.keys(properties["LifecycleConfiguration"]).length > 0) input["lifecycleConfiguration"] = pascalToCamelCaseKeys(properties["LifecycleConfiguration"], CFN_MAP_KEYS);
|
|
24608
25149
|
if (properties["EnvironmentVariables"] !== void 0) input["environmentVariables"] = properties["EnvironmentVariables"];
|
|
24609
25150
|
if (properties["ClientToken"] !== void 0) input["clientToken"] = properties["ClientToken"];
|
|
24610
25151
|
const response = await this.client.send(new CreateAgentRuntimeCommand(input));
|
|
@@ -24630,16 +25171,16 @@ var AgentCoreRuntimeProvider = class {
|
|
|
24630
25171
|
agentRuntimeId: physicalId,
|
|
24631
25172
|
roleArn
|
|
24632
25173
|
};
|
|
24633
|
-
if (properties["AgentRuntimeArtifact"] !== void 0) input["agentRuntimeArtifact"] = pascalToCamelCaseKeys(properties["AgentRuntimeArtifact"]);
|
|
24634
|
-
if (properties["NetworkConfiguration"] !== void 0) input["networkConfiguration"] = pascalToCamelCaseKeys(properties["NetworkConfiguration"]);
|
|
25174
|
+
if (properties["AgentRuntimeArtifact"] !== void 0) input["agentRuntimeArtifact"] = pascalToCamelCaseKeys(properties["AgentRuntimeArtifact"], CFN_MAP_KEYS);
|
|
25175
|
+
if (properties["NetworkConfiguration"] !== void 0) input["networkConfiguration"] = pascalToCamelCaseKeys(properties["NetworkConfiguration"], CFN_MAP_KEYS);
|
|
24635
25176
|
if (properties["Description"] !== void 0) input["description"] = properties["Description"];
|
|
24636
|
-
if (properties["AuthorizerConfiguration"] !== void 0) input["authorizerConfiguration"] = pascalToCamelCaseKeys(properties["AuthorizerConfiguration"]);
|
|
25177
|
+
if (properties["AuthorizerConfiguration"] !== void 0) input["authorizerConfiguration"] = pascalToCamelCaseKeys(properties["AuthorizerConfiguration"], CFN_MAP_KEYS);
|
|
24637
25178
|
if (properties["ProtocolConfiguration"] !== void 0) {
|
|
24638
25179
|
const proto = properties["ProtocolConfiguration"];
|
|
24639
25180
|
if (typeof proto === "string") input["protocolConfiguration"] = { serverProtocol: proto };
|
|
24640
|
-
else input["protocolConfiguration"] = pascalToCamelCaseKeys(proto);
|
|
25181
|
+
else input["protocolConfiguration"] = pascalToCamelCaseKeys(proto, CFN_MAP_KEYS);
|
|
24641
25182
|
}
|
|
24642
|
-
if (properties["LifecycleConfiguration"] !== void 0 && typeof properties["LifecycleConfiguration"] === "object" && properties["LifecycleConfiguration"] !== null && Object.keys(properties["LifecycleConfiguration"]).length > 0) input["lifecycleConfiguration"] = pascalToCamelCaseKeys(properties["LifecycleConfiguration"]);
|
|
25183
|
+
if (properties["LifecycleConfiguration"] !== void 0 && typeof properties["LifecycleConfiguration"] === "object" && properties["LifecycleConfiguration"] !== null && Object.keys(properties["LifecycleConfiguration"]).length > 0) input["lifecycleConfiguration"] = pascalToCamelCaseKeys(properties["LifecycleConfiguration"], CFN_MAP_KEYS);
|
|
24643
25184
|
if (properties["EnvironmentVariables"] !== void 0) input["environmentVariables"] = properties["EnvironmentVariables"];
|
|
24644
25185
|
if (properties["ClientToken"] !== void 0) input["clientToken"] = properties["ClientToken"];
|
|
24645
25186
|
const response = await this.client.send(new UpdateAgentRuntimeCommand(input));
|
|
@@ -24681,7 +25222,7 @@ var AgentCoreRuntimeProvider = class {
|
|
|
24681
25222
|
if (response.agentRuntimeVersion !== void 0) attributes["AgentRuntimeVersion"] = response.agentRuntimeVersion;
|
|
24682
25223
|
if (response.status !== void 0) attributes["Status"] = response.status;
|
|
24683
25224
|
if (response.createdAt !== void 0) attributes["CreatedAt"] = response.createdAt.toISOString();
|
|
24684
|
-
if (response.workloadIdentityDetails !== void 0) attributes["WorkloadIdentityDetails"] = camelToPascalCaseKeys(response.workloadIdentityDetails);
|
|
25225
|
+
if (response.workloadIdentityDetails !== void 0) attributes["WorkloadIdentityDetails"] = camelToPascalCaseKeys(response.workloadIdentityDetails, SDK_MAP_KEYS);
|
|
24685
25226
|
return attributes;
|
|
24686
25227
|
}
|
|
24687
25228
|
async getAttribute(physicalId, _resourceType, attributeName) {
|
|
@@ -24710,17 +25251,17 @@ var AgentCoreRuntimeProvider = class {
|
|
|
24710
25251
|
const result = {};
|
|
24711
25252
|
if (resp.agentRuntimeName !== void 0) result["AgentRuntimeName"] = resp.agentRuntimeName;
|
|
24712
25253
|
if (resp.roleArn !== void 0) result["RoleArn"] = resp.roleArn;
|
|
24713
|
-
if (resp.agentRuntimeArtifact !== void 0) result["AgentRuntimeArtifact"] = camelToPascalCaseKeys(resp.agentRuntimeArtifact);
|
|
24714
|
-
if (resp.networkConfiguration !== void 0) result["NetworkConfiguration"] = camelToPascalCaseKeys(resp.networkConfiguration);
|
|
25254
|
+
if (resp.agentRuntimeArtifact !== void 0) result["AgentRuntimeArtifact"] = camelToPascalCaseKeys(resp.agentRuntimeArtifact, SDK_MAP_KEYS);
|
|
25255
|
+
if (resp.networkConfiguration !== void 0) result["NetworkConfiguration"] = camelToPascalCaseKeys(resp.networkConfiguration, SDK_MAP_KEYS);
|
|
24715
25256
|
result["Description"] = resp.description ?? "";
|
|
24716
|
-
if (resp.authorizerConfiguration !== void 0) result["AuthorizerConfiguration"] = camelToPascalCaseKeys(resp.authorizerConfiguration);
|
|
25257
|
+
if (resp.authorizerConfiguration !== void 0) result["AuthorizerConfiguration"] = camelToPascalCaseKeys(resp.authorizerConfiguration, SDK_MAP_KEYS);
|
|
24717
25258
|
if (resp.protocolConfiguration !== void 0) {
|
|
24718
25259
|
const proto = resp.protocolConfiguration;
|
|
24719
25260
|
const keys = Object.keys(proto);
|
|
24720
25261
|
if (keys.length === 1 && keys[0] === "serverProtocol" && typeof proto["serverProtocol"] === "string") result["ProtocolConfiguration"] = proto["serverProtocol"];
|
|
24721
|
-
else result["ProtocolConfiguration"] = camelToPascalCaseKeys(resp.protocolConfiguration);
|
|
25262
|
+
else result["ProtocolConfiguration"] = camelToPascalCaseKeys(resp.protocolConfiguration, SDK_MAP_KEYS);
|
|
24722
25263
|
}
|
|
24723
|
-
if (resp.lifecycleConfiguration !== void 0) result["LifecycleConfiguration"] = camelToPascalCaseKeys(resp.lifecycleConfiguration);
|
|
25264
|
+
if (resp.lifecycleConfiguration !== void 0) result["LifecycleConfiguration"] = camelToPascalCaseKeys(resp.lifecycleConfiguration, SDK_MAP_KEYS);
|
|
24724
25265
|
if (resp.environmentVariables !== void 0) result["EnvironmentVariables"] = resp.environmentVariables;
|
|
24725
25266
|
return result;
|
|
24726
25267
|
}
|
|
@@ -29871,7 +30412,7 @@ var DocDBProvider = class {
|
|
|
29871
30412
|
createdResourceId = response.DBCluster?.DbClusterResourceId;
|
|
29872
30413
|
if (!response.DBCluster) throw new Error("CreateDBCluster did not return DBCluster");
|
|
29873
30414
|
this.logger.debug(`Successfully created DocDB DBCluster ${logicalId}: ${dbClusterIdentifier}`);
|
|
29874
|
-
if (process.env["CDKD_NO_WAIT"] !== "true") await this.waitForClusterAvailable(dbClusterIdentifier);
|
|
30415
|
+
if (process.env["CDKD_NO_WAIT"] !== "true") await this.waitForClusterAvailable(logicalId, dbClusterIdentifier);
|
|
29875
30416
|
return {
|
|
29876
30417
|
physicalId: dbClusterIdentifier,
|
|
29877
30418
|
attributes: clusterAttributes(await this.describeDBCluster(dbClusterIdentifier))
|
|
@@ -30026,7 +30567,7 @@ var DocDBProvider = class {
|
|
|
30026
30567
|
createdResourceId = response.DBInstance?.DbiResourceId;
|
|
30027
30568
|
if (!response.DBInstance) throw new Error("CreateDBInstance did not return DBInstance");
|
|
30028
30569
|
this.logger.debug(`Successfully created DocDB DBInstance ${logicalId}: ${dbInstanceIdentifier}`);
|
|
30029
|
-
if (process.env["CDKD_NO_WAIT"] !== "true") await this.waitForInstanceAvailable(dbInstanceIdentifier);
|
|
30570
|
+
if (process.env["CDKD_NO_WAIT"] !== "true") await this.waitForInstanceAvailable(logicalId, dbInstanceIdentifier);
|
|
30030
30571
|
return {
|
|
30031
30572
|
physicalId: dbInstanceIdentifier,
|
|
30032
30573
|
attributes: instanceAttributes(await this.describeDBInstance(dbInstanceIdentifier))
|
|
@@ -30161,7 +30702,7 @@ var DocDBProvider = class {
|
|
|
30161
30702
|
}
|
|
30162
30703
|
requireClusterWhileWaiting(cluster, logicalId, change) {
|
|
30163
30704
|
if (cluster === void 0) throw new Error(safeMsg`DescribeDBClusters returned no cluster for DocDB DBCluster ${logicalId} while waiting for its new ${change}`);
|
|
30164
|
-
if (
|
|
30705
|
+
if (isTerminalDbWaitStatus(cluster.Status)) throw new Error(safeMsg`DocDB DBCluster ${logicalId} entered status ${cluster.Status ?? ""} while applying its new ${change}`);
|
|
30165
30706
|
return cluster;
|
|
30166
30707
|
}
|
|
30167
30708
|
async waitForClusterPortApplied(dbClusterIdentifier, logicalId, port, maxWaitMs = 18e5) {
|
|
@@ -30210,13 +30751,14 @@ var DocDBProvider = class {
|
|
|
30210
30751
|
remainingMs: enclosingDeadlineRemainingMs()
|
|
30211
30752
|
});
|
|
30212
30753
|
}
|
|
30213
|
-
async waitForClusterAvailable(dbClusterIdentifier, maxWaitMs = 18e5) {
|
|
30754
|
+
async waitForClusterAvailable(logicalId, dbClusterIdentifier, maxWaitMs = 18e5) {
|
|
30214
30755
|
const startTime = Date.now();
|
|
30215
30756
|
let delay = 5e3;
|
|
30216
30757
|
while (Date.now() - startTime < maxWaitMs) {
|
|
30217
30758
|
const status = (await this.describeDBCluster(dbClusterIdentifier))?.Status;
|
|
30218
30759
|
this.logger.debug(`DocDB DBCluster ${dbClusterIdentifier} status: ${status}`);
|
|
30219
30760
|
if (status === "available") return;
|
|
30761
|
+
if (isTerminalDbWaitStatus(status)) throw new Error(safeMsg`DocDB DBCluster ${logicalId} entered status ${status ?? ""} while being created, which it does not leave on its own`);
|
|
30220
30762
|
await this.sleep(delay);
|
|
30221
30763
|
delay = Math.min(delay * 2, 1e4);
|
|
30222
30764
|
}
|
|
@@ -30240,13 +30782,14 @@ var DocDBProvider = class {
|
|
|
30240
30782
|
}
|
|
30241
30783
|
throw new Error(`Timed out waiting for DocDB DBCluster ${logicalId} to be deleted`);
|
|
30242
30784
|
}
|
|
30243
|
-
async waitForInstanceAvailable(dbInstanceIdentifier, maxWaitMs = 18e5) {
|
|
30785
|
+
async waitForInstanceAvailable(logicalId, dbInstanceIdentifier, maxWaitMs = 18e5) {
|
|
30244
30786
|
const startTime = Date.now();
|
|
30245
30787
|
let delay = 1e4;
|
|
30246
30788
|
while (Date.now() - startTime < maxWaitMs) {
|
|
30247
30789
|
const status = (await this.describeDBInstance(dbInstanceIdentifier))?.DBInstanceStatus;
|
|
30248
30790
|
this.logger.debug(`DocDB DBInstance ${dbInstanceIdentifier} status: ${status}`);
|
|
30249
30791
|
if (status === "available") return;
|
|
30792
|
+
if (isTerminalDbWaitStatus(status)) throw new Error(safeMsg`DocDB DBInstance ${logicalId} entered status ${status ?? ""} while being created, which it does not leave on its own`);
|
|
30250
30793
|
await this.sleep(delay);
|
|
30251
30794
|
delay = Math.min(delay * 2, 1e4);
|
|
30252
30795
|
}
|
|
@@ -30511,6 +31054,18 @@ var DocDBSubnetGroupProvider = class {
|
|
|
30511
31054
|
function isZoneDisabledForMutationError(error) {
|
|
30512
31055
|
return error instanceof Error && error.message.includes("is marked disabled for mutation");
|
|
30513
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
|
+
]);
|
|
30514
31069
|
var HostedZoneNameNotFoundError = class HostedZoneNameNotFoundError extends ProvisioningError {
|
|
30515
31070
|
constructor(message, resourceType, logicalId, physicalId, cause) {
|
|
30516
31071
|
super(message, resourceType, logicalId, physicalId, cause);
|
|
@@ -30726,26 +31281,29 @@ var Route53Provider = class {
|
|
|
30726
31281
|
}
|
|
30727
31282
|
await this.applyHostedZoneTags(zoneId, properties, logicalId, void 0, mask);
|
|
30728
31283
|
await this.applyQueryLoggingConfig(zoneId, properties, logicalId);
|
|
30729
|
-
if (properties
|
|
30730
|
-
await this.getClient().send(new UpdateHostedZoneFeaturesCommand({
|
|
30731
|
-
HostedZoneId: zoneId,
|
|
30732
|
-
EnableAcceleratedRecovery: true
|
|
30733
|
-
}));
|
|
30734
|
-
} catch (uhfError) {
|
|
30735
|
-
this.logger.error(`UpdateHostedZoneFeatures failed for ${zoneId} after CreateHostedZone — rolling back the hosted zone to keep deploy retry idempotent`);
|
|
31284
|
+
if (declaresAcceleratedRecovery(properties)) {
|
|
30736
31285
|
try {
|
|
30737
|
-
await this.
|
|
30738
|
-
|
|
30739
|
-
|
|
30740
|
-
|
|
30741
|
-
} catch (
|
|
30742
|
-
|
|
30743
|
-
|
|
30744
|
-
|
|
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));
|
|
30745
31305
|
}
|
|
30746
|
-
|
|
30747
|
-
markAuxiliaryFailure(uhfError, logicalId);
|
|
30748
|
-
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);
|
|
30749
31307
|
}
|
|
30750
31308
|
const nameServers = response.DelegationSet?.NameServers ?? [];
|
|
30751
31309
|
this.logger.debug(`Successfully created hosted zone ${logicalId}: ${zoneId}`);
|
|
@@ -30823,12 +31381,15 @@ var Route53Provider = class {
|
|
|
30823
31381
|
await this.applyHostedZoneTags(physicalId, properties, logicalId, previousProperties, mask);
|
|
30824
31382
|
await this.applyQueryLoggingConfig(physicalId, properties, logicalId, previousProperties);
|
|
30825
31383
|
await this.syncVPCAssociations(physicalId, properties, logicalId);
|
|
30826
|
-
const prevEnabled = previousProperties
|
|
30827
|
-
const nextEnabled = properties
|
|
30828
|
-
if (prevEnabled !== nextEnabled)
|
|
30829
|
-
|
|
30830
|
-
|
|
30831
|
-
|
|
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
|
+
}
|
|
30832
31393
|
const nameServers = (await this.getClient().send(new GetHostedZoneCommand({ Id: physicalId }))).DelegationSet?.NameServers ?? [];
|
|
30833
31394
|
this.logger.debug(`Successfully updated hosted zone ${logicalId}`);
|
|
30834
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}`);
|
|
@@ -31083,25 +31644,43 @@ var Route53Provider = class {
|
|
|
31083
31644
|
throw this.wrapDeleteError(context?.maskSecrets, error, (text) => new ProvisioningError(`Failed to delete record set ${logicalId}: ${text}`, resourceType, logicalId, physicalId, cause));
|
|
31084
31645
|
}
|
|
31085
31646
|
}
|
|
31086
|
-
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
|
+
}) {
|
|
31087
31660
|
const client = this.getClient();
|
|
31088
31661
|
const parsedInterval = Number.parseInt(process.env["CDKD_R53_ACCEL_RECOVERY_POLL_INTERVAL_MS"] ?? "15000", 10);
|
|
31089
31662
|
const pollIntervalMs = Number.isFinite(parsedInterval) && parsedInterval > 0 ? parsedInterval : 15e3;
|
|
31090
31663
|
const parsedTimeout = Number.parseInt(process.env["CDKD_R53_ACCEL_RECOVERY_POLL_TIMEOUT_MS"] ?? "600000", 10);
|
|
31091
31664
|
const timeoutMs = Number.isFinite(parsedTimeout) && parsedTimeout > 0 ? parsedTimeout : 6e5;
|
|
31092
31665
|
const deadline = Date.now() + timeoutMs;
|
|
31093
|
-
const TERMINAL_FAILED =
|
|
31094
|
-
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;
|
|
31095
31670
|
while (Date.now() < deadline) {
|
|
31096
31671
|
let status;
|
|
31097
31672
|
try {
|
|
31098
31673
|
status = (await client.send(new GetHostedZoneCommand({ Id: zoneId }))).HostedZone?.Features?.AcceleratedRecoveryStatus;
|
|
31099
31674
|
} catch (err) {
|
|
31100
|
-
if (err instanceof Error && err.name === "NoSuchHostedZone") return;
|
|
31675
|
+
if (err instanceof Error && err.name === "NoSuchHostedZone" && purpose.settledAt === void 0) return;
|
|
31101
31676
|
throw err;
|
|
31102
31677
|
}
|
|
31103
|
-
if (status === void 0
|
|
31104
|
-
|
|
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);
|
|
31105
31684
|
this.logger.debug(`Polling AcceleratedRecoveryStatus for ${zoneId}: ${status} (waiting for a mutable state, will re-poll in ~${pollIntervalMs}ms)`);
|
|
31106
31685
|
const sliceEnd = Math.min(Date.now() + pollIntervalMs, deadline);
|
|
31107
31686
|
while (Date.now() < sliceEnd) {
|
|
@@ -31110,7 +31689,7 @@ var Route53Provider = class {
|
|
|
31110
31689
|
await new Promise((resolve) => setTimeout(resolve, tick));
|
|
31111
31690
|
}
|
|
31112
31691
|
}
|
|
31113
|
-
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);
|
|
31114
31693
|
}
|
|
31115
31694
|
buildResourceRecordSet(properties) {
|
|
31116
31695
|
const name = properties["Name"];
|
|
@@ -31418,7 +31997,8 @@ var Route53Provider = class {
|
|
|
31418
31997
|
const bare = resp.DelegationSet.Id.replace(/^\/delegationset\//, "");
|
|
31419
31998
|
result["DelegationSetId"] = properties?.["DelegationSetId"] === `/delegationset/${bare}` ? `/delegationset/${bare}` : bare;
|
|
31420
31999
|
}
|
|
31421
|
-
|
|
32000
|
+
const acceleratedRecoveryStatus = resp.HostedZone.Features?.AcceleratedRecoveryStatus;
|
|
32001
|
+
if (acceleratedRecoveryStatus !== void 0) result["HostedZoneFeatures"] = { EnableAcceleratedRecovery: ACCELERATED_RECOVERY_ON_STATUSES.has(acceleratedRecoveryStatus) };
|
|
31422
32002
|
if (resp.HostedZone.Config?.PrivateZone === true) result["VPCs"] = (resp.VPCs ?? []).map((v) => {
|
|
31423
32003
|
const out = {};
|
|
31424
32004
|
if (v.VPCId !== void 0) out["VPCId"] = v.VPCId;
|
|
@@ -33179,7 +33759,7 @@ var CognitoUserPoolProvider = class {
|
|
|
33179
33759
|
//#region src/provisioning/providers/elasticache-provider.ts
|
|
33180
33760
|
const CACHE_DELETE_WAIT_MS = Math.max(6e5, slowCcOperationTimeoutMs("AWS::ElastiCache::CacheCluster", "DELETE"));
|
|
33181
33761
|
const NODE_TYPE_MODIFY_WAIT_MS = Math.max(36e5, slowCcOperationTimeoutMs("AWS::ElastiCache::CacheCluster", "UPDATE"));
|
|
33182
|
-
const
|
|
33762
|
+
const MODIFY_DROPPED_AFTER_MS = 12e4;
|
|
33183
33763
|
function availabilityZonesNotCovered(a, b) {
|
|
33184
33764
|
const remaining = [...b];
|
|
33185
33765
|
const out = [];
|
|
@@ -33190,6 +33770,27 @@ function availabilityZonesNotCovered(a, b) {
|
|
|
33190
33770
|
}
|
|
33191
33771
|
return out;
|
|
33192
33772
|
}
|
|
33773
|
+
function nodesToRemove(nodes, desiredCount, desiredZones) {
|
|
33774
|
+
const remainingZones = desiredZones === void 0 ? void 0 : [...desiredZones];
|
|
33775
|
+
const named = nodes.filter((n) => n.id !== void 0);
|
|
33776
|
+
const keep = /* @__PURE__ */ new Set();
|
|
33777
|
+
const unnamed = nodes.length - named.length;
|
|
33778
|
+
const byIdDesc = [...named].sort((a, b) => a.id < b.id ? 1 : a.id > b.id ? -1 : 0);
|
|
33779
|
+
for (const node of byIdDesc) {
|
|
33780
|
+
if (keep.size + unnamed >= desiredCount) break;
|
|
33781
|
+
if (remainingZones === void 0) {
|
|
33782
|
+
keep.add(node.id);
|
|
33783
|
+
continue;
|
|
33784
|
+
}
|
|
33785
|
+
const i = node.zone === void 0 ? -1 : remainingZones.indexOf(node.zone);
|
|
33786
|
+
if (i >= 0) {
|
|
33787
|
+
remainingZones.splice(i, 1);
|
|
33788
|
+
keep.add(node.id);
|
|
33789
|
+
}
|
|
33790
|
+
}
|
|
33791
|
+
if (keep.size + unnamed < desiredCount) return void 0;
|
|
33792
|
+
return named.map((n) => n.id).filter((id) => !keep.has(id)).sort();
|
|
33793
|
+
}
|
|
33193
33794
|
var ElastiCacheProvider = class {
|
|
33194
33795
|
client;
|
|
33195
33796
|
createClient;
|
|
@@ -33407,7 +34008,8 @@ var ElastiCacheProvider = class {
|
|
|
33407
34008
|
const sgIds = rawSgIds && rawSgIds.length > 0 ? rawSgIds : void 0;
|
|
33408
34009
|
const notificationTopicArn = properties["NotificationTopicArn"];
|
|
33409
34010
|
const desiredNodeType = properties["CacheNodeType"];
|
|
33410
|
-
const
|
|
34011
|
+
const nodeChanges = await this.planNodeChanges(logicalId, physicalId, resourceType, properties, previousProperties);
|
|
34012
|
+
const placement = nodeChanges.placement;
|
|
33411
34013
|
this.warnNotAppliedInPlace(logicalId, properties, previousProperties, placement);
|
|
33412
34014
|
await this.getClient().send(new ModifyCacheClusterCommand({
|
|
33413
34015
|
CacheClusterId: physicalId,
|
|
@@ -33417,6 +34019,7 @@ var ElastiCacheProvider = class {
|
|
|
33417
34019
|
NewAvailabilityZones: placement.newAvailabilityZones,
|
|
33418
34020
|
...placement.azMode !== void 0 && { AZMode: placement.azMode }
|
|
33419
34021
|
},
|
|
34022
|
+
...nodeChanges.removeIds.length > 0 && { CacheNodeIdsToRemove: nodeChanges.removeIds },
|
|
33420
34023
|
SecurityGroupIds: sgIds,
|
|
33421
34024
|
CacheParameterGroupName: properties["CacheParameterGroupName"],
|
|
33422
34025
|
EngineVersion: properties["EngineVersion"],
|
|
@@ -33431,7 +34034,7 @@ var ElastiCacheProvider = class {
|
|
|
33431
34034
|
ApplyImmediately: true
|
|
33432
34035
|
}));
|
|
33433
34036
|
this.logger.debug(`Successfully updated CacheCluster ${logicalId}`);
|
|
33434
|
-
if (desiredNodeType !== void 0) await this.waitForClusterAvailable(physicalId, NODE_TYPE_MODIFY_WAIT_MS, desiredNodeType);
|
|
34037
|
+
if (desiredNodeType !== void 0 || nodeChanges.removeIds.length > 0) await this.waitForClusterAvailable(physicalId, NODE_TYPE_MODIFY_WAIT_MS, desiredNodeType, nodeChanges.removeIds);
|
|
33435
34038
|
else await this.waitForClusterAvailable(physicalId);
|
|
33436
34039
|
const described = await this.describeCacheCluster(physicalId);
|
|
33437
34040
|
this.warnTransitEncryptionNotApplied(logicalId, properties, previousProperties, described?.TransitEncryptionEnabled);
|
|
@@ -33495,15 +34098,37 @@ var ElastiCacheProvider = class {
|
|
|
33495
34098
|
const state = current === true ? "ENABLED" : "DISABLED";
|
|
33496
34099
|
this.logger.warn(safeMsg`CacheCluster ${logicalId}: the cluster still has encryption in transit ${state} ` + safeMsg`(the template now says TransitEncryptionEnabled: ${String(next)}). ` + "ModifyCacheCluster cannot change it, and CloudFormation leaves it unchanged too; to change it, replace the cluster, for example by changing its logical ID.");
|
|
33497
34100
|
}
|
|
33498
|
-
async
|
|
33499
|
-
const
|
|
33500
|
-
|
|
33501
|
-
|
|
33502
|
-
|
|
33503
|
-
|
|
34101
|
+
async planNodeChanges(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
34102
|
+
const none = {
|
|
34103
|
+
placement: void 0,
|
|
34104
|
+
removeIds: []
|
|
34105
|
+
};
|
|
34106
|
+
const desiredZones = properties["PreferredAvailabilityZones"];
|
|
34107
|
+
const zones = Array.isArray(desiredZones) && desiredZones.length > 0 ? desiredZones : void 0;
|
|
34108
|
+
if (!(String(properties["NumCacheNodes"]) !== String(previousProperties["NumCacheNodes"])) && (zones === void 0 || isDeepStrictEqual(zones, previousProperties["PreferredAvailabilityZones"]))) return none;
|
|
34109
|
+
if (zones === void 0 && !(Number(properties["NumCacheNodes"]) < Number(previousProperties["NumCacheNodes"]))) return none;
|
|
34110
|
+
const liveNodes = ((await this.describeCacheCluster(physicalId))?.CacheNodes ?? []).map((n) => ({
|
|
34111
|
+
id: n.CacheNodeId,
|
|
34112
|
+
zone: n.CustomerAvailabilityZone
|
|
34113
|
+
}));
|
|
34114
|
+
const desiredCount = properties["NumCacheNodes"] != null ? Number(properties["NumCacheNodes"]) : void 0;
|
|
34115
|
+
const previousCount = Number(previousProperties["NumCacheNodes"]);
|
|
34116
|
+
const templateLowered = Number(properties["NumCacheNodes"]) < previousCount;
|
|
34117
|
+
let removeIds = [];
|
|
34118
|
+
if (templateLowered && desiredCount !== void 0 && desiredCount < liveNodes.length) {
|
|
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);
|
|
34120
|
+
const plan = nodesToRemove(liveNodes, desiredCount, zones);
|
|
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);
|
|
34122
|
+
removeIds = plan;
|
|
34123
|
+
this.logger.info(safeMsg`CacheCluster ${logicalId}: NumCacheNodes ${String(previousProperties["NumCacheNodes"])} -> ${String(desiredCount)}, removing cache nodes ${removeIds.join(", ")}`);
|
|
34124
|
+
}
|
|
34125
|
+
const newAvailabilityZones = zones === void 0 || removeIds.length > 0 ? [] : availabilityZonesNotCovered(zones, liveNodes.filter((n) => n.id === void 0 || !removeIds.includes(n.id)).map((n) => n.zone).filter((z) => typeof z === "string"));
|
|
33504
34126
|
return {
|
|
33505
|
-
newAvailabilityZones
|
|
33506
|
-
|
|
34127
|
+
placement: newAvailabilityZones.length > 0 ? {
|
|
34128
|
+
newAvailabilityZones,
|
|
34129
|
+
azMode: properties["AZMode"]
|
|
34130
|
+
} : void 0,
|
|
34131
|
+
removeIds
|
|
33507
34132
|
};
|
|
33508
34133
|
}
|
|
33509
34134
|
warnNotAppliedInPlace(logicalId, properties, previousProperties, placement) {
|
|
@@ -33577,7 +34202,7 @@ var ElastiCacheProvider = class {
|
|
|
33577
34202
|
ShowCacheNodeInfo: true
|
|
33578
34203
|
}))).CacheClusters?.[0];
|
|
33579
34204
|
}
|
|
33580
|
-
async waitForClusterAvailable(cacheClusterId, maxWaitMs = 6e5, expectedNodeType) {
|
|
34205
|
+
async waitForClusterAvailable(cacheClusterId, maxWaitMs = 6e5, expectedNodeType, removedNodeIds = []) {
|
|
33581
34206
|
const startTime = Date.now();
|
|
33582
34207
|
let delay = 1e4;
|
|
33583
34208
|
while (Date.now() - startTime < maxWaitMs) {
|
|
@@ -33585,12 +34210,14 @@ var ElastiCacheProvider = class {
|
|
|
33585
34210
|
const status = cluster?.CacheClusterStatus;
|
|
33586
34211
|
this.logger.debug(`CacheCluster ${cacheClusterId} status: ${status}`);
|
|
33587
34212
|
const liveNodeType = cluster?.CacheNodeType;
|
|
33588
|
-
|
|
33589
|
-
if (
|
|
34213
|
+
const removalDone = removedNodeIds.length === 0 || cluster?.CacheNodes !== void 0 && !cluster.CacheNodes.some((n) => n.CacheNodeId !== void 0 && removedNodeIds.includes(n.CacheNodeId));
|
|
34214
|
+
if (status === "available" && removalDone && (expectedNodeType === void 0 || liveNodeType === expectedNodeType)) return;
|
|
34215
|
+
if (!removalDone && status === "available" && (cluster?.PendingModifiedValues?.CacheNodeIdsToRemove ?? []).length === 0 && Date.now() - startTime > MODIFY_DROPPED_AFTER_MS) throw new Error(safeMsg`CacheCluster ${cacheClusterId} is available and still lists cache nodes ${removedNodeIds.join(", ")} with no removal pending; the removal was not applied. Check the cluster's events (aws elasticache describe-events) for the reason, then deploy again.`);
|
|
34216
|
+
if (expectedNodeType !== void 0 && liveNodeType !== expectedNodeType && status === "available" && cluster?.PendingModifiedValues?.CacheNodeType === void 0 && Date.now() - startTime > MODIFY_DROPPED_AFTER_MS) throw new Error(safeMsg`CacheCluster ${cacheClusterId} is available with node type ${liveNodeType} and no node-type change pending; the change to ${expectedNodeType} was not applied. Check the cluster's events (aws elasticache describe-events) for the reason, then deploy again.`);
|
|
33590
34217
|
await this.sleep(delay);
|
|
33591
34218
|
delay = Math.min(delay * 2, 1e4);
|
|
33592
34219
|
}
|
|
33593
|
-
throw new Error(expectedNodeType === void 0 ? `Timed out waiting for CacheCluster ${cacheClusterId} to become available` : safeMsg`Timed out waiting for CacheCluster ${cacheClusterId} to become available with node type ${expectedNodeType}`);
|
|
34220
|
+
throw new Error(expectedNodeType === void 0 && removedNodeIds.length === 0 ? `Timed out waiting for CacheCluster ${cacheClusterId} to become available` : safeMsg`Timed out waiting for CacheCluster ${cacheClusterId} to become available` + (expectedNodeType === void 0 ? "" : safeMsg` with node type ${expectedNodeType}`) + (removedNodeIds.length === 0 ? "" : safeMsg` without cache nodes ${removedNodeIds.join(", ")}`));
|
|
33594
34221
|
}
|
|
33595
34222
|
async waitForClusterDeleted(logicalId, cacheClusterId, maxWaitMs = 6e5) {
|
|
33596
34223
|
const startTime = Date.now();
|
|
@@ -37831,15 +38458,20 @@ function desiredGlueTags(raw, resourceType, logicalId, physicalId) {
|
|
|
37831
38458
|
const tags = refuseMalformedDesiredTags(tagMapAsList(raw), resourceType, logicalId, physicalId, "Tags", GLUE_TAGS_WHAT);
|
|
37832
38459
|
return tags.length > 0 ? Object.fromEntries(tags.map((t) => [t.Key, t.Value])) : void 0;
|
|
37833
38460
|
}
|
|
37834
|
-
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
|
+
}) {
|
|
37835
38465
|
const plan = planTagDiff(tagMapAsList(recorded), tagMapAsList(desired));
|
|
37836
38466
|
const warning = tagPlanWarning(plan, resourceType, logicalId);
|
|
37837
38467
|
if (warning !== void 0) warn(warning);
|
|
37838
|
-
|
|
38468
|
+
const toSet = unsettled.forceUpsert ? planTagDiff([], tagMapAsList(desired)).set : plan.set;
|
|
38469
|
+
if (toSet.size === 0 && plan.remove.length === 0) return;
|
|
38470
|
+
unsettled.beforeWrite();
|
|
37839
38471
|
const arn = await resourceArn();
|
|
37840
|
-
if (
|
|
38472
|
+
if (toSet.size > 0) await client.send(new TagResourceCommand$19({
|
|
37841
38473
|
ResourceArn: arn,
|
|
37842
|
-
TagsToAdd: Object.fromEntries(
|
|
38474
|
+
TagsToAdd: Object.fromEntries(toSet)
|
|
37843
38475
|
}));
|
|
37844
38476
|
if (plan.remove.length > 0) await client.send(new UntagResourceCommand$20({
|
|
37845
38477
|
ResourceArn: arn,
|
|
@@ -37874,6 +38506,28 @@ const crawlerLeftInPlaceWarning = (logicalId, names, caller) => {
|
|
|
37874
38506
|
const cfnKeeps = names.includes("LineageConfiguration") ? "" : `, as CloudFormation leaves ${one ? "it" : "them"}`;
|
|
37875
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.`;
|
|
37876
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
|
+
];
|
|
37877
38531
|
var GlueCrawlerProvider = class {
|
|
37878
38532
|
client;
|
|
37879
38533
|
createClient;
|
|
@@ -37956,6 +38610,7 @@ var GlueCrawlerProvider = class {
|
|
|
37956
38610
|
const { value: v } = log;
|
|
37957
38611
|
log.debug(`Updating Glue Crawler ${logicalId}: ${v(physicalId)}`);
|
|
37958
38612
|
desiredGlueTags(properties["Tags"], resourceType, logicalId, physicalId);
|
|
38613
|
+
const markUnsettled = (key) => context?.markUnsettled?.(key);
|
|
37959
38614
|
try {
|
|
37960
38615
|
const updateInput = {
|
|
37961
38616
|
Name: physicalId,
|
|
@@ -37963,6 +38618,7 @@ var GlueCrawlerProvider = class {
|
|
|
37963
38618
|
...properties["Targets"] !== void 0 && { Targets: toSdkCrawlerTargets(properties["Targets"]) },
|
|
37964
38619
|
...buildCrawlerCommonFields(properties)
|
|
37965
38620
|
};
|
|
38621
|
+
for (const key of CRAWLER_UPDATE_KEYS) if (JSON.stringify(properties[key]) !== JSON.stringify(previousProperties[key])) markUnsettled(key);
|
|
37966
38622
|
try {
|
|
37967
38623
|
await this.getClient().send(new UpdateCrawlerCommand(updateInput));
|
|
37968
38624
|
} catch (err) {
|
|
@@ -37972,7 +38628,10 @@ var GlueCrawlerProvider = class {
|
|
|
37972
38628
|
await this.getClient().send(new UpdateCrawlerCommand(updateInput));
|
|
37973
38629
|
} else throw err;
|
|
37974
38630
|
}
|
|
37975
|
-
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
|
+
});
|
|
37976
38635
|
if (!context?.desiredFromAwsReadback) {
|
|
37977
38636
|
const removed = context?.removedProperties;
|
|
37978
38637
|
const leftInPlace = [];
|
|
@@ -38448,6 +39107,7 @@ var GlueTriggerProvider = class {
|
|
|
38448
39107
|
const { value: v } = log;
|
|
38449
39108
|
log.debug(`Updating Glue Trigger ${logicalId}: ${v(physicalId)}`);
|
|
38450
39109
|
desiredGlueTags(properties["Tags"], resourceType, logicalId, physicalId);
|
|
39110
|
+
const markUnsettled = (key) => context?.markUnsettled?.(key);
|
|
38451
39111
|
try {
|
|
38452
39112
|
let restart = false;
|
|
38453
39113
|
try {
|
|
@@ -38467,6 +39127,7 @@ var GlueTriggerProvider = class {
|
|
|
38467
39127
|
...properties["EventBatchingCondition"] !== void 0 && { EventBatchingCondition: properties["EventBatchingCondition"] }
|
|
38468
39128
|
};
|
|
38469
39129
|
let updateError;
|
|
39130
|
+
for (const key of TRIGGER_UPDATE_KEYS) if (JSON.stringify(properties[key]) !== JSON.stringify(previousProperties[key])) markUnsettled(key);
|
|
38470
39131
|
try {
|
|
38471
39132
|
await this.getClient().send(new UpdateTriggerCommand({
|
|
38472
39133
|
Name: physicalId,
|
|
@@ -38484,7 +39145,10 @@ var GlueTriggerProvider = class {
|
|
|
38484
39145
|
if (restartFailure.redacted) log.debug(`Failed to re-activate Glue Trigger ${v(physicalId)} after a failed update: ${restartFailure.detail}`);
|
|
38485
39146
|
}
|
|
38486
39147
|
if (updateError !== void 0) throw updateError;
|
|
38487
|
-
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
|
+
});
|
|
38488
39152
|
return {
|
|
38489
39153
|
physicalId,
|
|
38490
39154
|
wasReplaced: false
|
|
@@ -38494,6 +39158,14 @@ var GlueTriggerProvider = class {
|
|
|
38494
39158
|
throw this.wrapMaskedError(log.mask, error, (text) => new ProvisioningError(`Failed to update Glue Trigger ${logicalId}: ${text}`, resourceType, logicalId, physicalId, cause));
|
|
38495
39159
|
}
|
|
38496
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
|
+
}
|
|
38497
39169
|
async waitForTriggerDeactivated(physicalId) {
|
|
38498
39170
|
for (let attempt = 0; attempt < TRIGGER_DEACTIVATE_MAX_ATTEMPTS; attempt++) {
|
|
38499
39171
|
try {
|
|
@@ -40052,6 +40724,7 @@ function previousMetricNames(value) {
|
|
|
40052
40724
|
const expanded = expandShardLevelMetrics(value);
|
|
40053
40725
|
return isUsableMetricsList(expanded) ? expanded : [];
|
|
40054
40726
|
}
|
|
40727
|
+
const DEFAULT_MAX_RECORD_SIZE_KIB = 1024;
|
|
40055
40728
|
function readMaxRecordSize(value, mask) {
|
|
40056
40729
|
if (value == null) return { kind: "absent" };
|
|
40057
40730
|
if (typeof value === "number" && Number.isFinite(value)) return {
|
|
@@ -40248,6 +40921,7 @@ var KinesisStreamProvider = class {
|
|
|
40248
40921
|
const desiredRetention = readRetentionHours(properties["RetentionPeriodHours"], mask);
|
|
40249
40922
|
if (desiredRetention.kind === "unusable" && context?.replayingState !== true) throw new ProvisioningError(desiredRetention.reason, resourceType, logicalId, physicalId);
|
|
40250
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);
|
|
40251
40925
|
const previousRetention = readRetentionHours(previousProperties["RetentionPeriodHours"], mask);
|
|
40252
40926
|
try {
|
|
40253
40927
|
const streamModeDetails = properties["StreamModeDetails"];
|
|
@@ -40257,6 +40931,7 @@ var KinesisStreamProvider = class {
|
|
|
40257
40931
|
if (modeChanged) {
|
|
40258
40932
|
const streamArn = await this.resolveStreamArn(physicalId);
|
|
40259
40933
|
this.logger.debug(`Switching stream mode for ${physicalId}: from ${oldStreamMode} to ${streamMode}`);
|
|
40934
|
+
markUnsettled("StreamModeDetails");
|
|
40260
40935
|
await this.getClient().send(new UpdateStreamModeCommand({
|
|
40261
40936
|
StreamARN: streamArn,
|
|
40262
40937
|
StreamModeDetails: { StreamMode: streamMode }
|
|
@@ -40265,9 +40940,10 @@ var KinesisStreamProvider = class {
|
|
|
40265
40940
|
}
|
|
40266
40941
|
if (streamMode === "PROVISIONED") {
|
|
40267
40942
|
const newShardCount = Number(properties["ShardCount"] ?? 1);
|
|
40268
|
-
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);
|
|
40269
40944
|
if (newShardCount !== oldShardCount) {
|
|
40270
40945
|
this.logger.debug(`Updating shard count for ${physicalId}: from ${oldShardCount} to ${newShardCount}`);
|
|
40946
|
+
markUnsettled("ShardCount");
|
|
40271
40947
|
await this.getClient().send(new UpdateShardCountCommand({
|
|
40272
40948
|
StreamName: physicalId,
|
|
40273
40949
|
TargetShardCount: newShardCount,
|
|
@@ -40280,6 +40956,7 @@ var KinesisStreamProvider = class {
|
|
|
40280
40956
|
const effectiveOldRetention = previousRetention.kind === "usable" ? previousRetention.hours ?? 24 : 24;
|
|
40281
40957
|
if (desiredRetention.kind !== "unusable" && effectiveNewRetention !== effectiveOldRetention) {
|
|
40282
40958
|
this.logger.debug(`Updating retention period for ${physicalId}: from ${effectiveOldRetention} to ${effectiveNewRetention}`);
|
|
40959
|
+
markUnsettled("RetentionPeriodHours");
|
|
40283
40960
|
if (effectiveNewRetention > effectiveOldRetention) await this.getClient().send(new IncreaseStreamRetentionPeriodCommand({
|
|
40284
40961
|
StreamName: physicalId,
|
|
40285
40962
|
RetentionPeriodHours: effectiveNewRetention
|
|
@@ -40290,7 +40967,10 @@ var KinesisStreamProvider = class {
|
|
|
40290
40967
|
}));
|
|
40291
40968
|
await this.waitForStreamActive(physicalId);
|
|
40292
40969
|
}
|
|
40293
|
-
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
|
+
});
|
|
40294
40974
|
const newEncryption = properties["StreamEncryption"];
|
|
40295
40975
|
const oldEncryption = previousProperties["StreamEncryption"];
|
|
40296
40976
|
const oldIsKms = isKmsEncryption(oldEncryption);
|
|
@@ -40298,6 +40978,7 @@ var KinesisStreamProvider = class {
|
|
|
40298
40978
|
const oldKeyId = oldIsKms ? oldEncryption["KeyId"] : void 0;
|
|
40299
40979
|
const newKeyId = newIsKms ? newEncryption["KeyId"] : void 0;
|
|
40300
40980
|
if (oldIsKms !== newIsKms || oldIsKms && newIsKms && oldKeyId !== newKeyId) {
|
|
40981
|
+
markUnsettled("StreamEncryption");
|
|
40301
40982
|
if (oldIsKms) {
|
|
40302
40983
|
await this.getClient().send(new StopStreamEncryptionCommand({
|
|
40303
40984
|
StreamName: physicalId,
|
|
@@ -40317,17 +40998,18 @@ var KinesisStreamProvider = class {
|
|
|
40317
40998
|
}
|
|
40318
40999
|
const desiredSizeRead = readMaxRecordSize(properties["MaxRecordSizeInKiB"], mask);
|
|
40319
41000
|
if (desiredSizeRead.kind === "unusable") warn(`${desiredSizeRead.reason}. Leaving the maximum record size on ${physicalId} unchanged; the same value is REFUSED on a template-path create`);
|
|
40320
|
-
const newMaxRecordSize = comparableRecordSize(properties["MaxRecordSizeInKiB"], mask);
|
|
40321
|
-
const
|
|
40322
|
-
if (newMaxRecordSize !== void 0 && newMaxRecordSize !==
|
|
40323
|
-
this.logger.debug(`Updating max record size for ${physicalId}: from ${
|
|
41001
|
+
const newMaxRecordSize = desiredSizeRead.kind === "absent" ? DEFAULT_MAX_RECORD_SIZE_KIB : comparableRecordSize(properties["MaxRecordSizeInKiB"], mask);
|
|
41002
|
+
const recordedMaxRecordSize = comparableRecordSize(previousProperties["MaxRecordSizeInKiB"], mask);
|
|
41003
|
+
if (newMaxRecordSize !== void 0 && newMaxRecordSize !== (recordedMaxRecordSize ?? DEFAULT_MAX_RECORD_SIZE_KIB)) {
|
|
41004
|
+
this.logger.debug(`Updating max record size for ${physicalId}: from ${recordedMaxRecordSize ?? "no value"} to ${newMaxRecordSize}`);
|
|
41005
|
+
markUnsettled("MaxRecordSizeInKiB");
|
|
40324
41006
|
await this.getClient().send(new UpdateMaxRecordSizeCommand({
|
|
40325
41007
|
StreamARN: await this.resolveStreamArn(physicalId),
|
|
40326
41008
|
MaxRecordSizeInKiB: newMaxRecordSize
|
|
40327
41009
|
}));
|
|
40328
41010
|
await this.waitForStreamActive(physicalId);
|
|
40329
41011
|
}
|
|
40330
|
-
await this.reconcileDistributionStrategy(physicalId, streamMode, properties, previousProperties, mask, warn);
|
|
41012
|
+
await this.reconcileDistributionStrategy(physicalId, streamMode, properties, previousProperties, mask, warn, markUnsettled);
|
|
40331
41013
|
const desiredRead = readShardLevelMetrics(properties["DesiredShardLevelMetrics"], mask);
|
|
40332
41014
|
let desiredMetrics;
|
|
40333
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`);
|
|
@@ -40336,7 +41018,9 @@ var KinesisStreamProvider = class {
|
|
|
40336
41018
|
const desiredSet = desiredRead.kind === "usable" ? desiredRead.metrics : [];
|
|
40337
41019
|
const previousSet = previousMetricNames(previousProperties["DesiredShardLevelMetrics"]);
|
|
40338
41020
|
const toDisable = previousSet.filter((m) => !desiredSet.includes(m));
|
|
41021
|
+
if (context?.unsettledProperties?.has("DesiredShardLevelMetrics") === true) await this.warnUndeclaredLiveMetrics(physicalId, [...previousSet, ...desiredSet], warn, mask);
|
|
40339
41022
|
const toEnable = desiredSet.filter((m) => !previousSet.includes(m));
|
|
41023
|
+
if (toDisable.length > 0 || toEnable.length > 0) markUnsettled("DesiredShardLevelMetrics");
|
|
40340
41024
|
if (toDisable.length > 0) {
|
|
40341
41025
|
this.logger.debug(`Disabling ${toDisable.length} shard-level metric(s) on ${physicalId}`);
|
|
40342
41026
|
await this.getClient().send(new DisableEnhancedMonitoringCommand({
|
|
@@ -40448,7 +41132,7 @@ var KinesisStreamProvider = class {
|
|
|
40448
41132
|
throw error;
|
|
40449
41133
|
}
|
|
40450
41134
|
}
|
|
40451
|
-
async reconcileDistributionStrategy(physicalId, streamMode, properties, previousProperties, mask, warn) {
|
|
41135
|
+
async reconcileDistributionStrategy(physicalId, streamMode, properties, previousProperties, mask, warn, markUnsettled) {
|
|
40452
41136
|
const desired = readDistributionStrategy(properties["RecordDistributionStrategy"], mask);
|
|
40453
41137
|
if (desired.kind === "unusable") {
|
|
40454
41138
|
warn(`${desired.reason}. Leaving the record distribution strategy on ${physicalId} unchanged; the same value is REFUSED on a template-path create`);
|
|
@@ -40466,6 +41150,7 @@ var KinesisStreamProvider = class {
|
|
|
40466
41150
|
target = DEFAULT_RECORD_DISTRIBUTION_STRATEGY;
|
|
40467
41151
|
}
|
|
40468
41152
|
this.logger.debug(mask(safeMsg`Updating record distribution strategy for ${physicalId}: from ${recorded ?? "no value"} to ${target}`));
|
|
41153
|
+
markUnsettled("RecordDistributionStrategy");
|
|
40469
41154
|
await this.getClient().send(new UpdateStreamRecordDistributionStrategyCommand({
|
|
40470
41155
|
StreamARN: await this.resolveStreamArn(physicalId),
|
|
40471
41156
|
RecordDistributionStrategy: target
|
|
@@ -40494,12 +41179,16 @@ var KinesisStreamProvider = class {
|
|
|
40494
41179
|
if (resourceType !== "AWS::Kinesis::Stream") return [];
|
|
40495
41180
|
return ["DesiredShardLevelMetrics"];
|
|
40496
41181
|
}
|
|
40497
|
-
async applyTagDiff(streamName, resourceType, logicalId, oldTagsRaw, newTagsRaw
|
|
41182
|
+
async applyTagDiff(streamName, resourceType, logicalId, oldTagsRaw, newTagsRaw, unsettled = {
|
|
41183
|
+
forceUpsert: false,
|
|
41184
|
+
beforeWrite: () => void 0
|
|
41185
|
+
}) {
|
|
40498
41186
|
const plan = planTagDiff(oldTagsRaw, newTagsRaw);
|
|
40499
41187
|
const tagWarning = tagPlanWarning(plan, resourceType, logicalId);
|
|
40500
41188
|
if (tagWarning !== void 0) this.logger.warn(tagWarning);
|
|
40501
|
-
const tagsToAdd = Object.fromEntries(plan.set);
|
|
41189
|
+
const tagsToAdd = Object.fromEntries(unsettled.forceUpsert ? planTagDiff(void 0, newTagsRaw).set : plan.set);
|
|
40502
41190
|
const tagsToRemove = plan.remove;
|
|
41191
|
+
if (tagsToRemove.length > 0 || Object.keys(tagsToAdd).length > 0) unsettled.beforeWrite();
|
|
40503
41192
|
if (tagsToRemove.length > 0) {
|
|
40504
41193
|
await this.getClient().send(new RemoveTagsFromStreamCommand({
|
|
40505
41194
|
StreamName: streamName,
|
|
@@ -40515,6 +41204,46 @@ var KinesisStreamProvider = class {
|
|
|
40515
41204
|
this.logger.debug(`Added/updated ${Object.keys(tagsToAdd).length} tag(s) on Kinesis stream ${streamName}`);
|
|
40516
41205
|
}
|
|
40517
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
|
+
}
|
|
40518
41247
|
async readCurrentState(physicalId, _logicalId, resourceType, _properties) {
|
|
40519
41248
|
if (resourceType !== "AWS::Kinesis::Stream") return void 0;
|
|
40520
41249
|
let stream;
|
|
@@ -41280,6 +42009,13 @@ function pipeIdentityToken(name, arn, creationTime) {
|
|
|
41280
42009
|
return `${arn}@${Math.floor(ms / 1e3)}`;
|
|
41281
42010
|
}
|
|
41282
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
|
+
]);
|
|
41283
42019
|
const PIPE_POLL_INTERVAL_MS = 5e3;
|
|
41284
42020
|
const PIPE_SETTLE_MAX_WAIT_MS = 9e5;
|
|
41285
42021
|
const PIPE_DELETE_MAX_WAIT_MS = 6e5;
|
|
@@ -41573,13 +42309,19 @@ var PipesPipeProvider = class {
|
|
|
41573
42309
|
};
|
|
41574
42310
|
const sourceParameters = toUpdateSourceParameters(desired["SourceParameters"], previousProperties["SourceParameters"]);
|
|
41575
42311
|
if (sourceParameters !== void 0) input.SourceParameters = sourceParameters;
|
|
42312
|
+
for (const key of this.changedPipeFields(desired, previousProperties)) context?.markUnsettled?.(key);
|
|
41576
42313
|
const accepted = await this.getClient().send(new UpdatePipeCommand(input));
|
|
41577
42314
|
settled = await this.waitForSettled(physicalId, logicalId, resourceType, "update", mask, accepted.LastModifiedTime);
|
|
41578
42315
|
}
|
|
41579
|
-
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;
|
|
41580
42321
|
const warning = tagPlanWarning(plan, resourceType, logicalId);
|
|
41581
42322
|
if (warning) this.logger.warn(warning);
|
|
41582
42323
|
if (plan.set.size > 0 || plan.remove.length > 0) {
|
|
42324
|
+
context?.markUnsettled?.("Tags");
|
|
41583
42325
|
settled ??= await this.describe(physicalId);
|
|
41584
42326
|
const arn = settled.Arn;
|
|
41585
42327
|
if (!arn) throw new Error("DescribePipe returned no Arn, which tagging needs");
|
|
@@ -41739,10 +42481,30 @@ var PipesPipeProvider = class {
|
|
|
41739
42481
|
return value;
|
|
41740
42482
|
}
|
|
41741
42483
|
pipeFieldsChanged(desired, previous) {
|
|
42484
|
+
return this.changedPipeFields(desired, previous).length > 0;
|
|
42485
|
+
}
|
|
42486
|
+
changedPipeFields(desired, previous) {
|
|
41742
42487
|
const keys = /* @__PURE__ */ new Set([...Object.keys(desired), ...Object.keys(previous)]);
|
|
41743
42488
|
keys.delete("Tags");
|
|
41744
|
-
|
|
41745
|
-
|
|
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;
|
|
41746
42508
|
}
|
|
41747
42509
|
async readStateForDelete(name) {
|
|
41748
42510
|
try {
|
|
@@ -41905,6 +42667,7 @@ var EFSProvider = class {
|
|
|
41905
42667
|
providerRegion = ambientRegion();
|
|
41906
42668
|
logger = getLogger().child("EFSProvider");
|
|
41907
42669
|
unconfirmedCreationTokens = /* @__PURE__ */ new Map();
|
|
42670
|
+
removalDefaults = /* @__PURE__ */ new Map([["AWS::EFS::FileSystem", /* @__PURE__ */ new Map([["BackupPolicy", { Status: "DISABLED" }], ["FileSystemProtection", { ReplicationOverwriteProtection: "ENABLED" }]])]]);
|
|
41908
42671
|
handledProperties = /* @__PURE__ */ new Map([
|
|
41909
42672
|
["AWS::EFS::FileSystem", /* @__PURE__ */ new Set([
|
|
41910
42673
|
"FileSystemTags",
|
|
@@ -41976,13 +42739,56 @@ var EFSProvider = class {
|
|
|
41976
42739
|
}
|
|
41977
42740
|
update(logicalId, physicalId, resourceType, properties, previousProperties, context) {
|
|
41978
42741
|
const log = createMaskedLogSinks(this.logger, context?.maskSecrets);
|
|
42742
|
+
properties = withRemovalDefaults(this.removalDefaults, resourceType, properties, previousProperties, context);
|
|
41979
42743
|
switch (resourceType) {
|
|
41980
42744
|
case "AWS::EFS::FileSystem": return this.updateFileSystem(logicalId, physicalId, resourceType, properties, previousProperties, log);
|
|
41981
42745
|
case "AWS::EFS::MountTarget": return this.updateMountTarget(logicalId, physicalId, resourceType, properties, log);
|
|
41982
|
-
case "AWS::EFS::AccessPoint": return
|
|
42746
|
+
case "AWS::EFS::AccessPoint": return this.updateAccessPoint(logicalId, physicalId, resourceType, properties, previousProperties, log);
|
|
41983
42747
|
default: throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId, physicalId);
|
|
41984
42748
|
}
|
|
41985
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
|
+
}
|
|
41986
42792
|
async updateFileSystem(logicalId, physicalId, resourceType, properties, previousProperties, log) {
|
|
41987
42793
|
for (const key of [
|
|
41988
42794
|
"Encrypted",
|
|
@@ -42006,7 +42812,9 @@ var EFSProvider = class {
|
|
|
42006
42812
|
const backupChanged = changed("BackupPolicy");
|
|
42007
42813
|
const policyChanged = changed("FileSystemPolicy") || changed("BypassPolicyLockoutSafetyCheck");
|
|
42008
42814
|
const protectionChanged = changed("FileSystemProtection");
|
|
42009
|
-
|
|
42815
|
+
const tagsChanged = changed("FileSystemTags");
|
|
42816
|
+
if (tagsChanged) refuseMalformedDesiredTags(properties["FileSystemTags"], resourceType, logicalId, physicalId, "FileSystemTags");
|
|
42817
|
+
if (!throughputModeChanged && !provisionedChanged && !lifecycleChanged && !backupChanged && !policyChanged && !protectionChanged && !tagsChanged) {
|
|
42010
42818
|
log.debug(`No mutable diff for EFS FileSystem ${logicalId}, skipping update`);
|
|
42011
42819
|
return {
|
|
42012
42820
|
physicalId,
|
|
@@ -42025,8 +42833,12 @@ var EFSProvider = class {
|
|
|
42025
42833
|
}
|
|
42026
42834
|
if (lifecycleChanged) await this.applyLifecyclePolicies(physicalId, properties["LifecyclePolicies"], log, previousProperties["LifecyclePolicies"]);
|
|
42027
42835
|
if (backupChanged) await this.applyBackupPolicy(physicalId, properties["BackupPolicy"], log);
|
|
42028
|
-
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
|
+
}
|
|
42029
42840
|
if (protectionChanged) await this.applyFileSystemProtection(physicalId, properties["FileSystemProtection"], log);
|
|
42841
|
+
if (tagsChanged) await this.applyTagDiff(physicalId, resourceType, logicalId, previousProperties["FileSystemTags"], properties["FileSystemTags"], log);
|
|
42030
42842
|
log.debug(`Successfully updated EFS FileSystem ${logicalId}`);
|
|
42031
42843
|
return {
|
|
42032
42844
|
physicalId,
|
|
@@ -42234,6 +43046,10 @@ var EFSProvider = class {
|
|
|
42234
43046
|
})), `set FileSystemPolicy on ${fileSystemId}`, log);
|
|
42235
43047
|
log.debug(`Set FileSystemPolicy on EFS FileSystem ${fileSystemId}`);
|
|
42236
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
|
+
}
|
|
42237
43053
|
async applyFileSystemProtection(fileSystemId, spec, log) {
|
|
42238
43054
|
if (spec === void 0 || spec === null) return;
|
|
42239
43055
|
const protection = spec.ReplicationOverwriteProtection;
|
|
@@ -42742,6 +43558,23 @@ const routeTableDelta = (next, prev) => {
|
|
|
42742
43558
|
...remove.length > 0 && { remove }
|
|
42743
43559
|
};
|
|
42744
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
|
+
};
|
|
42745
43578
|
const TOP_LEVEL_IMMUTABLE_PROPS = [
|
|
42746
43579
|
"FileSystemType",
|
|
42747
43580
|
"SubnetIds",
|
|
@@ -43144,11 +43977,16 @@ var FSxFileSystemProvider = class {
|
|
|
43144
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.`);
|
|
43145
43978
|
}
|
|
43146
43979
|
const variantConfigKey = this.detectVariantConfigKey(properties, previousProperties);
|
|
43147
|
-
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] ?? {}) : {
|
|
43148
43981
|
diff: {},
|
|
43149
43982
|
hasMutableDiff: false,
|
|
43150
|
-
leftInPlace: []
|
|
43983
|
+
leftInPlace: [],
|
|
43984
|
+
aliases: {
|
|
43985
|
+
add: [],
|
|
43986
|
+
remove: []
|
|
43987
|
+
}
|
|
43151
43988
|
};
|
|
43989
|
+
const aliasesChanged = aliases.add.length > 0 || aliases.remove.length > 0;
|
|
43152
43990
|
const leftInPlaceNames = [...TOP_LEVEL_LEFT_IN_PLACE_PROPS.filter((key) => properties[key] === void 0 && previousProperties[key] !== void 0), ...leftInPlace.map((key) => `${variantConfigKey}.${key}`)];
|
|
43153
43991
|
const warnLeftInPlace = () => {
|
|
43154
43992
|
if (leftInPlaceNames.length === 0 || context?.desiredFromAwsReadback) return;
|
|
@@ -43169,7 +44007,7 @@ var FSxFileSystemProvider = class {
|
|
|
43169
44007
|
const typeVersionChanged = sendsChange("FileSystemTypeVersion");
|
|
43170
44008
|
const networkTypeChanged = sendsChange("NetworkType");
|
|
43171
44009
|
const tagsChanged = changed("Tags");
|
|
43172
|
-
if (!variantHasMutableDiff && !storageCapacityChanged && !storageTypeChanged && !typeVersionChanged && !networkTypeChanged && !tagsChanged) {
|
|
44010
|
+
if (!variantHasMutableDiff && !storageCapacityChanged && !storageTypeChanged && !typeVersionChanged && !networkTypeChanged && !aliasesChanged && !tagsChanged) {
|
|
43173
44011
|
this.logger.debug(`No mutable diff for FSx FileSystem ${logicalId}, skipping update`);
|
|
43174
44012
|
warnLeftInPlace();
|
|
43175
44013
|
return {
|
|
@@ -43179,6 +44017,7 @@ var FSxFileSystemProvider = class {
|
|
|
43179
44017
|
}
|
|
43180
44018
|
this.logger.debug(`Updating FSx FileSystem ${logicalId}: ${physicalId}`);
|
|
43181
44019
|
try {
|
|
44020
|
+
const deadline = Date.now() + this.maxWaitMs;
|
|
43182
44021
|
const needsUpdateCall = variantHasMutableDiff || storageCapacityChanged || storageTypeChanged || typeVersionChanged || networkTypeChanged;
|
|
43183
44022
|
let updatedFs;
|
|
43184
44023
|
if (needsUpdateCall) {
|
|
@@ -43193,8 +44032,9 @@ var FSxFileSystemProvider = class {
|
|
|
43193
44032
|
}))).FileSystem?.AdministrativeActions ?? []).filter((a) => a.AdministrativeActionType === "FILE_SYSTEM_UPDATE" && (a.Status === "PENDING" || a.Status === "IN_PROGRESS"));
|
|
43194
44033
|
const requestTimes = respPendingActions.map((a) => a.RequestTime?.getTime()).filter((t) => t !== void 0);
|
|
43195
44034
|
const actionThresholdMs = requestTimes.length > 0 ? Math.min(...requestTimes) : callTimeMs - 6e4;
|
|
43196
|
-
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);
|
|
43197
44036
|
}
|
|
44037
|
+
if (aliasesChanged) await this.applyAliasDelta(physicalId, logicalId, resourceType, aliases, deadline);
|
|
43198
44038
|
if (tagsChanged) await this.applyTagDiff(physicalId, resourceType, logicalId, properties["Tags"], previousProperties["Tags"]);
|
|
43199
44039
|
if (!updatedFs) try {
|
|
43200
44040
|
updatedFs = (await this.getClient().send(new DescribeFileSystemsCommand$1({ FileSystemIds: [physicalId] }))).FileSystems?.[0];
|
|
@@ -43222,11 +44062,20 @@ var FSxFileSystemProvider = class {
|
|
|
43222
44062
|
const keys = /* @__PURE__ */ new Set([...Object.keys(next), ...Object.keys(prev)]);
|
|
43223
44063
|
const diff = {};
|
|
43224
44064
|
const leftInPlace = [];
|
|
44065
|
+
let aliases = {
|
|
44066
|
+
add: [],
|
|
44067
|
+
remove: []
|
|
44068
|
+
};
|
|
43225
44069
|
let hasMutableDiff = false;
|
|
43226
44070
|
for (const key of keys) {
|
|
43227
44071
|
const nextVal = next[key];
|
|
43228
44072
|
const prevVal = prev[key];
|
|
43229
44073
|
if (JSON.stringify(nextVal) === JSON.stringify(prevVal)) continue;
|
|
44074
|
+
if (configKey === "OpenZFSConfiguration" && key === "Options") continue;
|
|
44075
|
+
if (configKey === "WindowsConfiguration" && key === "Aliases") {
|
|
44076
|
+
aliases = aliasDelta(nextVal, prevVal);
|
|
44077
|
+
continue;
|
|
44078
|
+
}
|
|
43230
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.`);
|
|
43231
44080
|
if (nextVal === void 0 && key !== "RouteTableIds") {
|
|
43232
44081
|
leftInPlace.push(key);
|
|
@@ -43242,7 +44091,8 @@ var FSxFileSystemProvider = class {
|
|
|
43242
44091
|
return {
|
|
43243
44092
|
diff,
|
|
43244
44093
|
hasMutableDiff,
|
|
43245
|
-
leftInPlace
|
|
44094
|
+
leftInPlace,
|
|
44095
|
+
aliases
|
|
43246
44096
|
};
|
|
43247
44097
|
}
|
|
43248
44098
|
unmappedMutableSubprop(ctx, key) {
|
|
@@ -43374,6 +44224,104 @@ var FSxFileSystemProvider = class {
|
|
|
43374
44224
|
}
|
|
43375
44225
|
return true;
|
|
43376
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
|
+
}
|
|
43377
44325
|
async applyTagDiff(physicalId, resourceType, logicalId, nextTags, prevTags) {
|
|
43378
44326
|
const plan = planTagDiff(prevTags, nextTags);
|
|
43379
44327
|
const arn = (await this.getClient().send(new DescribeFileSystemsCommand$1({ FileSystemIds: [physicalId] }))).FileSystems?.[0]?.ResourceARN;
|
|
@@ -43385,19 +44333,23 @@ var FSxFileSystemProvider = class {
|
|
|
43385
44333
|
Value
|
|
43386
44334
|
}));
|
|
43387
44335
|
const toRemove = plan.remove;
|
|
43388
|
-
if (toSet.length > 0) await this.getClient().send(new TagResourceCommand$
|
|
44336
|
+
if (toSet.length > 0) await this.getClient().send(new TagResourceCommand$24({
|
|
43389
44337
|
ResourceARN: arn,
|
|
43390
44338
|
Tags: toSet
|
|
43391
44339
|
}));
|
|
43392
|
-
if (toRemove.length > 0) await this.getClient().send(new UntagResourceCommand$
|
|
44340
|
+
if (toRemove.length > 0) await this.getClient().send(new UntagResourceCommand$25({
|
|
43393
44341
|
ResourceARN: arn,
|
|
43394
44342
|
TagKeys: toRemove
|
|
43395
44343
|
}));
|
|
43396
44344
|
}
|
|
43397
|
-
async delete(logicalId, physicalId, resourceType,
|
|
44345
|
+
async delete(logicalId, physicalId, resourceType, properties, context) {
|
|
43398
44346
|
this.logger.debug(`Deleting FSx FileSystem ${logicalId}: ${physicalId}`);
|
|
43399
44347
|
try {
|
|
43400
|
-
|
|
44348
|
+
const openZfsOptions = this.toDeleteOpenZFSOptions(properties);
|
|
44349
|
+
await this.getClient().send(new DeleteFileSystemCommand$1({
|
|
44350
|
+
FileSystemId: physicalId,
|
|
44351
|
+
...openZfsOptions && { OpenZFSConfiguration: { Options: openZfsOptions } }
|
|
44352
|
+
}));
|
|
43401
44353
|
} catch (error) {
|
|
43402
44354
|
if (error instanceof FileSystemNotFound$1) {
|
|
43403
44355
|
const clientRegion = await this.getClient().config.region();
|
|
@@ -43413,6 +44365,14 @@ var FSxFileSystemProvider = class {
|
|
|
43413
44365
|
await this.waitForFileSystemDeleted(physicalId, logicalId, resourceType, context?.maskSecrets);
|
|
43414
44366
|
this.logger.debug(`Successfully deleted FSx FileSystem ${logicalId}`);
|
|
43415
44367
|
}
|
|
44368
|
+
toDeleteOpenZFSOptions(properties) {
|
|
44369
|
+
if (properties?.["FileSystemType"] !== "OPENZFS") return void 0;
|
|
44370
|
+
const config = properties["OpenZFSConfiguration"];
|
|
44371
|
+
if (typeof config !== "object" || config === null || Array.isArray(config)) return void 0;
|
|
44372
|
+
const options = config["Options"];
|
|
44373
|
+
if (!Array.isArray(options) || options.length === 0) return void 0;
|
|
44374
|
+
return options.map((o) => String(o));
|
|
44375
|
+
}
|
|
43416
44376
|
async isSameResource(journaledPhysicalId, record, resourceType, context) {
|
|
43417
44377
|
if (resourceType !== "AWS::FSx::FileSystem") return "unknown";
|
|
43418
44378
|
if (!FILE_SYSTEM_ID_PATTERN.test(journaledPhysicalId) || !FILE_SYSTEM_ID_PATTERN.test(record.physicalId)) return "unknown";
|
|
@@ -43443,9 +44403,8 @@ var FSxFileSystemProvider = class {
|
|
|
43443
44403
|
transientState.count = 0;
|
|
43444
44404
|
return response.FileSystems?.[0];
|
|
43445
44405
|
} catch (error) {
|
|
43446
|
-
const name = error instanceof Error ? error.name : "";
|
|
43447
44406
|
const msg = describeAwsFailure(error).detail;
|
|
43448
|
-
if ((
|
|
44407
|
+
if (isTransientFsxError(error) && transientState.count < maxConsecutiveTransient) {
|
|
43449
44408
|
transientState.count += 1;
|
|
43450
44409
|
this.logger.debug(`Transient DescribeFileSystems error while polling ${fileSystemId} (${transientState.count}/${maxConsecutiveTransient}): ${msg} — retrying`);
|
|
43451
44410
|
return;
|
|
@@ -43466,11 +44425,10 @@ var FSxFileSystemProvider = class {
|
|
|
43466
44425
|
}
|
|
43467
44426
|
throw new ProvisioningError(`Timed out waiting for FSx FileSystem ${fileSystemId} to become AVAILABLE (${Math.round(this.maxWaitMs / 6e4)} min)`, resourceType, logicalId, fileSystemId);
|
|
43468
44427
|
}
|
|
43469
|
-
async waitForUpdateActionComplete(fileSystemId, logicalId, resourceType, actionThresholdMs, requireActionObservation, mask) {
|
|
43470
|
-
const startTime = Date.now();
|
|
44428
|
+
async waitForUpdateActionComplete(fileSystemId, logicalId, resourceType, actionThresholdMs, requireActionObservation, deadline, mask) {
|
|
43471
44429
|
const transientState = { count: 0 };
|
|
43472
44430
|
let seenTrackedAction = false;
|
|
43473
|
-
while (Date.now()
|
|
44431
|
+
while (Date.now() < deadline) {
|
|
43474
44432
|
const fs = await this.describeForPoll(fileSystemId, transientState);
|
|
43475
44433
|
if (fs) {
|
|
43476
44434
|
const updateActions = (fs.AdministrativeActions ?? []).filter((a) => a.AdministrativeActionType === "FILE_SYSTEM_UPDATE" && (a.RequestTime === void 0 || a.RequestTime.getTime() >= actionThresholdMs));
|
|
@@ -43659,13 +44617,26 @@ var FSxFileSystemProvider = class {
|
|
|
43659
44617
|
canonicalizeDriftProperties(resourceType, properties) {
|
|
43660
44618
|
if (resourceType !== "AWS::FSx::FileSystem") return properties;
|
|
43661
44619
|
const lustre = properties["LustreConfiguration"];
|
|
43662
|
-
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);
|
|
43663
44621
|
const log = lustre["LogConfiguration"];
|
|
43664
|
-
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);
|
|
43665
44623
|
const { LogConfiguration: _disabled, ...rest } = lustre;
|
|
43666
|
-
return {
|
|
44624
|
+
return this.canonicalizeWindowsAliases({
|
|
43667
44625
|
...properties,
|
|
43668
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
|
+
}
|
|
43669
44640
|
};
|
|
43670
44641
|
}
|
|
43671
44642
|
getDriftUnknownPaths(resourceType) {
|
|
@@ -43675,7 +44646,8 @@ var FSxFileSystemProvider = class {
|
|
|
43675
44646
|
"BackupId",
|
|
43676
44647
|
"WindowsConfiguration.SelfManagedActiveDirectoryConfiguration.Password",
|
|
43677
44648
|
"OntapConfiguration.FsxAdminPassword",
|
|
43678
|
-
"OpenZFSConfiguration.RootVolumeConfiguration"
|
|
44649
|
+
"OpenZFSConfiguration.RootVolumeConfiguration",
|
|
44650
|
+
"OpenZFSConfiguration.Options"
|
|
43679
44651
|
];
|
|
43680
44652
|
}
|
|
43681
44653
|
getDriftUnorderedPaths(resourceType) {
|
|
@@ -43805,6 +44777,12 @@ const toNumber$2 = (v) => {
|
|
|
43805
44777
|
const jsonEqual$2 = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
43806
44778
|
const addInstanceGroupsLatch = new AmbiguousCreateLatch("emr:AddInstanceGroups");
|
|
43807
44779
|
const groupsCreatedByThisProcess = new RecentIdSet();
|
|
44780
|
+
const MOVING_GROUP_STATES = /* @__PURE__ */ new Set([
|
|
44781
|
+
"PROVISIONING",
|
|
44782
|
+
"BOOTSTRAPPING",
|
|
44783
|
+
"RESIZING",
|
|
44784
|
+
"RECONFIGURING"
|
|
44785
|
+
]);
|
|
43808
44786
|
var EMRInstanceGroupConfigProvider = class {
|
|
43809
44787
|
disableCcApiFallback = true;
|
|
43810
44788
|
client;
|
|
@@ -44005,6 +44983,7 @@ var EMRInstanceGroupConfigProvider = class {
|
|
|
44005
44983
|
this.logger.debug(`Updating EMR instance group ${logicalId}: ${physicalId}`);
|
|
44006
44984
|
try {
|
|
44007
44985
|
if (instanceCountChanged) {
|
|
44986
|
+
context?.markUnsettled?.("InstanceCount");
|
|
44008
44987
|
await this.getClient().send(new ModifyInstanceGroupsCommand({
|
|
44009
44988
|
...jobFlowId && { ClusterId: jobFlowId },
|
|
44010
44989
|
InstanceGroups: [{
|
|
@@ -44017,6 +44996,7 @@ var EMRInstanceGroupConfigProvider = class {
|
|
|
44017
44996
|
if (autoScalingChanged) {
|
|
44018
44997
|
if (!jobFlowId) throw new ProvisioningError(`EMR InstanceGroupConfig ${logicalId} AutoScalingPolicy update needs JobFlowId (the cluster id), which is absent`, resourceType, logicalId, physicalId);
|
|
44019
44998
|
const policy = properties["AutoScalingPolicy"];
|
|
44999
|
+
context?.markUnsettled?.("AutoScalingPolicy");
|
|
44020
45000
|
if (policy) await this.getClient().send(new PutAutoScalingPolicyCommand({
|
|
44021
45001
|
ClusterId: jobFlowId,
|
|
44022
45002
|
InstanceGroupId: physicalId,
|
|
@@ -44100,6 +45080,27 @@ var EMRInstanceGroupConfigProvider = class {
|
|
|
44100
45080
|
}
|
|
44101
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);
|
|
44102
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
|
+
}
|
|
44103
45104
|
async findGroupForPoll(clusterId, groupId, transientState, maxConsecutiveTransient = 5) {
|
|
44104
45105
|
try {
|
|
44105
45106
|
let marker;
|
|
@@ -45761,7 +46762,7 @@ var FirehoseProvider = class {
|
|
|
45761
46762
|
async applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, context) {
|
|
45762
46763
|
this.logger.debug(`Updating Firehose delivery stream ${logicalId}: ${physicalId}`);
|
|
45763
46764
|
const desiredEncryption = readEncryptionInput(properties[ENCRYPTION_KEY], context?.desiredFromAwsReadback === true);
|
|
45764
|
-
const encryptionChanged = !sameEncryptionInput(properties[ENCRYPTION_KEY], desiredEncryption, previousProperties[ENCRYPTION_KEY]);
|
|
46765
|
+
const encryptionChanged = !sameEncryptionInput(properties[ENCRYPTION_KEY], desiredEncryption, previousProperties[ENCRYPTION_KEY]) || context?.unsettledProperties?.has(ENCRYPTION_KEY) === true && desiredEncryption.kind !== "unusable";
|
|
45765
46766
|
let encryptionSkipped = false;
|
|
45766
46767
|
if (encryptionChanged && desiredEncryption.kind === "unusable") {
|
|
45767
46768
|
const message = `${ENCRYPTION_KEY} of Firehose delivery stream ${logicalId} is not an object with a string KeyType (and a string KeyARN, if any)`;
|
|
@@ -45830,7 +46831,7 @@ var FirehoseProvider = class {
|
|
|
45830
46831
|
const prevDest = previousProperties[activeDest] ?? {};
|
|
45831
46832
|
if (JSON.stringify(nextDest) !== JSON.stringify(prevDest)) await this.applySnowflakeDestinationUpdate(logicalId, physicalId, nextDest);
|
|
45832
46833
|
}
|
|
45833
|
-
if (encryptionChanged && desiredEncryption.kind !== "unusable") await this.applyEncryptionUpdate(logicalId, physicalId, resourceType, desiredEncryption, maskerOrIdentity(context?.maskSecrets));
|
|
46834
|
+
if (encryptionChanged && desiredEncryption.kind !== "unusable") await this.applyEncryptionUpdate(logicalId, physicalId, resourceType, desiredEncryption, maskerOrIdentity(context?.maskSecrets), context?.markUnsettled);
|
|
45834
46835
|
const description = await this.getClient().send(new DescribeDeliveryStreamCommand({ DeliveryStreamName: physicalId }));
|
|
45835
46836
|
this.warnUnappliedS3BackupMode(logicalId, properties, unappliedS3BackupModeDestination(properties, previousProperties, destKey, context?.changedProperties), description.DeliveryStreamDescription);
|
|
45836
46837
|
const desc = description.DeliveryStreamDescription;
|
|
@@ -45911,7 +46912,7 @@ var FirehoseProvider = class {
|
|
|
45911
46912
|
}))
|
|
45912
46913
|
}));
|
|
45913
46914
|
}
|
|
45914
|
-
async applyEncryptionUpdate(logicalId, physicalId, resourceType, desired, mask) {
|
|
46915
|
+
async applyEncryptionUpdate(logicalId, physicalId, resourceType, desired, mask, markUnsettled) {
|
|
45915
46916
|
const settled = await this.waitForEncryption(logicalId, physicalId, resourceType, mask, {
|
|
45916
46917
|
what: "settle",
|
|
45917
46918
|
done: (enc) => enc?.Status !== "ENABLING" && enc?.Status !== "DISABLING"
|
|
@@ -45919,8 +46920,9 @@ var FirehoseProvider = class {
|
|
|
45919
46920
|
if (desired.kind === "absent") {
|
|
45920
46921
|
if (settled?.Status !== "ENABLED" && settled?.Status !== "DISABLING_FAILED") return;
|
|
45921
46922
|
this.refuseToStartTransition(logicalId, physicalId, resourceType, "disable");
|
|
46923
|
+
markUnsettled?.(ENCRYPTION_KEY);
|
|
45922
46924
|
await this.getClient().send(new StopDeliveryStreamEncryptionCommand({ DeliveryStreamName: physicalId }));
|
|
45923
|
-
await this.warnIfUnfinished(logicalId, "StopDeliveryStreamEncryption", () => this.waitForEncryption(logicalId, physicalId, resourceType, mask, {
|
|
46925
|
+
await this.warnIfUnfinished(logicalId, "StopDeliveryStreamEncryption", markUnsettled, () => this.waitForEncryption(logicalId, physicalId, resourceType, mask, {
|
|
45924
46926
|
what: "disable",
|
|
45925
46927
|
done: (enc) => enc === void 0 || enc.Status === "DISABLED",
|
|
45926
46928
|
inProgress: "DISABLING",
|
|
@@ -45931,6 +46933,7 @@ var FirehoseProvider = class {
|
|
|
45931
46933
|
}
|
|
45932
46934
|
if (encryptionMatches(settled, desired)) return;
|
|
45933
46935
|
this.refuseToStartTransition(logicalId, physicalId, resourceType, "enable");
|
|
46936
|
+
markUnsettled?.(ENCRYPTION_KEY);
|
|
45934
46937
|
await this.getClient().send(new StartDeliveryStreamEncryptionCommand({
|
|
45935
46938
|
DeliveryStreamName: physicalId,
|
|
45936
46939
|
DeliveryStreamEncryptionConfigurationInput: {
|
|
@@ -45938,7 +46941,7 @@ var FirehoseProvider = class {
|
|
|
45938
46941
|
...desired.keyArn !== void 0 && { KeyARN: desired.keyArn }
|
|
45939
46942
|
}
|
|
45940
46943
|
}));
|
|
45941
|
-
await this.warnIfUnfinished(logicalId, "StartDeliveryStreamEncryption", () => this.waitForEncryption(logicalId, physicalId, resourceType, mask, {
|
|
46944
|
+
await this.warnIfUnfinished(logicalId, "StartDeliveryStreamEncryption", markUnsettled, () => this.waitForEncryption(logicalId, physicalId, resourceType, mask, {
|
|
45942
46945
|
what: "enable",
|
|
45943
46946
|
done: (enc) => encryptionMatches(enc, desired),
|
|
45944
46947
|
inProgress: "ENABLING",
|
|
@@ -45946,12 +46949,12 @@ var FirehoseProvider = class {
|
|
|
45946
46949
|
staleFailure: settled?.Status === "ENABLING_FAILED"
|
|
45947
46950
|
}));
|
|
45948
46951
|
}
|
|
45949
|
-
async warnIfUnfinished(logicalId, call, wait) {
|
|
46952
|
+
async warnIfUnfinished(logicalId, call, markUnsettled, wait) {
|
|
45950
46953
|
try {
|
|
45951
46954
|
return await wait();
|
|
45952
46955
|
} catch (error) {
|
|
45953
46956
|
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";
|
|
45954
|
-
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.`);
|
|
46957
|
+
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).`));
|
|
45955
46958
|
throw error;
|
|
45956
46959
|
}
|
|
45957
46960
|
}
|
|
@@ -46369,6 +47372,15 @@ var FirehoseProvider = class {
|
|
|
46369
47372
|
if (config["CloudWatchLoggingOptions"] !== void 0) result.CloudWatchLoggingOptions = config["CloudWatchLoggingOptions"];
|
|
46370
47373
|
return result;
|
|
46371
47374
|
}
|
|
47375
|
+
async unsettledInTransition(physicalId, _logicalId, _resourceType, names) {
|
|
47376
|
+
if (!names.has(ENCRYPTION_KEY)) return /* @__PURE__ */ new Set();
|
|
47377
|
+
try {
|
|
47378
|
+
const status = (await this.getClient().send(new DescribeDeliveryStreamCommand({ DeliveryStreamName: physicalId }))).DeliveryStreamDescription?.DeliveryStreamEncryptionConfiguration?.Status;
|
|
47379
|
+
return status === "ENABLING" || status === "DISABLING" ? /* @__PURE__ */ new Set([ENCRYPTION_KEY]) : /* @__PURE__ */ new Set();
|
|
47380
|
+
} catch {
|
|
47381
|
+
return /* @__PURE__ */ new Set([ENCRYPTION_KEY]);
|
|
47382
|
+
}
|
|
47383
|
+
}
|
|
46372
47384
|
async readCurrentState(physicalId, _logicalId, _resourceType) {
|
|
46373
47385
|
let desc;
|
|
46374
47386
|
try {
|
|
@@ -46916,6 +47928,7 @@ var CloudTrailProvider = class {
|
|
|
46916
47928
|
//#endregion
|
|
46917
47929
|
//#region src/provisioning/providers/codebuild-provider.ts
|
|
46918
47930
|
const DEFAULT_PROJECT_VISIBILITY = "PRIVATE";
|
|
47931
|
+
const DEFAULT_ENCRYPTION_KEY = "alias/aws/s3";
|
|
46919
47932
|
function readVisibility(properties, mask) {
|
|
46920
47933
|
const visibility = properties["Visibility"];
|
|
46921
47934
|
const role = properties["ResourceAccessRole"];
|
|
@@ -47194,6 +48207,9 @@ var CodeBuildProvider = class {
|
|
|
47194
48207
|
const input = this.mapProperties(() => physicalId, properties);
|
|
47195
48208
|
input.name = physicalId;
|
|
47196
48209
|
if (properties["BuildBatchConfig"] == null && previousProperties["BuildBatchConfig"] != null) input.buildBatchConfig = {};
|
|
48210
|
+
const declaredKey = (value) => value != null && value !== "";
|
|
48211
|
+
if (!declaredKey(properties["EncryptionKey"]) && declaredKey(previousProperties["EncryptionKey"])) input.encryptionKey = DEFAULT_ENCRYPTION_KEY;
|
|
48212
|
+
if (properties["Tags"] == null && previousProperties["Tags"] != null) input.tags = [];
|
|
47197
48213
|
const updated = await this.getClient().send(new UpdateProjectCommand(input));
|
|
47198
48214
|
const desiredVisibility = readVisibility(properties, mask);
|
|
47199
48215
|
const recorded = readVisibility(previousProperties, mask);
|
|
@@ -47680,11 +48696,11 @@ var CodeCommitRepositoryProvider = class {
|
|
|
47680
48696
|
const repoArn = metadata?.Arn;
|
|
47681
48697
|
if (repoArn) {
|
|
47682
48698
|
const removedKeys = Object.keys(oldTagMap).filter((k) => !Object.hasOwn(newTagMap, k));
|
|
47683
|
-
if (removedKeys.length > 0) await this.getClient().send(new UntagResourceCommand$
|
|
48699
|
+
if (removedKeys.length > 0) await this.getClient().send(new UntagResourceCommand$26({
|
|
47684
48700
|
resourceArn: repoArn,
|
|
47685
48701
|
tagKeys: removedKeys
|
|
47686
48702
|
}));
|
|
47687
|
-
if (Object.keys(newTagMap).length > 0) await this.getClient().send(new TagResourceCommand$
|
|
48703
|
+
if (Object.keys(newTagMap).length > 0) await this.getClient().send(new TagResourceCommand$25({
|
|
47688
48704
|
resourceArn: repoArn,
|
|
47689
48705
|
tags: newTagMap
|
|
47690
48706
|
}));
|
|
@@ -48127,7 +49143,7 @@ var DLMLifecyclePolicyProvider = class {
|
|
|
48127
49143
|
if (tagsChanged && arn) {
|
|
48128
49144
|
const removedKeys = plan.remove;
|
|
48129
49145
|
if (removedKeys.length > 0) {
|
|
48130
|
-
await this.getClient().send(new UntagResourceCommand$
|
|
49146
|
+
await this.getClient().send(new UntagResourceCommand$27({
|
|
48131
49147
|
ResourceArn: arn,
|
|
48132
49148
|
TagKeys: removedKeys
|
|
48133
49149
|
}));
|
|
@@ -48135,7 +49151,7 @@ var DLMLifecyclePolicyProvider = class {
|
|
|
48135
49151
|
}
|
|
48136
49152
|
const tagsToAdd = Object.fromEntries(plan.set);
|
|
48137
49153
|
if (Object.keys(tagsToAdd).length > 0) {
|
|
48138
|
-
await this.getClient().send(new TagResourceCommand$
|
|
49154
|
+
await this.getClient().send(new TagResourceCommand$26({
|
|
48139
49155
|
ResourceArn: arn,
|
|
48140
49156
|
Tags: tagsToAdd
|
|
48141
49157
|
}));
|
|
@@ -48299,11 +49315,11 @@ var S3VectorsProvider = class {
|
|
|
48299
49315
|
}
|
|
48300
49316
|
if (!resourceArn) throw new ProvisioningError(`Could not resolve ARN for S3 VectorBucket ${logicalId} (${mask(physicalId)}); cannot apply tag update.`, resourceType, logicalId, physicalId);
|
|
48301
49317
|
try {
|
|
48302
|
-
if (Object.keys(toSet).length > 0) await this.getClient().send(new TagResourceCommand$
|
|
49318
|
+
if (Object.keys(toSet).length > 0) await this.getClient().send(new TagResourceCommand$27({
|
|
48303
49319
|
resourceArn,
|
|
48304
49320
|
tags: toSet
|
|
48305
49321
|
}));
|
|
48306
|
-
if (toRemove.length > 0) await this.getClient().send(new UntagResourceCommand$
|
|
49322
|
+
if (toRemove.length > 0) await this.getClient().send(new UntagResourceCommand$28({
|
|
48307
49323
|
resourceArn,
|
|
48308
49324
|
tagKeys: toRemove
|
|
48309
49325
|
}));
|
|
@@ -48586,12 +49602,12 @@ var S3DirectoryBucketProvider = class {
|
|
|
48586
49602
|
if (removedKeys.length > 0 || tagsToApply.length > 0) {
|
|
48587
49603
|
const accountId = await this.getAccountId();
|
|
48588
49604
|
const resourceArn = await this.buildBucketArn(physicalId, accountId);
|
|
48589
|
-
if (removedKeys.length > 0) await this.getS3ControlClient().send(new UntagResourceCommand$
|
|
49605
|
+
if (removedKeys.length > 0) await this.getS3ControlClient().send(new UntagResourceCommand$29({
|
|
48590
49606
|
AccountId: accountId,
|
|
48591
49607
|
ResourceArn: resourceArn,
|
|
48592
49608
|
TagKeys: removedKeys
|
|
48593
49609
|
}));
|
|
48594
|
-
if (tagsToApply.length > 0) await this.getS3ControlClient().send(new TagResourceCommand$
|
|
49610
|
+
if (tagsToApply.length > 0) await this.getS3ControlClient().send(new TagResourceCommand$28({
|
|
48595
49611
|
AccountId: accountId,
|
|
48596
49612
|
ResourceArn: resourceArn,
|
|
48597
49613
|
Tags: tagsToApply
|
|
@@ -49439,7 +50455,7 @@ var S3TablesProvider = class {
|
|
|
49439
50455
|
const resourceArn = await this.lookupTableArn(tableBucketARN, namespace, name);
|
|
49440
50456
|
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);
|
|
49441
50457
|
if (removedKeys.length > 0) try {
|
|
49442
|
-
await this.getClient().send(new UntagResourceCommand$
|
|
50458
|
+
await this.getClient().send(new UntagResourceCommand$30({
|
|
49443
50459
|
resourceArn,
|
|
49444
50460
|
tagKeys: removedKeys
|
|
49445
50461
|
}));
|
|
@@ -49448,7 +50464,7 @@ var S3TablesProvider = class {
|
|
|
49448
50464
|
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));
|
|
49449
50465
|
}
|
|
49450
50466
|
if (Object.keys(upserts).length > 0) try {
|
|
49451
|
-
await this.getClient().send(new TagResourceCommand$
|
|
50467
|
+
await this.getClient().send(new TagResourceCommand$29({
|
|
49452
50468
|
resourceArn,
|
|
49453
50469
|
tags: upserts
|
|
49454
50470
|
}));
|
|
@@ -49466,7 +50482,7 @@ var S3TablesProvider = class {
|
|
|
49466
50482
|
if (removedKeys.length === 0 && Object.keys(upserts).length === 0) return;
|
|
49467
50483
|
const resourceArn = physicalId;
|
|
49468
50484
|
if (removedKeys.length > 0) try {
|
|
49469
|
-
await this.getClient().send(new UntagResourceCommand$
|
|
50485
|
+
await this.getClient().send(new UntagResourceCommand$30({
|
|
49470
50486
|
resourceArn,
|
|
49471
50487
|
tagKeys: removedKeys
|
|
49472
50488
|
}));
|
|
@@ -49475,7 +50491,7 @@ var S3TablesProvider = class {
|
|
|
49475
50491
|
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));
|
|
49476
50492
|
}
|
|
49477
50493
|
if (Object.keys(upserts).length > 0) try {
|
|
49478
|
-
await this.getClient().send(new TagResourceCommand$
|
|
50494
|
+
await this.getClient().send(new TagResourceCommand$29({
|
|
49479
50495
|
resourceArn,
|
|
49480
50496
|
tags: upserts
|
|
49481
50497
|
}));
|
|
@@ -50595,4 +51611,4 @@ var ACMCertificateProvider = class {
|
|
|
50595
51611
|
|
|
50596
51612
|
//#endregion
|
|
50597
51613
|
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 };
|
|
50598
|
-
//# sourceMappingURL=provider-classes-
|
|
51614
|
+
//# sourceMappingURL=provider-classes-DYke4HKr.js.map
|