@go-to-k/cdkd 0.305.0 → 0.307.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-C8HDzpYh.js → asg-provider-oKlrkJeO.js} +4 -4
- package/dist/{asg-provider-C8HDzpYh.js.map → asg-provider-oKlrkJeO.js.map} +1 -1
- package/dist/{aws-clients-WQOzP1x4.js → aws-clients-Bu9EMILF.js} +87 -3
- package/dist/aws-clients-Bu9EMILF.js.map +1 -0
- package/dist/{aws-failure-text-Durl920o.js → aws-failure-text-NSBdKPYK.js} +7 -1
- package/dist/aws-failure-text-NSBdKPYK.js.map +1 -0
- package/dist/cli.js +2 -2
- package/dist/{db-instance-modify-retry-DfY7rzvu.js → db-instance-modify-retry-DOJPkECL.js} +3 -3
- package/dist/{db-instance-modify-retry-DfY7rzvu.js.map → db-instance-modify-retry-DOJPkECL.js.map} +1 -1
- package/dist/{deploy-engine-BdqMXegu.js → deploy-engine-BOgsnnk0.js} +857 -83
- package/dist/deploy-engine-BOgsnnk0.js.map +1 -0
- package/dist/{iam-policy-targets-OyoL9Woo.js → iam-policy-targets-TFGunWmV.js} +56 -56
- package/dist/{iam-policy-targets-OyoL9Woo.js.map → iam-policy-targets-TFGunWmV.js.map} +1 -1
- package/dist/{iam-role-provider-mYhK_-VN.js → iam-role-provider-DfDYgfqK.js} +5 -5
- package/dist/{iam-role-provider-mYhK_-VN.js.map → iam-role-provider-DfDYgfqK.js.map} +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -5
- package/dist/{neptune-provider-DvFVCaYo.js → neptune-provider-DvuvSkfJ.js} +5 -5
- package/dist/{neptune-provider-DvFVCaYo.js.map → neptune-provider-DvuvSkfJ.js.map} +1 -1
- package/dist/{program-CUklr39z.js → program-DU5UlgkO.js} +44 -16
- package/dist/program-DU5UlgkO.js.map +1 -0
- package/dist/{provider-classes-L1a3Wl0g.js → provider-classes-CPMW_2-R.js} +1069 -236
- package/dist/provider-classes-CPMW_2-R.js.map +1 -0
- package/dist/{rds-provider-CjasAFV5.js → rds-provider-DcBsBQLi.js} +40 -7
- package/dist/rds-provider-DcBsBQLi.js.map +1 -0
- package/dist/{version-Cp2r-ot9.js → version-Dhhyrf1v.js} +2 -2
- package/dist/{version-Cp2r-ot9.js.map → version-Dhhyrf1v.js.map} +1 -1
- package/package.json +2 -2
- package/dist/aws-clients-WQOzP1x4.js.map +0 -1
- package/dist/aws-failure-text-Durl920o.js.map +0 -1
- package/dist/deploy-engine-BdqMXegu.js.map +0 -1
- package/dist/program-CUklr39z.js.map +0 -1
- package/dist/provider-classes-L1a3Wl0g.js.map +0 -1
- package/dist/rds-provider-CjasAFV5.js.map +0 -1
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { r as getAwsClients } from "./aws-clients-
|
|
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-
|
|
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, 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,
|
|
1
|
+
import { r as getAwsClients, s as withApiGatewayPacing } from "./aws-clients-Bu9EMILF.js";
|
|
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, 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-TFGunWmV.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 { $n as awaitInFlightSibling, $o as withoutSilentDropProperties, $r as isRefusedByName, $s as hasMaskableValues, Bi as reEnableInstanceApiTermination, C as hasCdkAutoDeleteTag, Cc as physicalNameCopiesOf, Dc as carriesSecretMask, Ds as canonicalLambdaFunctionName, Dt as isAccessDeniedError, E as markRefusedBeforeApplying, Ei as unchangedBehindSecretReference, Es as withRetry, Et as chunks, F as findNestedTemplateTreeDefect, Fa as passedParameterClassesOf, Fu as describeFileReadFailure, G as enclosingDeadlineRemainingMs, Gi as isSettledInstanceState, Gr as earliestDefined, Ha as accountArgs, I as isAbsoluteAssetPath, Ii as ec2InstanceProtectionSite, Iu as displayAssemblyPath, Ji as s3BucketDualStackDomainName, Js as redactForState, Ki as s3BucketArn, L as listNestedTemplateRows, Li as isTerminationProtectionPropagationError, Lo as refuseMalformedResourcesForDestroy, Lu as renderAssemblyPathEscape, Ma as parseWebACLArn, Mi as withIndeterminateGuard, Mr as secretNamedAttributeNamesOf, Ni as isWaitAbandonedError, Os as lambdaFunctionNameForMask, Ot as lookupEachName, Pi as markWaitAbandoned, R as renderNestedTemplateTreeDefect, Ri as observeThenDisableInstanceApiTermination, Ru as resolveAssemblyPath, S as S3_AUTO_DELETE_OBJECTS_TAG, Sc as recoverMaskedOutput, Ss as requireConfigString, Su as derivePartitionAndUrlSuffix, T as getPriorAttempts, Ti as slowCcOperationTimeoutMs, Vs as passedNoEchoParametersOf, W as enclosingDeadlineExpired, Xi as s3BucketWebsiteUrl, Xs as snapshotPassProvenance, Yi as s3BucketRegionalDomainName, Yo as withheldAccountClause, Yr as acquireIdempotencyToken, Ys as recordReferenceProvenanceEntry, Zo as findSilentDropProperties, _ as deleteTableWithIndexBusyRetry, _o as refuseMalformedNestedChildOutputs, _s as configStringRefusal, ai as refuseMalformedDesiredTags, an as REDACTED_DELETE_ADDRESS_SKIP_REASON, b as waitForIndexesSettled, bs as requireConfigArray, c as DynamoDBGlobalTableProvider, ci as definedAttributes, cn as redactedDeleteAddressSkip, cs as WARM_THROUGHPUT_MEMBERS, ct as getNestedRevertRun, d as compensateRemovedDeletionProtection, dl as timePhase, ds as toCfnInteger, dt as revertNestedChildFromJournal, ei as markDeleteStarted, f as deleteBudgetKey, fs as toFiniteNumber, g as INDEX_SETTLE_POLL_INTERVAL_MS, gs as configIntegerRefusal, gt as withNestedStackContext, h as DELETE_INDEX_WAIT_PROCEED_NOTE, hc as dynamicReferenceTokens, hi as waitForLambdaFunctionActive, hs as configBooleanRefusal, ht as getCurrentNestedStackContext, ii as readTagList, ji as deleteSkipReason, ks as sameLambdaFunctionAddress, kt as withApiLimit, l as DYNAMODB_DELETE_MIN_RESOURCE_TIMEOUT_MS, li as stringifyIfAssigned, ls as coerceWarmThroughput$1, m as resolveDynamoDbDeleteBudgetMs, ml as stringifyValue, ms as coerceCfnInteger, ni as DBPROXY_TAG_OPTIONS, oi as tagMapAsList, on as isRedactedRecordedValue, p as resolveDynamoDbDeleteBudgetClock, pc as withoutPhysicalNameCopies, ps as coerceCfnBoolean, qi as s3BucketDomainName, qr as reserveStackCreateToken, qs as markSameGenerationBag, ri as planTagDiff, rn as getCurrentProducerRegions, rr as replacedDeleteFailureVerdict, si as tagPlanWarning, sn as redactedDeleteAddressFields, t as DeployEngine, ta as outputReferenceProvenanceOf, ti as DBPROXY_TAGS_WHAT, tr as getStackRecords, u as beginDeleteWait, us as isWarmThroughputDecrease, v as maskedLogger, vs as readConfigString, vu as decodeListingKey, w as isTruthyCfnBoolean, wc as recordAttributeIdCopy, x as ECR_AUTO_DELETE_IMAGES_TAG, xa as getAccountInfo, xs as requireConfigObject, xu as canonicalizeRegion, y as relayedIndexBusyDelete, yi as getCurrentResourceSecrets, yl as rewriteTemplateAssetReferences, ys as replayWarn, zi as reDisableInstanceApiTermination } from "./deploy-engine-BOgsnnk0.js";
|
|
6
|
+
import { n as collectInlinePolicyNamesManagedBySiblings, r as IamCreateClientCache, t as IAMRoleProvider } from "./iam-role-provider-DfDYgfqK.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-DU5UlgkO.js";
|
|
8
|
+
import { t as modifyDbInstanceWhenAvailable } from "./db-instance-modify-retry-DOJPkECL.js";
|
|
9
|
+
import { RDSProvider } from "./rds-provider-DcBsBQLi.js";
|
|
10
|
+
import { NeptuneProvider } from "./neptune-provider-DvuvSkfJ.js";
|
|
11
|
+
import { ASGProvider } from "./asg-provider-oKlrkJeO.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, 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, 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, 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";
|
|
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, 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, 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";
|
|
@@ -50,20 +50,20 @@ import { CreateHttpNamespaceCommand, CreatePrivateDnsNamespaceCommand, CreatePub
|
|
|
50
50
|
import { AppSyncClient, CreateApiKeyCommand, CreateDataSourceCommand, CreateGraphqlApiCommand, CreateResolverCommand, DeleteApiKeyCommand, DeleteDataSourceCommand, DeleteGraphqlApiCommand, DeleteResolverCommand, GetDataSourceCommand, GetGraphqlApiCommand, GetGraphqlApiEnvironmentVariablesCommand, GetIntrospectionSchemaCommand, GetResolverCommand, ListApiKeysCommand, ListGraphqlApisCommand, NotFoundException as NotFoundException$4, PutGraphqlApiEnvironmentVariablesCommand, StartSchemaCreationCommand, TagResourceCommand as TagResourceCommand$17, UntagResourceCommand as UntagResourceCommand$17, UpdateApiKeyCommand, UpdateDataSourceCommand, UpdateGraphqlApiCommand, UpdateResolverCommand } from "@aws-sdk/client-appsync";
|
|
51
51
|
import { ConcurrentModificationException, CrawlerRunningException, CreateConnectionCommand, CreateCrawlerCommand, CreateDatabaseCommand, CreateJobCommand, CreateSecurityConfigurationCommand, CreateTableCommand as CreateTableCommand$1, CreateTriggerCommand, CreateWorkflowCommand, DeleteConnectionCommand, DeleteCrawlerCommand, DeleteDatabaseCommand, DeleteJobCommand, DeleteSecurityConfigurationCommand, DeleteTableCommand as DeleteTableCommand$1, DeleteTriggerCommand, DeleteWorkflowCommand, EntityNotFoundException, GetConnectionCommand, GetCrawlerCommand, GetDatabaseCommand, GetJobCommand, GetSecurityConfigurationCommand, GetTableCommand, GetTagsCommand, GetTriggerCommand, GetWorkflowCommand, GlueClient, StartCrawlerScheduleCommand, StartTriggerCommand, StopCrawlerCommand, StopCrawlerScheduleCommand, StopTriggerCommand, TagResourceCommand as TagResourceCommand$18, UntagResourceCommand as UntagResourceCommand$18, UpdateConnectionCommand, UpdateCrawlerCommand, UpdateDatabaseCommand, UpdateJobCommand, UpdateTableCommand as UpdateTableCommand$1, UpdateTriggerCommand, UpdateWorkflowCommand } from "@aws-sdk/client-glue";
|
|
52
52
|
import { BudgetsClient, CreateBudgetCommand, CreateNotificationCommand, CreateSubscriberCommand, DeleteBudgetCommand, DeleteNotificationCommand, DeleteSubscriberCommand, DescribeBudgetCommand, DescribeNotificationsForBudgetCommand, DescribeSubscribersForNotificationCommand, DuplicateRecordException, ListTagsForResourceCommand as ListTagsForResourceCommand$15, NotFoundException as NotFoundException$5, TagResourceCommand as TagResourceCommand$19, UntagResourceCommand as UntagResourceCommand$19, UpdateBudgetCommand } from "@aws-sdk/client-budgets";
|
|
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$20, UntagResourceCommand as UntagResourceCommand$20, UpdateMaxRecordSizeCommand, UpdateShardCountCommand, UpdateStreamModeCommand } from "@aws-sdk/client-kinesis";
|
|
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$20, UntagResourceCommand as UntagResourceCommand$20, 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$21, UntagResourceCommand as UntagResourceCommand$21, UpdatePipeCommand } from "@aws-sdk/client-pipes";
|
|
56
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
57
|
import { CreateFileSystemCommand as CreateFileSystemCommand$1, CreateFileSystemFromBackupCommand, DeleteFileSystemCommand as DeleteFileSystemCommand$1, DescribeFileSystemsCommand as DescribeFileSystemsCommand$1, FSxClient, FileSystemNotFound as FileSystemNotFound$1, TagResourceCommand as TagResourceCommand$22, UntagResourceCommand as UntagResourceCommand$22, 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, SetVisibleToAllUsersCommand, TerminateJobFlowsCommand } from "@aws-sdk/client-emr";
|
|
59
|
-
import { CreateDeliveryStreamCommand, DeleteDeliveryStreamCommand, DescribeDeliveryStreamCommand, FirehoseClient, ListTagsForDeliveryStreamCommand, ResourceNotFoundException as ResourceNotFoundException$14, TagDeliveryStreamCommand, UntagDeliveryStreamCommand, UpdateDestinationCommand } from "@aws-sdk/client-firehose";
|
|
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
|
-
import { BatchGetProjectsCommand, CodeBuildClient, CreateProjectCommand, DeleteProjectCommand, ResourceNotFoundException as ResourceNotFoundException$15, UpdateProjectCommand } from "@aws-sdk/client-codebuild";
|
|
61
|
+
import { BatchGetProjectsCommand, CodeBuildClient, CreateProjectCommand, DeleteProjectCommand, ResourceNotFoundException as ResourceNotFoundException$15, UpdateProjectCommand, UpdateProjectVisibilityCommand } from "@aws-sdk/client-codebuild";
|
|
62
62
|
import { CodeCommitClient, CreateCommitCommand, CreateRepositoryCommand as CreateRepositoryCommand$1, DeleteRepositoryCommand as DeleteRepositoryCommand$1, GetRepositoryCommand, GetRepositoryTriggersCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$17, PutRepositoryTriggersCommand, RepositoryDoesNotExistException, TagResourceCommand as TagResourceCommand$23, UntagResourceCommand as UntagResourceCommand$23, UpdateRepositoryDescriptionCommand, UpdateRepositoryEncryptionKeyCommand, UpdateRepositoryNameCommand } from "@aws-sdk/client-codecommit";
|
|
63
63
|
import { CreateLifecyclePolicyCommand, DLMClient, DeleteLifecyclePolicyCommand as DeleteLifecyclePolicyCommand$1, GetLifecyclePoliciesCommand, GetLifecyclePolicyCommand as GetLifecyclePolicyCommand$1, ResourceNotFoundException as ResourceNotFoundException$16, TagResourceCommand as TagResourceCommand$24, UntagResourceCommand as UntagResourceCommand$24, UpdateLifecyclePolicyCommand } from "@aws-sdk/client-dlm";
|
|
64
64
|
import { CreateVectorBucketCommand, DeleteIndexCommand, DeleteVectorBucketCommand, GetVectorBucketCommand, ListIndexesCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$18, S3VectorsClient, TagResourceCommand as TagResourceCommand$25, UntagResourceCommand as UntagResourceCommand$25 } from "@aws-sdk/client-s3vectors";
|
|
65
65
|
import { ListTagsForResourceCommand as ListTagsForResourceCommand$19, S3ControlClient, TagResourceCommand as TagResourceCommand$26, UntagResourceCommand as UntagResourceCommand$26 } 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, S3TablesClient, TagResourceCommand as TagResourceCommand$27, UntagResourceCommand as UntagResourceCommand$27 } from "@aws-sdk/client-s3tables";
|
|
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$27, UntagResourceCommand as UntagResourceCommand$27 } 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";
|
|
@@ -2924,6 +2924,13 @@ var IAMUserGroupProvider = class {
|
|
|
2924
2924
|
}
|
|
2925
2925
|
};
|
|
2926
2926
|
|
|
2927
|
+
//#endregion
|
|
2928
|
+
//#region src/utils/cfn-timestamp.ts
|
|
2929
|
+
const OFFSETLESS_DATE_TIME = /^\d{4}-\d{2}-\d{2}[Tt ]\d{2}:\d{2}(:\d{2}(\.\d+)?)?$/;
|
|
2930
|
+
function parseCfnTimestamp(value) {
|
|
2931
|
+
return new Date(OFFSETLESS_DATE_TIME.test(value) ? `${value}Z` : value);
|
|
2932
|
+
}
|
|
2933
|
+
|
|
2927
2934
|
//#endregion
|
|
2928
2935
|
//#region src/provisioning/providers/s3-bucket-provider.ts
|
|
2929
2936
|
function manualBucketDeletionClause(bucketName, maskSecrets, journaled) {
|
|
@@ -2936,7 +2943,7 @@ function manualBucketDeletionClause(bucketName, maskSecrets, journaled) {
|
|
|
2936
2943
|
return command ? `${lead}: ${command}` : `${lead}, via the console: the bucket name cannot be reproduced safely on a command line, so any command shown here could act on a different bucket or run part of the name as shell.`;
|
|
2937
2944
|
}
|
|
2938
2945
|
function configItemId(item) {
|
|
2939
|
-
if (!isPlainObject$
|
|
2946
|
+
if (!isPlainObject$3(item)) return void 0;
|
|
2940
2947
|
const id = item["Id"];
|
|
2941
2948
|
if (typeof id === "string") return id;
|
|
2942
2949
|
if (typeof id === "number" && Number.isFinite(id)) return String(id);
|
|
@@ -2944,11 +2951,11 @@ function configItemId(item) {
|
|
|
2944
2951
|
function declaresBucketObjectLock(properties) {
|
|
2945
2952
|
return properties["ObjectLockEnabled"] === true || properties["ObjectLockEnabled"] === "true";
|
|
2946
2953
|
}
|
|
2947
|
-
function isPlainObject$
|
|
2954
|
+
function isPlainObject$3(value) {
|
|
2948
2955
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2949
2956
|
}
|
|
2950
2957
|
function effectiveS3BucketDestination(declared, sentFormat) {
|
|
2951
|
-
if (!isPlainObject$
|
|
2958
|
+
if (!isPlainObject$3(declared)) return declared;
|
|
2952
2959
|
if (!declared["BucketArn"]) return declared;
|
|
2953
2960
|
const out = { BucketArn: declared["BucketArn"] };
|
|
2954
2961
|
if (declared["BucketAccountId"] !== void 0) out["BucketAccountId"] = declared["BucketAccountId"];
|
|
@@ -2984,7 +2991,7 @@ function effectiveInventoryItem(item, sent) {
|
|
|
2984
2991
|
const scheduleContainerUsable = configStringRefusal(declaredSchedule, "Frequency", INVENTORY_DEFAULT_SCHEDULE_FREQUENCY, "AWS::S3::Bucket InventoryConfigurations[].Schedule") === void 0;
|
|
2985
2992
|
const canFoldSchedule = sent?.frequency !== void 0 || scheduleFrequencyUsable || !declaresScheduleFrequency && scheduleContainerUsable;
|
|
2986
2993
|
if (canFoldSchedule) {
|
|
2987
|
-
const declaredFrequency = declaresScheduleFrequency ? item["ScheduleFrequency"] : isPlainObject$
|
|
2994
|
+
const declaredFrequency = declaresScheduleFrequency ? item["ScheduleFrequency"] : isPlainObject$3(declaredSchedule) && declaredSchedule["Frequency"] !== void 0 ? declaredSchedule["Frequency"] : INVENTORY_DEFAULT_SCHEDULE_FREQUENCY;
|
|
2988
2995
|
const frequency = sent?.frequency ?? declaredFrequency;
|
|
2989
2996
|
if (!Object.is(item["ScheduleFrequency"], frequency)) patch["ScheduleFrequency"] = frequency;
|
|
2990
2997
|
}
|
|
@@ -3001,9 +3008,9 @@ function effectiveInventoryItem(item, sent) {
|
|
|
3001
3008
|
}
|
|
3002
3009
|
function effectiveAnalyticsItem(item, sent) {
|
|
3003
3010
|
const storageClassAnalysis = item["StorageClassAnalysis"];
|
|
3004
|
-
if (!isPlainObject$
|
|
3011
|
+
if (!isPlainObject$3(storageClassAnalysis)) return item;
|
|
3005
3012
|
const dataExport = storageClassAnalysis["DataExport"];
|
|
3006
|
-
if (!isPlainObject$
|
|
3013
|
+
if (!isPlainObject$3(dataExport)) return item;
|
|
3007
3014
|
const patch = {};
|
|
3008
3015
|
const outputSchemaVersion = sent?.outputSchemaVersion ?? declaredOrDefault(dataExport, "OutputSchemaVersion", ANALYTICS_DEFAULT_OUTPUT_SCHEMA_VERSION);
|
|
3009
3016
|
if (!Object.is(dataExport["OutputSchemaVersion"], outputSchemaVersion)) patch["OutputSchemaVersion"] = outputSchemaVersion;
|
|
@@ -3045,7 +3052,7 @@ const EVENTBRIDGE_CONFIG_PATH = "AWS::S3::Bucket NotificationConfiguration.Event
|
|
|
3045
3052
|
const EVENTBRIDGE_CONFIG_KEY = "EventBridgeConfiguration";
|
|
3046
3053
|
const EVENTBRIDGE_DEFAULT_ENABLED = true;
|
|
3047
3054
|
function eventBridgeEnabledOf(eb) {
|
|
3048
|
-
const declared = isPlainObject$
|
|
3055
|
+
const declared = isPlainObject$3(eb) ? eb["EventBridgeEnabled"] : void 0;
|
|
3049
3056
|
return coerceCfnBoolean(declared) ?? EVENTBRIDGE_DEFAULT_ENABLED;
|
|
3050
3057
|
}
|
|
3051
3058
|
const NOTIFICATION_LIST_KEYS = [
|
|
@@ -3075,7 +3082,7 @@ function foldNotificationEvents(item) {
|
|
|
3075
3082
|
return out;
|
|
3076
3083
|
}
|
|
3077
3084
|
function effectiveNotificationConfiguration(config) {
|
|
3078
|
-
if (!isPlainObject$
|
|
3085
|
+
if (!isPlainObject$3(config)) return config;
|
|
3079
3086
|
let out = config;
|
|
3080
3087
|
for (const listKey of NOTIFICATION_LIST_KEYS) out = canonicalizeItemList(out, listKey, foldNotificationEvents);
|
|
3081
3088
|
out = dropEmptyNotificationFamilies(out);
|
|
@@ -3086,8 +3093,8 @@ function foldEventBridgeConfiguration(config) {
|
|
|
3086
3093
|
if (eb === void 0) return config;
|
|
3087
3094
|
if (eb !== null && configBooleanRefusal(eb, "EventBridgeEnabled", EVENTBRIDGE_CONFIG_PATH)) return config;
|
|
3088
3095
|
const enabled = eb === null ? false : eventBridgeEnabledOf(eb);
|
|
3089
|
-
const declared = isPlainObject$
|
|
3090
|
-
if (isPlainObject$
|
|
3096
|
+
const declared = isPlainObject$3(eb) ? eb["EventBridgeEnabled"] : void 0;
|
|
3097
|
+
if (isPlainObject$3(eb) && Object.keys(eb).length === 1 && Object.is(declared, enabled)) return config;
|
|
3091
3098
|
return {
|
|
3092
3099
|
...config,
|
|
3093
3100
|
[EVENTBRIDGE_CONFIG_KEY]: { EventBridgeEnabled: enabled }
|
|
@@ -3129,18 +3136,21 @@ function deepSameValue(a, b) {
|
|
|
3129
3136
|
if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;
|
|
3130
3137
|
return a.every((element, index) => deepSameValue(element, b[index]));
|
|
3131
3138
|
}
|
|
3132
|
-
if (isPlainObject$
|
|
3139
|
+
if (isPlainObject$3(a) && isPlainObject$3(b)) {
|
|
3133
3140
|
const keysA = Object.keys(a);
|
|
3134
3141
|
if (keysA.length !== Object.keys(b).length) return false;
|
|
3135
3142
|
return keysA.every((key) => Object.hasOwn(b, key) && deepSameValue(a[key], b[key]));
|
|
3136
3143
|
}
|
|
3137
3144
|
return false;
|
|
3138
3145
|
}
|
|
3139
|
-
const TIMEZONE_INDEPENDENT_DATE = /^\d{4}-\d{2}-\d{2}(
|
|
3146
|
+
const TIMEZONE_INDEPENDENT_DATE = /^\d{4}-\d{2}-\d{2}([Tt ]\d{2}:\d{2}(:\d{2}(\.\d+)?)?(Z|[+-]\d{2}:\d{2})?)?$/;
|
|
3140
3147
|
function cfnDateToIso(value) {
|
|
3141
|
-
|
|
3142
|
-
if (typeof value
|
|
3143
|
-
|
|
3148
|
+
let parsed;
|
|
3149
|
+
if (typeof value === "string") {
|
|
3150
|
+
if (!TIMEZONE_INDEPENDENT_DATE.test(value)) return void 0;
|
|
3151
|
+
parsed = parseCfnTimestamp(value);
|
|
3152
|
+
} else if (typeof value === "number") parsed = new Date(value);
|
|
3153
|
+
else return;
|
|
3144
3154
|
return Number.isNaN(parsed.getTime()) ? void 0 : parsed.toISOString();
|
|
3145
3155
|
}
|
|
3146
3156
|
const LEGACY_SINGULAR_TRANSITIONS = [["Transitions", "Transition"], ["NoncurrentVersionTransitions", "NoncurrentVersionTransition"]];
|
|
@@ -3148,9 +3158,9 @@ function foldLegacySingularTransitions(rule) {
|
|
|
3148
3158
|
let out;
|
|
3149
3159
|
for (const [pluralKey, singularKey] of LEGACY_SINGULAR_TRANSITIONS) {
|
|
3150
3160
|
const singular = rule[singularKey];
|
|
3151
|
-
const hasSingular = isPlainObject$
|
|
3161
|
+
const hasSingular = isPlainObject$3(singular);
|
|
3152
3162
|
const plural = rule[pluralKey];
|
|
3153
|
-
const needsFilter = Array.isArray(plural) && plural.some((element) => !isPlainObject$
|
|
3163
|
+
const needsFilter = Array.isArray(plural) && plural.some((element) => !isPlainObject$3(element));
|
|
3154
3164
|
if (!hasSingular && !needsFilter) continue;
|
|
3155
3165
|
let collided = false;
|
|
3156
3166
|
const merged = mergeLegacySingular(plural, hasSingular ? singular : void 0, () => {
|
|
@@ -3199,7 +3209,7 @@ function foldLifecycleExpiration(rule) {
|
|
|
3199
3209
|
const iso = cfnDateToIso(expiration);
|
|
3200
3210
|
if (iso === void 0) return rule;
|
|
3201
3211
|
date = iso;
|
|
3202
|
-
} else if (isPlainObject$
|
|
3212
|
+
} else if (isPlainObject$3(expiration)) {
|
|
3203
3213
|
if (expiration["Days"] !== void 0) days = expiration["Days"];
|
|
3204
3214
|
if (expiration["Date"]) {
|
|
3205
3215
|
const iso = cfnDateToIso(expiration["Date"]);
|
|
@@ -3232,10 +3242,10 @@ function foldNoncurrentVersionExpiration(rule) {
|
|
|
3232
3242
|
const legacy = rule["NoncurrentVersionExpirationInDays"];
|
|
3233
3243
|
if (legacy === void 0) return rule;
|
|
3234
3244
|
const declaredObject = rule["NoncurrentVersionExpiration"];
|
|
3235
|
-
if (declaredObject !== void 0 && !isPlainObject$
|
|
3245
|
+
if (declaredObject !== void 0 && !isPlainObject$3(declaredObject)) return rule;
|
|
3236
3246
|
const out = { ...rule };
|
|
3237
3247
|
delete out["NoncurrentVersionExpirationInDays"];
|
|
3238
|
-
if (isPlainObject$
|
|
3248
|
+
if (isPlainObject$3(declaredObject)) return out;
|
|
3239
3249
|
const days = coerceCfnNumber(legacy);
|
|
3240
3250
|
if (days === void 0) return rule;
|
|
3241
3251
|
out["NoncurrentVersionExpiration"] = { NoncurrentDays: days };
|
|
@@ -3267,10 +3277,10 @@ function foldLifecycleScope(rule, useFilterForm) {
|
|
|
3267
3277
|
return out;
|
|
3268
3278
|
}
|
|
3269
3279
|
function effectiveLifecycleConfiguration(config) {
|
|
3270
|
-
if (!isPlainObject$
|
|
3280
|
+
if (!isPlainObject$3(config)) return config;
|
|
3271
3281
|
const rules = config["Rules"];
|
|
3272
3282
|
if (!Array.isArray(rules)) return config;
|
|
3273
|
-
const objectRules = rules.filter(isPlainObject$
|
|
3283
|
+
const objectRules = rules.filter(isPlainObject$3);
|
|
3274
3284
|
if (objectRules.length !== rules.length || objectRules.length === 0) return config;
|
|
3275
3285
|
if (objectRules.some(lifecycleRuleRefused)) return config;
|
|
3276
3286
|
const useFilterForm = lifecycleUsesFilterForm(objectRules);
|
|
@@ -3302,7 +3312,7 @@ function canonicalizeItemList(properties, key, fold) {
|
|
|
3302
3312
|
if (!Array.isArray(list)) return properties;
|
|
3303
3313
|
let changed = false;
|
|
3304
3314
|
const mapped = list.map((element) => {
|
|
3305
|
-
if (!isPlainObject$
|
|
3315
|
+
if (!isPlainObject$3(element)) return element;
|
|
3306
3316
|
const next = fold(element);
|
|
3307
3317
|
if (next !== element) changed = true;
|
|
3308
3318
|
return next;
|
|
@@ -3316,7 +3326,7 @@ function describeValue$1(value, maskSecrets = (text) => text) {
|
|
|
3316
3326
|
if (value === null) return "null";
|
|
3317
3327
|
if (Array.isArray(value)) return "an array";
|
|
3318
3328
|
if (typeof value === "string") return `a string ${displaySafe(JSON.stringify(maskDeep(value, maskSecrets)))}`;
|
|
3319
|
-
if (isPlainObject$
|
|
3329
|
+
if (isPlainObject$3(value)) return `an object with keys [${Object.keys(value).map((key) => displaySafe(maskSecrets(key))).join(", ")}]`;
|
|
3320
3330
|
return `a ${typeof value} (${maskSecrets(String(value))})`;
|
|
3321
3331
|
}
|
|
3322
3332
|
function coerceCfnNumber(value) {
|
|
@@ -3326,8 +3336,8 @@ function coerceCfnNumber(value) {
|
|
|
3326
3336
|
return Number.isFinite(n) ? n : void 0;
|
|
3327
3337
|
}
|
|
3328
3338
|
function mergeLegacySingular(plural, singular, onCollision) {
|
|
3329
|
-
const out = (Array.isArray(plural) ? plural : []).filter(isPlainObject$
|
|
3330
|
-
if (!isPlainObject$
|
|
3339
|
+
const out = (Array.isArray(plural) ? plural : []).filter(isPlainObject$3);
|
|
3340
|
+
if (!isPlainObject$3(singular)) return out;
|
|
3331
3341
|
const sc = singular["StorageClass"];
|
|
3332
3342
|
if (typeof sc === "string" && out.some((e) => e["StorageClass"] === sc)) {
|
|
3333
3343
|
onCollision(sc);
|
|
@@ -3669,12 +3679,12 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
3669
3679
|
};
|
|
3670
3680
|
const expiration = rule["ExpirationInDays"] || rule["ExpirationDate"] || rule["Expiration"];
|
|
3671
3681
|
if (typeof expiration === "number") sdkRule.Expiration = { Days: expiration };
|
|
3672
|
-
else if (typeof expiration === "string") sdkRule.Expiration = { Date:
|
|
3682
|
+
else if (typeof expiration === "string") sdkRule.Expiration = { Date: parseCfnTimestamp(expiration) };
|
|
3673
3683
|
else if (expiration && typeof expiration === "object") {
|
|
3674
3684
|
const exp = expiration;
|
|
3675
3685
|
sdkRule.Expiration = {
|
|
3676
3686
|
Days: exp["Days"],
|
|
3677
|
-
Date: exp["Date"] ?
|
|
3687
|
+
Date: exp["Date"] ? parseCfnTimestamp(exp["Date"]) : void 0,
|
|
3678
3688
|
ExpiredObjectDeleteMarker: exp["ExpiredObjectDeleteMarker"]
|
|
3679
3689
|
};
|
|
3680
3690
|
}
|
|
@@ -3683,7 +3693,7 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
3683
3693
|
if (!(exp?.["Days"] !== void 0 || exp?.["Date"] !== void 0)) sdkRule.Expiration = { ExpiredObjectDeleteMarker: true };
|
|
3684
3694
|
else this.logger.warn(`Lifecycle rule ${shownLifecycleRuleId(maskDeep(rule["Id"], this.shownMask))} on ${this.shown(bucketName)} sets ExpiredObjectDeleteMarker alongside an expiration Days/Date; S3 forbids combining them, so the delete-marker cleanup was not applied.`);
|
|
3685
3695
|
}
|
|
3686
|
-
const nve = isPlainObject$
|
|
3696
|
+
const nve = isPlainObject$3(rule["NoncurrentVersionExpiration"]) ? rule["NoncurrentVersionExpiration"] : void 0;
|
|
3687
3697
|
const legacyNveDays = rule["NoncurrentVersionExpirationInDays"];
|
|
3688
3698
|
if (nve) sdkRule.NoncurrentVersionExpiration = {
|
|
3689
3699
|
NoncurrentDays: nve["NoncurrentDays"],
|
|
@@ -3701,14 +3711,14 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
3701
3711
|
if (allNvts.length > 0) sdkRule.NoncurrentVersionTransitions = allNvts.map(toSdkNvt);
|
|
3702
3712
|
const toSdkTransition = (t) => ({
|
|
3703
3713
|
Days: t["TransitionInDays"] ?? t["Days"],
|
|
3704
|
-
Date: t["TransitionDate"] ?? t["Date"] ?
|
|
3714
|
+
Date: t["TransitionDate"] ?? t["Date"] ? parseCfnTimestamp(t["TransitionDate"] ?? t["Date"]) : void 0,
|
|
3705
3715
|
StorageClass: t["StorageClass"]
|
|
3706
3716
|
});
|
|
3707
3717
|
const transitions = rule["Transitions"];
|
|
3708
3718
|
const singularTransition = rule["Transition"];
|
|
3709
3719
|
const allTransitions = mergeLegacySingular(transitions, singularTransition, (sc) => this.logger.warn(`Lifecycle rule ${shownLifecycleRuleId(maskDeep(rule["Id"], this.shownMask))} on ${this.shown(bucketName)} declares both Transitions and the legacy Transition for storage class ${this.shown(sc)}; S3 rejects duplicates, so the legacy singular was ignored.`));
|
|
3710
3720
|
if (allTransitions.length > 0) sdkRule.Transitions = allTransitions.map(toSdkTransition);
|
|
3711
|
-
const abort = isPlainObject$
|
|
3721
|
+
const abort = isPlainObject$3(rule["AbortIncompleteMultipartUpload"]) ? rule["AbortIncompleteMultipartUpload"] : void 0;
|
|
3712
3722
|
if (abort) sdkRule.AbortIncompleteMultipartUpload = { DaysAfterInitiation: abort["DaysAfterInitiation"] };
|
|
3713
3723
|
const { prefix, tagFilters, sizeGt, sizeLt } = lifecycleRuleScope(rule);
|
|
3714
3724
|
const hasTags = tagFilters != null && tagFilters.length > 0;
|
|
@@ -3940,7 +3950,7 @@ var S3BucketProvider = class S3BucketProvider {
|
|
|
3940
3950
|
throw new Error(message);
|
|
3941
3951
|
};
|
|
3942
3952
|
if (dest === void 0 || dest === null) return;
|
|
3943
|
-
if (!isPlainObject$
|
|
3953
|
+
if (!isPlainObject$3(dest)) return drop(`${destinationPath} must be an object (got ${describeValue$1(dest, maskSecrets)}) — check for an unresolved intrinsic or a mis-nested template value; the destination would otherwise be dropped from the request with no error`);
|
|
3944
3954
|
if (!dest["BucketArn"]) return drop(`${destinationPath} has no destination bucket (BucketArn) (got ${describeValue$1(dest, maskSecrets)}) — the request would be rejected by S3, or silently carry no destination`);
|
|
3945
3955
|
return dest;
|
|
3946
3956
|
}
|
|
@@ -8201,6 +8211,8 @@ var LambdaFunctionProvider = class {
|
|
|
8201
8211
|
S3Bucket: builtCode.S3Bucket,
|
|
8202
8212
|
S3Key: builtCode.S3Key,
|
|
8203
8213
|
S3ObjectVersion: builtCode.S3ObjectVersion,
|
|
8214
|
+
S3ObjectStorageMode: builtCode.S3ObjectStorageMode,
|
|
8215
|
+
SourceKMSKeyArn: builtCode.SourceKMSKeyArn,
|
|
8204
8216
|
ZipFile: builtCode.ZipFile,
|
|
8205
8217
|
ImageUri: builtCode.ImageUri,
|
|
8206
8218
|
Architectures: architecturesChanged ? normalizeArchitectures(properties["Architectures"]) : void 0
|
|
@@ -8461,6 +8473,8 @@ var LambdaFunctionProvider = class {
|
|
|
8461
8473
|
if (code["S3Bucket"]) result.S3Bucket = code["S3Bucket"];
|
|
8462
8474
|
if (code["S3Key"]) result.S3Key = code["S3Key"];
|
|
8463
8475
|
if (code["S3ObjectVersion"]) result.S3ObjectVersion = code["S3ObjectVersion"];
|
|
8476
|
+
if (code["S3ObjectStorageMode"]) result.S3ObjectStorageMode = code["S3ObjectStorageMode"];
|
|
8477
|
+
if (code["SourceKMSKeyArn"]) result.SourceKMSKeyArn = code["SourceKMSKeyArn"];
|
|
8464
8478
|
if (code["ZipFile"]) result.ZipFile = this.createZipFromInlineCode(code["ZipFile"], runtime);
|
|
8465
8479
|
if (code["ImageUri"]) result.ImageUri = code["ImageUri"];
|
|
8466
8480
|
return result;
|
|
@@ -8673,6 +8687,7 @@ var LambdaFunctionProvider = class {
|
|
|
8673
8687
|
"Code.S3Bucket",
|
|
8674
8688
|
"Code.S3Key",
|
|
8675
8689
|
"Code.S3ObjectVersion",
|
|
8690
|
+
"Code.S3ObjectStorageMode",
|
|
8676
8691
|
"Code.ZipFile",
|
|
8677
8692
|
"Code.SourceKMSKeyArn"
|
|
8678
8693
|
];
|
|
@@ -9364,7 +9379,7 @@ var LambdaEventSourceMappingProvider = class {
|
|
|
9364
9379
|
async create(logicalId, resourceType, properties, context) {
|
|
9365
9380
|
const log = this.operationSinks(context?.maskSecrets, properties);
|
|
9366
9381
|
log.debug(`Creating event source mapping ${logicalId}`);
|
|
9367
|
-
const desiredTags = refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId);
|
|
9382
|
+
const desiredTags = refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, void 0, "Tags", DBPROXY_TAGS_WHAT, DBPROXY_TAG_OPTIONS);
|
|
9368
9383
|
const functionName = properties["FunctionName"];
|
|
9369
9384
|
if (!functionName) throw new ProvisioningError(`FunctionName is required for event source mapping ${logicalId}`, resourceType, logicalId);
|
|
9370
9385
|
if (declaredConsumptionMode(properties) !== void 0) {
|
|
@@ -9378,7 +9393,7 @@ var LambdaEventSourceMappingProvider = class {
|
|
|
9378
9393
|
if (properties["BatchSize"]) params.BatchSize = properties["BatchSize"];
|
|
9379
9394
|
if (properties["StartingPosition"]) params.StartingPosition = properties["StartingPosition"];
|
|
9380
9395
|
if (properties["Enabled"] !== void 0) params.Enabled = properties["Enabled"];
|
|
9381
|
-
if (properties["MaximumBatchingWindowInSeconds"]) params.MaximumBatchingWindowInSeconds = properties["MaximumBatchingWindowInSeconds"];
|
|
9396
|
+
if (properties["MaximumBatchingWindowInSeconds"] !== void 0) params.MaximumBatchingWindowInSeconds = properties["MaximumBatchingWindowInSeconds"];
|
|
9382
9397
|
if (properties["MaximumRetryAttempts"] !== void 0) params.MaximumRetryAttempts = properties["MaximumRetryAttempts"];
|
|
9383
9398
|
if (properties["BisectBatchOnFunctionError"] !== void 0) params.BisectBatchOnFunctionError = properties["BisectBatchOnFunctionError"];
|
|
9384
9399
|
if (properties["MaximumRecordAgeInSeconds"]) params.MaximumRecordAgeInSeconds = properties["MaximumRecordAgeInSeconds"];
|
|
@@ -9402,7 +9417,7 @@ var LambdaEventSourceMappingProvider = class {
|
|
|
9402
9417
|
if (properties["Topics"]) params.Topics = properties["Topics"];
|
|
9403
9418
|
if (properties["StartingPositionTimestamp"] !== void 0) {
|
|
9404
9419
|
const raw = properties["StartingPositionTimestamp"];
|
|
9405
|
-
params.StartingPositionTimestamp = typeof raw === "number" ? /* @__PURE__ */ new Date(raw * 1e3) : raw instanceof Date ? raw :
|
|
9420
|
+
params.StartingPositionTimestamp = typeof raw === "number" ? /* @__PURE__ */ new Date(raw * 1e3) : raw instanceof Date ? raw : parseCfnTimestamp(raw);
|
|
9406
9421
|
}
|
|
9407
9422
|
const orphanWindow = createEventSourceMappingLatch.take(logicalId);
|
|
9408
9423
|
if (orphanWindow !== void 0) await this.reportPossibleMappingOrphans(logicalId, orphanWindow, log, functionName, params.EventSourceArn);
|
|
@@ -9458,22 +9473,29 @@ var LambdaEventSourceMappingProvider = class {
|
|
|
9458
9473
|
}
|
|
9459
9474
|
async update(logicalId, physicalId, resourceType, properties, previousProperties, context) {
|
|
9460
9475
|
const log = this.operationSinks(context?.maskSecrets, properties, previousProperties);
|
|
9461
|
-
refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId);
|
|
9476
|
+
refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId, "Tags", DBPROXY_TAGS_WHAT, DBPROXY_TAG_OPTIONS);
|
|
9477
|
+
const restoring = context?.replayingState === true || context?.desiredFromAwsReadback === true;
|
|
9478
|
+
for (const key of ["Queues", "Topics"]) {
|
|
9479
|
+
if (JSON.stringify(properties[key]) === JSON.stringify(previousProperties[key])) continue;
|
|
9480
|
+
const reason = `${key} cannot be changed on an existing event source mapping (UpdateEventSourceMapping does not take it, and CloudFormation refuses the change too)`;
|
|
9481
|
+
if (!restoring) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `${reason}; deploy with --replace to delete and recreate the mapping`);
|
|
9482
|
+
log.warn(safeMsg`AWS::Lambda::EventSourceMapping ${logicalId}: ${reason}. Proceeding without it: this update restores a recorded or read-back configuration.`);
|
|
9483
|
+
}
|
|
9462
9484
|
const desiredMode = declaredConsumptionMode(properties);
|
|
9463
9485
|
if (desiredMode !== void 0 && JSON.stringify(desiredMode) !== JSON.stringify(declaredConsumptionMode(previousProperties))) {
|
|
9464
9486
|
const message = consumptionModeRefusalMessage(logicalId, "update");
|
|
9465
|
-
if (
|
|
9487
|
+
if (!restoring) throw new ProvisioningError(message, resourceType, logicalId, physicalId);
|
|
9466
9488
|
log.warn(safeMsg`${message} Proceeding without it: this update restores a recorded or read-back configuration.`);
|
|
9467
9489
|
}
|
|
9468
9490
|
try {
|
|
9469
|
-
return await this.applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, log,
|
|
9491
|
+
return await this.applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, log, restoring);
|
|
9470
9492
|
} catch (error) {
|
|
9471
9493
|
if (error instanceof CdkdError) throw error;
|
|
9472
9494
|
const cause = error instanceof Error ? error : void 0;
|
|
9473
9495
|
throw this.wrapMaskedError(log, error, (text) => new ProvisioningError(`Failed to update event source mapping ${logicalId}: ${text}`, resourceType, logicalId, physicalId, cause));
|
|
9474
9496
|
}
|
|
9475
9497
|
}
|
|
9476
|
-
async applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, log,
|
|
9498
|
+
async applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, log, restoring) {
|
|
9477
9499
|
log.debug(`Updating event source mapping ${logicalId}: ${physicalId}`);
|
|
9478
9500
|
const updateParams = {
|
|
9479
9501
|
UUID: physicalId,
|
|
@@ -9494,7 +9516,7 @@ var LambdaEventSourceMappingProvider = class {
|
|
|
9494
9516
|
if (properties["ScalingConfig"] !== void 0) updateParams.ScalingConfig = properties["ScalingConfig"];
|
|
9495
9517
|
if (properties["DocumentDBEventSourceConfig"] !== void 0) updateParams.DocumentDBEventSourceConfig = properties["DocumentDBEventSourceConfig"];
|
|
9496
9518
|
for (const key of ["SelfManagedKafkaEventSourceConfig", "AmazonManagedKafkaEventSourceConfig"]) {
|
|
9497
|
-
const block = kafkaConfigForUpdate(properties[key], previousProperties[key], { restoring
|
|
9519
|
+
const block = kafkaConfigForUpdate(properties[key], previousProperties[key], { restoring });
|
|
9498
9520
|
if (block !== void 0) updateParams[key] = block;
|
|
9499
9521
|
}
|
|
9500
9522
|
if (properties["KmsKeyArn"] !== void 0) updateParams.KMSKeyArn = properties["KmsKeyArn"];
|
|
@@ -9539,7 +9561,7 @@ var LambdaEventSourceMappingProvider = class {
|
|
|
9539
9561
|
};
|
|
9540
9562
|
}
|
|
9541
9563
|
async applyTagDiff(arn, resourceType, logicalId, oldTagsRaw, newTagsRaw, log) {
|
|
9542
|
-
const plan = planTagDiff(oldTagsRaw, newTagsRaw);
|
|
9564
|
+
const plan = planTagDiff(oldTagsRaw, newTagsRaw, DBPROXY_TAG_OPTIONS);
|
|
9543
9565
|
const tagWarning = tagPlanWarning(plan, resourceType, logicalId);
|
|
9544
9566
|
if (tagWarning !== void 0) log.warn(tagWarning);
|
|
9545
9567
|
const tagsToAdd = Object.fromEntries(plan.set);
|
|
@@ -9749,6 +9771,7 @@ var LambdaLayerVersionProvider = class {
|
|
|
9749
9771
|
if (content["S3Bucket"]) contentInput.S3Bucket = content["S3Bucket"];
|
|
9750
9772
|
if (content["S3Key"]) contentInput.S3Key = content["S3Key"];
|
|
9751
9773
|
if (content["S3ObjectVersion"]) contentInput.S3ObjectVersion = content["S3ObjectVersion"];
|
|
9774
|
+
if (content["S3ObjectStorageMode"]) contentInput.S3ObjectStorageMode = content["S3ObjectStorageMode"];
|
|
9752
9775
|
const orphanWindow = publishLayerVersionLatch.take(logicalId);
|
|
9753
9776
|
if (orphanWindow !== void 0) await this.reportPossibleLayerOrphans(logicalId, orphanWindow, log, layerName);
|
|
9754
9777
|
const createClient = await this.getCreateClient();
|
|
@@ -11614,7 +11637,7 @@ const STREAM_POLICY_KEY = "ResourcePolicy";
|
|
|
11614
11637
|
const STREAM_TAGS_KEY = "Tags";
|
|
11615
11638
|
const POLICY_PATH = `${STREAM_SPECIFICATION_KEY}.${STREAM_POLICY_KEY}`;
|
|
11616
11639
|
const TAGS_PATH = `${STREAM_SPECIFICATION_KEY}.${STREAM_TAGS_KEY}`;
|
|
11617
|
-
function isPlainObject$
|
|
11640
|
+
function isPlainObject$2(value) {
|
|
11618
11641
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
11619
11642
|
}
|
|
11620
11643
|
function refusalOf(guard) {
|
|
@@ -11626,7 +11649,7 @@ function refusalOf(guard) {
|
|
|
11626
11649
|
}
|
|
11627
11650
|
}
|
|
11628
11651
|
function blockMembers(block) {
|
|
11629
|
-
return isPlainObject$
|
|
11652
|
+
return isPlainObject$2(block) ? block : {};
|
|
11630
11653
|
}
|
|
11631
11654
|
function readStreamPolicy(block) {
|
|
11632
11655
|
const value = blockMembers(block)[STREAM_POLICY_KEY];
|
|
@@ -11801,7 +11824,7 @@ function streamTagsMatchDeclared(liveTags, desiredBlock) {
|
|
|
11801
11824
|
}
|
|
11802
11825
|
function canonicalJson(value) {
|
|
11803
11826
|
if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
|
|
11804
|
-
if (isPlainObject$
|
|
11827
|
+
if (isPlainObject$2(value)) return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`).join(",")}}`;
|
|
11805
11828
|
return JSON.stringify(value) ?? "null";
|
|
11806
11829
|
}
|
|
11807
11830
|
|
|
@@ -12139,6 +12162,32 @@ function indexDeclares(desired, key, bagInformative) {
|
|
|
12139
12162
|
function declaresIndexList(value) {
|
|
12140
12163
|
return Array.isArray(value) && value.length > 0;
|
|
12141
12164
|
}
|
|
12165
|
+
function deletionProtectionRefusal(value, logicalId) {
|
|
12166
|
+
return configBooleanRefusal({ DeletionProtectionEnabled: value }, "DeletionProtectionEnabled", `AWS::DynamoDB::Table ${logicalId}`);
|
|
12167
|
+
}
|
|
12168
|
+
function localSecondaryIndexesKey(value) {
|
|
12169
|
+
if (value === void 0 || value === null) return "[]";
|
|
12170
|
+
if (!Array.isArray(value)) return JSON.stringify(value);
|
|
12171
|
+
const isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
12172
|
+
const entries = value.map((entry) => {
|
|
12173
|
+
if (!isRecord(entry)) return JSON.stringify(entry);
|
|
12174
|
+
const keySchema = Array.isArray(entry["KeySchema"]) ? entry["KeySchema"].map((element) => isRecord(element) ? {
|
|
12175
|
+
AttributeName: element["AttributeName"],
|
|
12176
|
+
KeyType: element["KeyType"]
|
|
12177
|
+
} : element) : entry["KeySchema"];
|
|
12178
|
+
const projection = entry["Projection"];
|
|
12179
|
+
const projectionKey = isRecord(projection) ? {
|
|
12180
|
+
ProjectionType: projection["ProjectionType"],
|
|
12181
|
+
NonKeyAttributes: Array.isArray(projection["NonKeyAttributes"]) ? projection["NonKeyAttributes"].length > 0 ? [...projection["NonKeyAttributes"]].map(String).sort() : void 0 : projection["NonKeyAttributes"]
|
|
12182
|
+
} : projection;
|
|
12183
|
+
return JSON.stringify({
|
|
12184
|
+
IndexName: entry["IndexName"],
|
|
12185
|
+
KeySchema: keySchema,
|
|
12186
|
+
Projection: projectionKey
|
|
12187
|
+
});
|
|
12188
|
+
});
|
|
12189
|
+
return JSON.stringify(entries.sort());
|
|
12190
|
+
}
|
|
12142
12191
|
function desiredIndexEntriesByName(value) {
|
|
12143
12192
|
const byName = /* @__PURE__ */ new Map();
|
|
12144
12193
|
if (!declaresIndexList(value)) return byName;
|
|
@@ -12271,7 +12320,11 @@ var DynamoDBTableProvider = class {
|
|
|
12271
12320
|
Key: t.Key,
|
|
12272
12321
|
Value: t.Value
|
|
12273
12322
|
}));
|
|
12274
|
-
if (properties["DeletionProtectionEnabled"] !== void 0)
|
|
12323
|
+
if (properties["DeletionProtectionEnabled"] !== void 0) {
|
|
12324
|
+
const protectionRefusal = deletionProtectionRefusal(properties["DeletionProtectionEnabled"], logicalId);
|
|
12325
|
+
if (protectionRefusal !== void 0) throw new ProvisioningError(`${maskSecrets(protectionRefusal)}. Nothing was created; fix the template value`, resourceType, logicalId);
|
|
12326
|
+
createParams.DeletionProtectionEnabled = coerceCfnBoolean(properties["DeletionProtectionEnabled"]);
|
|
12327
|
+
}
|
|
12275
12328
|
if (properties["TableClass"]) createParams.TableClass = properties["TableClass"];
|
|
12276
12329
|
const createResourcePolicyDoc = this.extractResourcePolicyDocument(properties["ResourcePolicy"]);
|
|
12277
12330
|
if (createResourcePolicyDoc !== void 0) createParams.ResourcePolicy = createResourcePolicyDoc;
|
|
@@ -12345,7 +12398,18 @@ var DynamoDBTableProvider = class {
|
|
|
12345
12398
|
const ceilingRefusal = onDemandCeilingRefusal(properties, previousProperties, logicalId);
|
|
12346
12399
|
if (ceilingRefusal !== void 0) throw new ProvisioningError(`${ceilingRefusal}. Nothing was applied to the table; fix the template value`, resourceType, logicalId, physicalId);
|
|
12347
12400
|
}
|
|
12401
|
+
const deletionProtectionChanged = JSON.stringify(properties["DeletionProtectionEnabled"]) !== JSON.stringify(previousProperties["DeletionProtectionEnabled"]);
|
|
12402
|
+
if (deletionProtectionChanged && context?.replayingState !== true && context?.desiredFromAwsReadback !== true) {
|
|
12403
|
+
const protectionRefusal = deletionProtectionRefusal(properties["DeletionProtectionEnabled"], logicalId);
|
|
12404
|
+
if (protectionRefusal !== void 0) throw new ProvisioningError(`${maskSecrets(protectionRefusal)}. Nothing was applied to the table; fix the template value`, resourceType, logicalId, physicalId);
|
|
12405
|
+
}
|
|
12348
12406
|
const table = (await this.dynamoDBClient.send(new DescribeTableCommand({ TableName: physicalId }))).Table;
|
|
12407
|
+
const desiredLsiKey = localSecondaryIndexesKey(properties["LocalSecondaryIndexes"]);
|
|
12408
|
+
if (desiredLsiKey !== localSecondaryIndexesKey(previousProperties["LocalSecondaryIndexes"]) && (table === void 0 || desiredLsiKey !== localSecondaryIndexesKey(table.LocalSecondaryIndexes))) {
|
|
12409
|
+
const lsiMessage = `AWS::DynamoDB::Table ${logicalId}: LocalSecondaryIndexes changed, but DynamoDB cannot add, remove or modify a local secondary index on an existing table, and CloudFormation fails the same update rather than replacing the table`;
|
|
12410
|
+
if (context?.replayingState !== true && context?.desiredFromAwsReadback !== true) throw new ProvisioningError(`${lsiMessage}. Nothing was applied to the table; revert the LocalSecondaryIndexes change, or create a new table under a new logical ID (a new table starts empty)`, resourceType, logicalId, physicalId);
|
|
12411
|
+
warn(`${lsiMessage}; the LocalSecondaryIndexes change was not applied`);
|
|
12412
|
+
}
|
|
12349
12413
|
let latestStreamArn = table?.LatestStreamArn;
|
|
12350
12414
|
if (table?.TableArn) await this.applyTagDiff(table.TableArn, resourceType, logicalId, previousProperties["Tags"], properties["Tags"]);
|
|
12351
12415
|
const normalizeTableClass = (v) => typeof v === "string" && v.length > 0 ? v : "STANDARD";
|
|
@@ -12493,6 +12557,19 @@ var DynamoDBTableProvider = class {
|
|
|
12493
12557
|
this.logger.debug(`Updated SSESpecification on DynamoDB table ${physicalId}`);
|
|
12494
12558
|
}
|
|
12495
12559
|
}
|
|
12560
|
+
if (deletionProtectionChanged) {
|
|
12561
|
+
const rawDeletionProtection = properties["DeletionProtectionEnabled"];
|
|
12562
|
+
const desiredDeletionProtection = rawDeletionProtection === void 0 ? false : coerceCfnBoolean(rawDeletionProtection);
|
|
12563
|
+
if (desiredDeletionProtection === void 0) warn(`AWS::DynamoDB::Table ${logicalId}: DeletionProtectionEnabled is not a boolean, so it was not applied`);
|
|
12564
|
+
else if (table?.DeletionProtectionEnabled !== desiredDeletionProtection) {
|
|
12565
|
+
await this.dynamoDBClient.send(new UpdateTableCommand({
|
|
12566
|
+
TableName: physicalId,
|
|
12567
|
+
DeletionProtectionEnabled: desiredDeletionProtection
|
|
12568
|
+
}));
|
|
12569
|
+
await this.waitForTableActiveAfterUpdate(physicalId);
|
|
12570
|
+
debug(`Set DeletionProtectionEnabled=${desiredDeletionProtection} on DynamoDB table ${physicalId}`);
|
|
12571
|
+
}
|
|
12572
|
+
}
|
|
12496
12573
|
if (JSON.stringify(properties["StreamSpecification"]) !== JSON.stringify(previousProperties["StreamSpecification"])) {
|
|
12497
12574
|
const newViewType = this.extractStreamViewType(properties["StreamSpecification"]);
|
|
12498
12575
|
const prevViewType = this.extractStreamViewType(previousProperties["StreamSpecification"]);
|
|
@@ -13277,6 +13354,11 @@ var DynamoDBTableProvider = class {
|
|
|
13277
13354
|
canonicalizeDriftProperties(resourceType, properties) {
|
|
13278
13355
|
if (resourceType !== "AWS::DynamoDB::Table") return properties;
|
|
13279
13356
|
let result = properties;
|
|
13357
|
+
const protection = coerceCfnBoolean(result["DeletionProtectionEnabled"]);
|
|
13358
|
+
if (protection !== void 0 && protection !== result["DeletionProtectionEnabled"]) result = {
|
|
13359
|
+
...result,
|
|
13360
|
+
DeletionProtectionEnabled: protection
|
|
13361
|
+
};
|
|
13280
13362
|
for (const listKey of ["GlobalSecondaryIndexes", "LocalSecondaryIndexes"]) {
|
|
13281
13363
|
const list = result[listKey];
|
|
13282
13364
|
if (!Array.isArray(list)) continue;
|
|
@@ -14550,7 +14632,7 @@ function buildDeleteParams(properties) {
|
|
|
14550
14632
|
function toDate(value, mask) {
|
|
14551
14633
|
if (value === void 0) return void 0;
|
|
14552
14634
|
if (value instanceof Date) return value;
|
|
14553
|
-
const parsed = typeof value === "string"
|
|
14635
|
+
const parsed = typeof value === "string" ? parseCfnTimestamp(value) : typeof value === "number" ? new Date(value) : /* @__PURE__ */ new Date(NaN);
|
|
14554
14636
|
if (Number.isNaN(parsed.getTime())) throw new Error(`Configuration.ExcludedTimeRanges contains an unparsable time value: ${JSON.stringify(maskDeep(value, mask))}`);
|
|
14555
14637
|
return parsed;
|
|
14556
14638
|
}
|
|
@@ -16184,6 +16266,125 @@ function isNamedError(error, names) {
|
|
|
16184
16266
|
return typeof name === "string" && names.has(name);
|
|
16185
16267
|
}
|
|
16186
16268
|
const NAT_GATEWAY_NOT_FOUND_NAMES = /* @__PURE__ */ new Set(["NatGatewayNotFound"]);
|
|
16269
|
+
function readNatZoneAddresses(raw) {
|
|
16270
|
+
if (raw === void 0 || raw === null) return { kind: "absent" };
|
|
16271
|
+
const unusable = (reason) => ({
|
|
16272
|
+
kind: "unusable",
|
|
16273
|
+
reason
|
|
16274
|
+
});
|
|
16275
|
+
if (!Array.isArray(raw)) return unusable("is not a list");
|
|
16276
|
+
if (raw.length === 0) return unusable("is an empty list");
|
|
16277
|
+
const entries = [];
|
|
16278
|
+
const seen = /* @__PURE__ */ new Set();
|
|
16279
|
+
for (const [index, item] of raw.entries()) {
|
|
16280
|
+
if (typeof item !== "object" || item === null || Array.isArray(item)) return unusable(`entry ${index} is not an object`);
|
|
16281
|
+
const record = item;
|
|
16282
|
+
const zone = record["AvailabilityZone"];
|
|
16283
|
+
const zoneId = record["AvailabilityZoneId"];
|
|
16284
|
+
if (zone !== void 0 && (typeof zone !== "string" || zone === "")) return unusable(`entry ${index}'s AvailabilityZone is not a zone name`);
|
|
16285
|
+
if (zoneId !== void 0 && (typeof zoneId !== "string" || zoneId === "")) return unusable(`entry ${index}'s AvailabilityZoneId is not a zone id`);
|
|
16286
|
+
if (zone === void 0 && zoneId === void 0) return unusable(`entry ${index} names neither AvailabilityZone nor AvailabilityZoneId`);
|
|
16287
|
+
const ids = record["AllocationIds"];
|
|
16288
|
+
if (!Array.isArray(ids) || ids.length === 0 || ids.some((id) => typeof id !== "string" || id === "")) return unusable(`entry ${index}'s AllocationIds is not a non-empty list of allocation ids`);
|
|
16289
|
+
for (const id of ids) {
|
|
16290
|
+
if (seen.has(id)) return unusable(`declares allocation id ${id} more than once`);
|
|
16291
|
+
seen.add(id);
|
|
16292
|
+
}
|
|
16293
|
+
entries.push({
|
|
16294
|
+
...zone !== void 0 && { availabilityZone: zone },
|
|
16295
|
+
...zoneId !== void 0 && { availabilityZoneId: zoneId },
|
|
16296
|
+
allocationIds: [...ids]
|
|
16297
|
+
});
|
|
16298
|
+
}
|
|
16299
|
+
return {
|
|
16300
|
+
kind: "usable",
|
|
16301
|
+
entries
|
|
16302
|
+
};
|
|
16303
|
+
}
|
|
16304
|
+
function natGatewayAttributes(gateway) {
|
|
16305
|
+
const addresses = gateway.NatGatewayAddresses ?? [];
|
|
16306
|
+
const primary = addresses.find((a) => a.IsPrimary === true) ?? addresses[0];
|
|
16307
|
+
return definedAttributes({
|
|
16308
|
+
NatGatewayId: gateway.NatGatewayId,
|
|
16309
|
+
EniId: gateway.AvailabilityMode === "regional" ? void 0 : primary?.NetworkInterfaceId,
|
|
16310
|
+
RouteTableId: gateway.RouteTableId,
|
|
16311
|
+
AutoProvisionZones: gateway.AutoProvisionZones,
|
|
16312
|
+
AutoScalingIps: gateway.AutoScalingIps
|
|
16313
|
+
});
|
|
16314
|
+
}
|
|
16315
|
+
const NAT_ADDRESS_SETTLE_POLLS = 90;
|
|
16316
|
+
const NAT_ADDRESS_SETTLE_DELAY_MS = 1e4;
|
|
16317
|
+
const NAT_ADDRESS_UNLISTED_POLLS = 6;
|
|
16318
|
+
function natAddressInZone(address, entry) {
|
|
16319
|
+
return entry.availabilityZone !== void 0 && address.AvailabilityZone === entry.availabilityZone || entry.availabilityZoneId !== void 0 && address.AvailabilityZoneId === entry.availabilityZoneId;
|
|
16320
|
+
}
|
|
16321
|
+
function natAddressHeld(address) {
|
|
16322
|
+
return typeof address.AllocationId === "string" && address.Status !== "disassociating" && address.Status !== "failed";
|
|
16323
|
+
}
|
|
16324
|
+
function planNatZoneAddressUpdate(desired, live) {
|
|
16325
|
+
const held = live.filter(natAddressHeld);
|
|
16326
|
+
const associate = [];
|
|
16327
|
+
const moved = [];
|
|
16328
|
+
const awaitingRelease = [];
|
|
16329
|
+
const wanted = /* @__PURE__ */ new Set();
|
|
16330
|
+
for (const entry of desired) {
|
|
16331
|
+
const missing = [];
|
|
16332
|
+
for (const allocationId of entry.allocationIds) {
|
|
16333
|
+
wanted.add(allocationId);
|
|
16334
|
+
const holder = held.find((a) => a.AllocationId === allocationId);
|
|
16335
|
+
if (holder === void 0) {
|
|
16336
|
+
missing.push(allocationId);
|
|
16337
|
+
if (live.some((a) => a.AllocationId === allocationId && a.Status === "disassociating")) awaitingRelease.push(allocationId);
|
|
16338
|
+
} else if (!natAddressInZone(holder, entry)) moved.push(allocationId);
|
|
16339
|
+
}
|
|
16340
|
+
if (missing.length > 0) associate.push({
|
|
16341
|
+
...entry,
|
|
16342
|
+
allocationIds: missing
|
|
16343
|
+
});
|
|
16344
|
+
}
|
|
16345
|
+
return {
|
|
16346
|
+
associate,
|
|
16347
|
+
disassociate: held.filter((a) => !wanted.has(a.AllocationId)).map((a) => ({
|
|
16348
|
+
allocationId: a.AllocationId,
|
|
16349
|
+
associationId: a.AssociationId
|
|
16350
|
+
})),
|
|
16351
|
+
moved,
|
|
16352
|
+
awaitingRelease,
|
|
16353
|
+
keptSettled: held.some((a) => wanted.has(a.AllocationId) && a.Status === "succeeded")
|
|
16354
|
+
};
|
|
16355
|
+
}
|
|
16356
|
+
function readbackNatZoneAddresses(live, recorded) {
|
|
16357
|
+
const held = live.filter(natAddressHeld).filter((a) => a.AvailabilityZone !== void 0 || a.AvailabilityZoneId !== void 0);
|
|
16358
|
+
const out = [];
|
|
16359
|
+
const emit = (entry, addresses) => {
|
|
16360
|
+
if (addresses.length === 0) return;
|
|
16361
|
+
const ids = addresses.map((a) => a.AllocationId);
|
|
16362
|
+
const ordered = [...entry.allocationIds.filter((id) => ids.includes(id)), ...ids.filter((id) => !entry.allocationIds.includes(id))];
|
|
16363
|
+
out.push({
|
|
16364
|
+
...entry.availabilityZone !== void 0 && { AvailabilityZone: entry.availabilityZone },
|
|
16365
|
+
...entry.availabilityZoneId !== void 0 && { AvailabilityZoneId: entry.availabilityZoneId },
|
|
16366
|
+
AllocationIds: ordered
|
|
16367
|
+
});
|
|
16368
|
+
};
|
|
16369
|
+
let rest = held;
|
|
16370
|
+
for (const entry of recorded) {
|
|
16371
|
+
emit(entry, rest.filter((a) => natAddressInZone(a, entry)));
|
|
16372
|
+
rest = rest.filter((a) => !natAddressInZone(a, entry));
|
|
16373
|
+
}
|
|
16374
|
+
const zones = [...new Set(rest.map((a) => a.AvailabilityZone ?? a.AvailabilityZoneId ?? ""))];
|
|
16375
|
+
for (const zone of zones) {
|
|
16376
|
+
const inZone = rest.filter((a) => (a.AvailabilityZone ?? a.AvailabilityZoneId ?? "") === zone);
|
|
16377
|
+
const first = inZone[0];
|
|
16378
|
+
emit(first.AvailabilityZone !== void 0 ? {
|
|
16379
|
+
availabilityZone: first.AvailabilityZone,
|
|
16380
|
+
allocationIds: []
|
|
16381
|
+
} : {
|
|
16382
|
+
availabilityZoneId: first.AvailabilityZoneId,
|
|
16383
|
+
allocationIds: []
|
|
16384
|
+
}, inZone);
|
|
16385
|
+
}
|
|
16386
|
+
return out;
|
|
16387
|
+
}
|
|
16187
16388
|
const EIP_ALLOCATION_NOT_FOUND_NAMES = /* @__PURE__ */ new Set(["InvalidAllocationID.NotFound"]);
|
|
16188
16389
|
const INSTANCE_NOT_FOUND_NAMES = /* @__PURE__ */ new Set(["InvalidInstanceID.NotFound"]);
|
|
16189
16390
|
const VPC_NOT_FOUND_NAMES = /* @__PURE__ */ new Set(["InvalidVpcID.NotFound"]);
|
|
@@ -16265,7 +16466,10 @@ var EC2Provider = class {
|
|
|
16265
16466
|
"SecondaryAllocationIds",
|
|
16266
16467
|
"SecondaryPrivateIpAddresses",
|
|
16267
16468
|
"SecondaryPrivateIpAddressCount",
|
|
16268
|
-
"Tags"
|
|
16469
|
+
"Tags",
|
|
16470
|
+
"AvailabilityMode",
|
|
16471
|
+
"VpcId",
|
|
16472
|
+
"AvailabilityZoneAddresses"
|
|
16269
16473
|
])],
|
|
16270
16474
|
["AWS::EC2::RouteTable", /* @__PURE__ */ new Set(["VpcId", "Tags"])],
|
|
16271
16475
|
["AWS::EC2::Route", /* @__PURE__ */ new Set([
|
|
@@ -16343,7 +16547,7 @@ var EC2Provider = class {
|
|
|
16343
16547
|
unhandledByDesign = /* @__PURE__ */ new Map([
|
|
16344
16548
|
["AWS::EC2::Instance", /* @__PURE__ */ new Map([["ElasticGpuSpecifications", "AWS Elastic GPU end-of-life (announced 2023-11); no replacement API"], ["ElasticInferenceAccelerators", "AWS Elastic Inference end-of-life 2024-04; use AWS Inferentia / Trainium accelerator instance families instead"]])],
|
|
16345
16549
|
["AWS::EC2::SecurityGroupIngress", /* @__PURE__ */ new Map([["GroupName", "EC2-Classic-only — use GroupId for VPC security groups (EC2-Classic retired 2022-08-15)"], ["SourceSecurityGroupName", "EC2-Classic-only — use SourceSecurityGroupId for VPC peer security groups (EC2-Classic retired 2022-08-15)"]])],
|
|
16346
|
-
["AWS::EC2::NatGateway", /* @__PURE__ */ new Map([["
|
|
16550
|
+
["AWS::EC2::NatGateway", /* @__PURE__ */ new Map([["MaxDrainDurationSeconds", "write-only address-drain timeout with no CreateNatGateway member and no NAT gateway modify API; only ec2:DisassociateNatGatewayAddress / UnassignPrivateNatGatewayAddress accept it, and the cdkd NatGateway update releases only the AvailabilityZoneAddresses of a regional gateway, never the secondary addresses of a zonal one — routed via Cloud Control instead"]])],
|
|
16347
16551
|
["AWS::EC2::EIP", /* @__PURE__ */ new Map([
|
|
16348
16552
|
["Address", "Bring-your-own-IP: allocating a specific address you own is not yet supported; cdkd allocates an Amazon-owned address"],
|
|
16349
16553
|
["IpamPoolId", "Allocation from an IPAM pool is not yet supported"],
|
|
@@ -16509,7 +16713,7 @@ var EC2Provider = class {
|
|
|
16509
16713
|
case "AWS::EC2::InternetGateway": return this.updateInternetGateway(logicalId, physicalId);
|
|
16510
16714
|
case "AWS::EC2::EIP": return this.updateEip(logicalId, physicalId, resourceType, properties, previousProperties, context);
|
|
16511
16715
|
case "AWS::EC2::VPCGatewayAttachment": return this.updateVpcGatewayAttachment(logicalId, physicalId, resourceType, properties, previousProperties, context);
|
|
16512
|
-
case "AWS::EC2::NatGateway": return this.updateNatGateway(logicalId, physicalId);
|
|
16716
|
+
case "AWS::EC2::NatGateway": return this.updateNatGateway(logicalId, physicalId, resourceType, properties, previousProperties, context);
|
|
16513
16717
|
case "AWS::EC2::RouteTable": return this.updateRouteTable(logicalId, physicalId);
|
|
16514
16718
|
case "AWS::EC2::Route": return this.updateRoute(logicalId, physicalId, resourceType, properties, previousProperties, context);
|
|
16515
16719
|
case "AWS::EC2::SubnetRouteTableAssociation": return this.updateSubnetRouteTableAssociation(logicalId, physicalId);
|
|
@@ -16551,9 +16755,15 @@ var EC2Provider = class {
|
|
|
16551
16755
|
case "AWS::EC2::SecurityGroup": return this.getSecurityGroupAttribute(physicalId, attributeName);
|
|
16552
16756
|
case "AWS::EC2::Instance": return this.getInstanceAttribute(physicalId, attributeName);
|
|
16553
16757
|
case "AWS::EC2::EIP": return this.getEipAttribute(physicalId, attributeName);
|
|
16758
|
+
case "AWS::EC2::NatGateway": return this.getNatGatewayAttribute(physicalId, attributeName);
|
|
16554
16759
|
default: return;
|
|
16555
16760
|
}
|
|
16556
16761
|
}
|
|
16762
|
+
async getNatGatewayAttribute(physicalId, attributeName) {
|
|
16763
|
+
if (attributeName === "NatGatewayId") return physicalId;
|
|
16764
|
+
const gateway = (await this.ec2Client.send(new DescribeNatGatewaysCommand({ NatGatewayIds: [physicalId] }))).NatGateways?.find((g) => g.NatGatewayId === physicalId);
|
|
16765
|
+
return gateway === void 0 ? void 0 : natGatewayAttributes(gateway)[attributeName];
|
|
16766
|
+
}
|
|
16557
16767
|
async isSameResource(journaledPhysicalId, record, resourceType, context) {
|
|
16558
16768
|
let read;
|
|
16559
16769
|
let identity;
|
|
@@ -17050,7 +17260,7 @@ var EC2Provider = class {
|
|
|
17050
17260
|
}
|
|
17051
17261
|
}
|
|
17052
17262
|
updateInternetGateway(logicalId, physicalId) {
|
|
17053
|
-
return Promise.reject(new ResourceUpdateNotSupportedError("AWS::EC2::InternetGateway", logicalId, "destroy + redeploy the InternetGateway. IGW properties are immutable in AWS
|
|
17263
|
+
return Promise.reject(new ResourceUpdateNotSupportedError("AWS::EC2::InternetGateway", logicalId, "destroy + redeploy the InternetGateway. IGW properties are immutable in AWS"));
|
|
17054
17264
|
}
|
|
17055
17265
|
async deleteInternetGateway(logicalId, physicalId, resourceType, context) {
|
|
17056
17266
|
this.logger.debug(`Deleting InternetGateway ${logicalId}: ${physicalId}`);
|
|
@@ -17559,8 +17769,11 @@ var EC2Provider = class {
|
|
|
17559
17769
|
async createNatGateway(logicalId, resourceType, properties, context) {
|
|
17560
17770
|
this.logger.debug(`Creating NatGateway ${logicalId}`);
|
|
17561
17771
|
const desiredTags = refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId);
|
|
17772
|
+
const regional = properties["AvailabilityMode"] === "regional";
|
|
17562
17773
|
const subnetId = properties["SubnetId"];
|
|
17563
|
-
if (!subnetId) throw new ProvisioningError(`SubnetId is required for NatGateway ${logicalId}`, resourceType, logicalId);
|
|
17774
|
+
if (!subnetId && !regional) throw new ProvisioningError(`SubnetId is required for NatGateway ${logicalId} (a regional NAT gateway, AvailabilityMode: regional, takes VpcId instead)`, resourceType, logicalId);
|
|
17775
|
+
const zoneAddresses = readNatZoneAddresses(properties["AvailabilityZoneAddresses"]);
|
|
17776
|
+
if (zoneAddresses.kind === "unusable") throw new ProvisioningError(`AvailabilityZoneAddresses of NatGateway ${logicalId} ${zoneAddresses.reason}; each entry needs AvailabilityZone or AvailabilityZoneId and a non-empty AllocationIds list`, resourceType, logicalId);
|
|
17564
17777
|
const natGatewayToken = acquireIdempotencyToken({
|
|
17565
17778
|
scope: "CreateNatGateway",
|
|
17566
17779
|
logicalId
|
|
@@ -17571,6 +17784,13 @@ var EC2Provider = class {
|
|
|
17571
17784
|
...TagSpecifications && { TagSpecifications },
|
|
17572
17785
|
ClientToken: natGatewayToken.value,
|
|
17573
17786
|
SubnetId: subnetId,
|
|
17787
|
+
AvailabilityMode: properties["AvailabilityMode"],
|
|
17788
|
+
VpcId: properties["VpcId"],
|
|
17789
|
+
...zoneAddresses.kind === "usable" && { AvailabilityZoneAddresses: zoneAddresses.entries.map((entry) => ({
|
|
17790
|
+
AvailabilityZone: entry.availabilityZone,
|
|
17791
|
+
AvailabilityZoneId: entry.availabilityZoneId,
|
|
17792
|
+
AllocationIds: entry.allocationIds
|
|
17793
|
+
})) },
|
|
17574
17794
|
AllocationId: properties["AllocationId"],
|
|
17575
17795
|
ConnectivityType: properties["ConnectivityType"] ?? void 0,
|
|
17576
17796
|
PrivateIpAddress: properties["PrivateIpAddress"],
|
|
@@ -17581,21 +17801,26 @@ var EC2Provider = class {
|
|
|
17581
17801
|
const natGatewayId = response.NatGateway.NatGatewayId;
|
|
17582
17802
|
createdId = natGatewayId;
|
|
17583
17803
|
if (!tagsApplied) await this.applyTags(natGatewayId, desiredTags, logicalId, maskerOrIdentity(context?.maskSecrets));
|
|
17804
|
+
let described;
|
|
17584
17805
|
if (process.env["CDKD_NO_WAIT"] !== "true") {
|
|
17585
17806
|
this.logger.debug(`Waiting for NatGateway ${natGatewayId} to reach available state...`);
|
|
17586
|
-
await waitUntilNatGatewayAvailable({
|
|
17807
|
+
described = (await waitUntilNatGatewayAvailable({
|
|
17587
17808
|
client: this.ec2Client,
|
|
17588
17809
|
maxWaitTime: 900,
|
|
17589
17810
|
minDelay: 5,
|
|
17590
17811
|
maxDelay: 10
|
|
17591
|
-
}, { NatGatewayIds: [natGatewayId] });
|
|
17812
|
+
}, { NatGatewayIds: [natGatewayId] })).reason?.NatGateways?.find((g) => g.NatGatewayId === natGatewayId);
|
|
17592
17813
|
this.logger.debug(`NatGateway ${natGatewayId} is available`);
|
|
17593
17814
|
} else this.logger.debug(`NatGateway ${natGatewayId} created (skipping available-state wait per --no-wait)`);
|
|
17594
17815
|
this.logger.debug(`Successfully created NatGateway ${logicalId}: ${natGatewayId}`);
|
|
17595
17816
|
natGatewayToken.release();
|
|
17596
17817
|
return {
|
|
17597
17818
|
physicalId: natGatewayId,
|
|
17598
|
-
attributes: {
|
|
17819
|
+
attributes: {
|
|
17820
|
+
...natGatewayAttributes(response.NatGateway ?? {}),
|
|
17821
|
+
...described !== void 0 && natGatewayAttributes(described),
|
|
17822
|
+
NatGatewayId: natGatewayId
|
|
17823
|
+
}
|
|
17599
17824
|
};
|
|
17600
17825
|
} catch (error) {
|
|
17601
17826
|
const cause = error instanceof Error ? error : void 0;
|
|
@@ -17604,8 +17829,125 @@ var EC2Provider = class {
|
|
|
17604
17829
|
throw thrown;
|
|
17605
17830
|
}
|
|
17606
17831
|
}
|
|
17607
|
-
updateNatGateway(logicalId, physicalId) {
|
|
17608
|
-
|
|
17832
|
+
async updateNatGateway(logicalId, physicalId, resourceType, properties, previousProperties, context) {
|
|
17833
|
+
this.logger.debug(safeMsg`Updating NatGateway ${logicalId}: ${physicalId}`);
|
|
17834
|
+
const refuse = (property) => {
|
|
17835
|
+
throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `destroy + redeploy the NatGateway (and the dependent Routes). cdkd cannot change ${property} of an existing NAT gateway`);
|
|
17836
|
+
};
|
|
17837
|
+
for (const key of [
|
|
17838
|
+
"SubnetId",
|
|
17839
|
+
"ConnectivityType",
|
|
17840
|
+
"AllocationId",
|
|
17841
|
+
"PrivateIpAddress",
|
|
17842
|
+
"AvailabilityMode",
|
|
17843
|
+
"VpcId"
|
|
17844
|
+
]) {
|
|
17845
|
+
const next = properties[key];
|
|
17846
|
+
const prev = previousProperties[key];
|
|
17847
|
+
if (next !== void 0 && prev !== void 0 && JSON.stringify(next) !== JSON.stringify(prev)) refuse(key);
|
|
17848
|
+
}
|
|
17849
|
+
if (previousProperties["AvailabilityZoneAddresses"] == null && properties["AvailabilityZoneAddresses"] != null) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "destroy + redeploy the NatGateway (and the dependent Routes). Adding AvailabilityZoneAddresses to a gateway created without it replaces the gateway");
|
|
17850
|
+
for (const key of [
|
|
17851
|
+
"SecondaryAllocationIds",
|
|
17852
|
+
"SecondaryPrivateIpAddresses",
|
|
17853
|
+
"SecondaryPrivateIpAddressCount"
|
|
17854
|
+
]) if (JSON.stringify(properties[key]) !== JSON.stringify(previousProperties[key])) refuse(key);
|
|
17855
|
+
refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId);
|
|
17856
|
+
const mask = maskerOrIdentity(context?.maskSecrets);
|
|
17857
|
+
try {
|
|
17858
|
+
let zonePlan;
|
|
17859
|
+
if (JSON.stringify(properties["AvailabilityZoneAddresses"]) !== JSON.stringify(previousProperties["AvailabilityZoneAddresses"])) zonePlan = await this.planNatGatewayZoneAddresses(logicalId, physicalId, resourceType, properties["AvailabilityZoneAddresses"]);
|
|
17860
|
+
if (zonePlan !== void 0) await this.applyNatGatewayZoneAddresses(logicalId, physicalId, resourceType, zonePlan);
|
|
17861
|
+
await this.applyTagDiff(physicalId, resourceType, logicalId, previousProperties["Tags"], properties["Tags"], mask);
|
|
17862
|
+
this.logger.debug(safeMsg`Successfully updated NatGateway ${logicalId}`);
|
|
17863
|
+
return {
|
|
17864
|
+
physicalId,
|
|
17865
|
+
wasReplaced: false
|
|
17866
|
+
};
|
|
17867
|
+
} catch (error) {
|
|
17868
|
+
if (error instanceof CdkdError) throw error;
|
|
17869
|
+
const cause = error instanceof Error ? error : void 0;
|
|
17870
|
+
throw this.wrapCaughtError(mask, error, (text) => new ProvisioningError(`Failed to update NatGateway ${logicalId}: ${text}`, resourceType, logicalId, physicalId, cause));
|
|
17871
|
+
}
|
|
17872
|
+
}
|
|
17873
|
+
async planNatGatewayZoneAddresses(logicalId, physicalId, resourceType, rawDesired) {
|
|
17874
|
+
const desired = readNatZoneAddresses(rawDesired);
|
|
17875
|
+
if (desired.kind === "unusable") throw markNonRetryable(new ProvisioningError(`AvailabilityZoneAddresses of NatGateway ${logicalId} ${desired.reason}; each entry needs AvailabilityZone or AvailabilityZoneId and a non-empty AllocationIds list`, resourceType, logicalId, physicalId));
|
|
17876
|
+
if (desired.kind === "absent") throw markNonRetryable(new ProvisioningError(`NatGateway ${logicalId} cannot drop AvailabilityZoneAddresses: a regional NAT gateway created with explicit zones does not return to automatic zone expansion, and CloudFormation refuses the same update. Keep at least one zone declared, or rename the logical id or change a create-only property to replace the gateway`, resourceType, logicalId, physicalId));
|
|
17877
|
+
const gateway = (await this.ec2Client.send(new DescribeNatGatewaysCommand({ NatGatewayIds: [physicalId] }))).NatGateways?.find((g) => g.NatGatewayId === physicalId);
|
|
17878
|
+
if (gateway === void 0) throw new ProvisioningError(`NatGateway ${logicalId} (${physicalId}) was not returned by DescribeNatGateways, so its addresses cannot be updated`, resourceType, logicalId, physicalId);
|
|
17879
|
+
const plan = planNatZoneAddressUpdate(desired.entries, gateway.NatGatewayAddresses ?? []);
|
|
17880
|
+
for (const d of plan.disassociate) {
|
|
17881
|
+
const status = gateway.NatGatewayAddresses?.find((x) => x.AllocationId === d.allocationId)?.Status ?? "unknown";
|
|
17882
|
+
this.logger.debug(safeMsg`NatGateway ${physicalId} plans to release ${d.allocationId} (live status ${status})`);
|
|
17883
|
+
}
|
|
17884
|
+
for (const id of plan.awaitingRelease) this.logger.debug(safeMsg`NatGateway ${physicalId} plans to associate ${id}, which AWS is still releasing`);
|
|
17885
|
+
if (plan.moved.length > 0) throw markNonRetryable(new ProvisioningError(`NatGateway ${logicalId} declares ${plan.moved.join(", ")} in a different zone from the one that holds it; cdkd does not move an Elastic IP between zones in one update. Remove it from AvailabilityZoneAddresses in one deploy and add it to the new zone in the next`, resourceType, logicalId, physicalId));
|
|
17886
|
+
return plan;
|
|
17887
|
+
}
|
|
17888
|
+
async applyNatGatewayZoneAddresses(logicalId, physicalId, resourceType, plan) {
|
|
17889
|
+
const budget = { polls: NAT_ADDRESS_SETTLE_POLLS };
|
|
17890
|
+
if (plan.awaitingRelease.length > 0) {
|
|
17891
|
+
const ids = new Set(plan.awaitingRelease);
|
|
17892
|
+
await this.pollNatGateway(logicalId, physicalId, resourceType, budget, `the release of ${plan.awaitingRelease.join(", ")}`, "nothing was associated or released", (gateway) => (gateway.NatGatewayAddresses ?? []).some((a) => typeof a.AllocationId === "string" && ids.has(a.AllocationId) && a.Status === "disassociating") ? "wait" : "done");
|
|
17893
|
+
}
|
|
17894
|
+
for (const entry of plan.associate) await this.ec2Client.send(new AssociateNatGatewayAddressCommand({
|
|
17895
|
+
NatGatewayId: physicalId,
|
|
17896
|
+
AllocationIds: entry.allocationIds,
|
|
17897
|
+
AvailabilityZone: entry.availabilityZone,
|
|
17898
|
+
AvailabilityZoneId: entry.availabilityZoneId
|
|
17899
|
+
}));
|
|
17900
|
+
if (plan.disassociate.length === 0) return;
|
|
17901
|
+
let associationIds = plan.disassociate.map((d) => d.associationId).filter((id) => id !== void 0);
|
|
17902
|
+
const unassociated = plan.disassociate.filter((d) => d.associationId === void 0);
|
|
17903
|
+
if (unassociated.length > 0) {
|
|
17904
|
+
const targets = new Set(unassociated.map((d) => d.allocationId));
|
|
17905
|
+
const gateway = await this.pollNatGateway(logicalId, physicalId, resourceType, budget, `the association of ${unassociated.map((d) => d.allocationId).join(", ")} before releasing it`, "the release was not sent", (gw) => (gw.NatGatewayAddresses ?? []).some((a) => typeof a.AllocationId === "string" && targets.has(a.AllocationId) && natAddressHeld(a) && !(a.Status === "succeeded" && typeof a.AssociationId === "string")) ? "wait" : "done");
|
|
17906
|
+
for (const a of gateway.NatGatewayAddresses ?? []) if (typeof a.AllocationId === "string" && targets.has(a.AllocationId) && natAddressHeld(a) && typeof a.AssociationId === "string") associationIds.push(a.AssociationId);
|
|
17907
|
+
associationIds = [...new Set(associationIds)];
|
|
17908
|
+
}
|
|
17909
|
+
if (associationIds.length === 0) return;
|
|
17910
|
+
if (!plan.keptSettled) {
|
|
17911
|
+
const releasing = new Set(plan.disassociate.map((d) => d.allocationId));
|
|
17912
|
+
const added = plan.associate.flatMap((e) => e.allocationIds);
|
|
17913
|
+
let unlisted = 0;
|
|
17914
|
+
await this.pollNatGateway(logicalId, physicalId, resourceType, budget, "an address the template keeps to associate before releasing the last associated one", "the release was not sent", (gw) => {
|
|
17915
|
+
const kept = (gw.NatGatewayAddresses ?? []).filter((a) => typeof a.AllocationId === "string" && !releasing.has(a.AllocationId));
|
|
17916
|
+
if (kept.some((a) => a.Status === "succeeded")) return "done";
|
|
17917
|
+
if (kept.some((a) => a.Status === "associating")) return "wait";
|
|
17918
|
+
const missing = added.filter((id) => !kept.some((a) => a.AllocationId === id));
|
|
17919
|
+
if (missing.length > 0) {
|
|
17920
|
+
unlisted++;
|
|
17921
|
+
if (unlisted <= NAT_ADDRESS_UNLISTED_POLLS) return "wait";
|
|
17922
|
+
return markNonRetryable(new ProvisioningError(`NatGateway ${logicalId} does not list ${missing.join(", ")} after associating it, so its last associated address was not released. Check \`aws ec2 describe-nat-gateways --nat-gateway-ids ${physicalId}\` and re-run the deploy`, resourceType, logicalId, physicalId));
|
|
17923
|
+
}
|
|
17924
|
+
const failed = added.filter((id) => kept.find((a) => a.AllocationId === id)?.Status === "failed");
|
|
17925
|
+
return markNonRetryable(new ProvisioningError(failed.length > 0 ? `NatGateway ${logicalId} could not associate ${failed.join(", ")}, so its last associated address was not released. Read the failure with \`aws ec2 describe-nat-gateways --nat-gateway-ids ${physicalId}\` and fix the declared Elastic IP` : `NatGateway ${logicalId} has no other associated or associating address, so its last associated address was not released. Declare an Elastic IP the gateway can associate`, resourceType, logicalId, physicalId));
|
|
17926
|
+
});
|
|
17927
|
+
}
|
|
17928
|
+
await this.ec2Client.send(new DisassociateNatGatewayAddressCommand({
|
|
17929
|
+
NatGatewayId: physicalId,
|
|
17930
|
+
AssociationIds: associationIds
|
|
17931
|
+
}));
|
|
17932
|
+
}
|
|
17933
|
+
async pollNatGateway(logicalId, physicalId, resourceType, budget, what, unsent, decide) {
|
|
17934
|
+
this.logger.debug(safeMsg`Waiting for NatGateway ${physicalId}: ${what}...`);
|
|
17935
|
+
const watch = startInterruptWatch(`NatGateway ${logicalId} address wait`);
|
|
17936
|
+
try {
|
|
17937
|
+
while (budget.polls > 0) {
|
|
17938
|
+
budget.polls--;
|
|
17939
|
+
if (watch.isInterrupted()) throw watch.onInterrupted();
|
|
17940
|
+
const gateway = (await this.ec2Client.send(new DescribeNatGatewaysCommand({ NatGatewayIds: [physicalId] }))).NatGateways?.find((g) => g.NatGatewayId === physicalId);
|
|
17941
|
+
if (gateway === void 0 || gateway.State === "deleting" || gateway.State === "deleted" || gateway.State === "failed") throw markNonRetryable(new ProvisioningError(`NatGateway ${logicalId} (${physicalId}) is ${gateway?.State ?? "no longer returned by DescribeNatGateways"}, so cdkd stopped waiting for ${what}`, resourceType, logicalId, physicalId));
|
|
17942
|
+
const verdict = decide(gateway);
|
|
17943
|
+
if (verdict === "done") return gateway;
|
|
17944
|
+
if (verdict !== "wait") throw verdict;
|
|
17945
|
+
await this.sleep(NAT_ADDRESS_SETTLE_DELAY_MS);
|
|
17946
|
+
}
|
|
17947
|
+
} finally {
|
|
17948
|
+
watch.dispose();
|
|
17949
|
+
}
|
|
17950
|
+
throw markNonRetryable(new ProvisioningError(`NatGateway ${logicalId} ran out of its ${NAT_ADDRESS_SETTLE_POLLS * NAT_ADDRESS_SETTLE_DELAY_MS / 6e4}-minute address wait while waiting for ${what}; ${unsent}. Re-run the deploy once \`aws ec2 describe-nat-gateways --nat-gateway-ids ${physicalId}\` shows its addresses settled`, resourceType, logicalId, physicalId));
|
|
17609
17951
|
}
|
|
17610
17952
|
async deleteNatGateway(logicalId, physicalId, resourceType, context) {
|
|
17611
17953
|
this.logger.debug(`Deleting NatGateway ${logicalId}: ${physicalId}`);
|
|
@@ -19209,7 +19551,7 @@ var EC2Provider = class {
|
|
|
19209
19551
|
case "AWS::EC2::VPC": return await this.readVpcCurrentState(physicalId);
|
|
19210
19552
|
case "AWS::EC2::Subnet": return await this.readSubnetCurrentState(physicalId);
|
|
19211
19553
|
case "AWS::EC2::InternetGateway": return await this.readInternetGatewayCurrentState(physicalId);
|
|
19212
|
-
case "AWS::EC2::NatGateway": return await this.readNatGatewayCurrentState(physicalId);
|
|
19554
|
+
case "AWS::EC2::NatGateway": return await this.readNatGatewayCurrentState(physicalId, properties);
|
|
19213
19555
|
case "AWS::EC2::RouteTable": return await this.readRouteTableCurrentState(physicalId);
|
|
19214
19556
|
case "AWS::EC2::SecurityGroup": return await this.readSecurityGroupCurrentState(physicalId, properties);
|
|
19215
19557
|
case "AWS::EC2::Instance": return await this.readInstanceCurrentState(physicalId);
|
|
@@ -19293,15 +19635,22 @@ var EC2Provider = class {
|
|
|
19293
19635
|
if (!(await this.ec2Client.send(new DescribeInternetGatewaysCommand({ InternetGatewayIds: [physicalId] }))).InternetGateways?.[0]) return RESOURCE_NOT_FOUND;
|
|
19294
19636
|
return {};
|
|
19295
19637
|
}
|
|
19296
|
-
async readNatGatewayCurrentState(physicalId) {
|
|
19638
|
+
async readNatGatewayCurrentState(physicalId, properties) {
|
|
19297
19639
|
const gw = (await this.ec2Client.send(new DescribeNatGatewaysCommand({ NatGatewayIds: [physicalId] }))).NatGateways?.find((g) => g.State !== "deleted" && g.State !== "deleting");
|
|
19298
19640
|
if (!gw) return RESOURCE_NOT_FOUND;
|
|
19299
19641
|
const result = {};
|
|
19300
19642
|
if (gw.SubnetId !== void 0) result["SubnetId"] = gw.SubnetId;
|
|
19301
19643
|
if (gw.ConnectivityType !== void 0) result["ConnectivityType"] = gw.ConnectivityType;
|
|
19302
|
-
const
|
|
19303
|
-
|
|
19304
|
-
if (primary?.
|
|
19644
|
+
const regional = gw.AvailabilityMode === "regional";
|
|
19645
|
+
const primary = gw.NatGatewayAddresses?.find((a) => a.IsPrimary === true) ?? gw.NatGatewayAddresses?.[0];
|
|
19646
|
+
if (primary?.AllocationId !== void 0 && (!regional || properties?.["AllocationId"] != null)) result["AllocationId"] = primary.AllocationId;
|
|
19647
|
+
if (primary?.PrivateIp !== void 0 && (!regional || properties?.["PrivateIpAddress"] != null)) result["PrivateIpAddress"] = primary.PrivateIp;
|
|
19648
|
+
if (gw.AvailabilityMode !== void 0) result["AvailabilityMode"] = gw.AvailabilityMode;
|
|
19649
|
+
if (gw.VpcId !== void 0) result["VpcId"] = gw.VpcId;
|
|
19650
|
+
if (gw.AvailabilityMode === "regional" && gw.AutoProvisionZones === "disabled") {
|
|
19651
|
+
const recorded = readNatZoneAddresses(properties?.["AvailabilityZoneAddresses"]);
|
|
19652
|
+
result["AvailabilityZoneAddresses"] = readbackNatZoneAddresses(gw.NatGatewayAddresses ?? [], recorded.kind === "usable" ? recorded.entries : []);
|
|
19653
|
+
}
|
|
19305
19654
|
return result;
|
|
19306
19655
|
}
|
|
19307
19656
|
async readEipCurrentState(physicalId, properties, afterOwnWrite) {
|
|
@@ -19693,10 +20042,13 @@ var EC2Provider = class {
|
|
|
19693
20042
|
attributes: { Id: rule.SecurityGroupRuleId }
|
|
19694
20043
|
};
|
|
19695
20044
|
}
|
|
19696
|
-
case "AWS::EC2::NatGateway":
|
|
19697
|
-
physicalId
|
|
19698
|
-
|
|
19699
|
-
|
|
20045
|
+
case "AWS::EC2::NatGateway": {
|
|
20046
|
+
const gw = (await this.ec2Client.send(new DescribeNatGatewaysCommand({ NatGatewayIds: [physicalId] }))).NatGateways?.find((g) => g.State !== "deleted" && g.State !== "deleting");
|
|
20047
|
+
return gw ? {
|
|
20048
|
+
physicalId,
|
|
20049
|
+
attributes: natGatewayAttributes(gw)
|
|
20050
|
+
} : null;
|
|
20051
|
+
}
|
|
19700
20052
|
case "AWS::EC2::EIP": {
|
|
19701
20053
|
const { allocationId, publicIp } = this.parseEipPhysicalId(physicalId);
|
|
19702
20054
|
const filter = allocationId ? { AllocationIds: [allocationId] } : { PublicIps: publicIp ? [publicIp] : [] };
|
|
@@ -20182,10 +20534,11 @@ var ApiGatewayProvider = class ApiGatewayProvider {
|
|
|
20182
20534
|
}
|
|
20183
20535
|
createClient;
|
|
20184
20536
|
getCreateClient() {
|
|
20185
|
-
this.createClient ??= this.apiGatewayClient.config.region().then((region) => withoutServerErrorRetries(new APIGatewayClient({
|
|
20537
|
+
this.createClient ??= this.apiGatewayClient.config.region().then((region) => withoutServerErrorRetries(withApiGatewayPacing(new APIGatewayClient({
|
|
20186
20538
|
...ambientClientDefaults(),
|
|
20187
|
-
region
|
|
20188
|
-
|
|
20539
|
+
region,
|
|
20540
|
+
maxAttempts: 8
|
|
20541
|
+
}))), (error) => {
|
|
20189
20542
|
this.createClient = void 0;
|
|
20190
20543
|
throw error;
|
|
20191
20544
|
});
|
|
@@ -20948,7 +21301,7 @@ var ApiGatewayProvider = class ApiGatewayProvider {
|
|
|
20948
21301
|
const methodPath = maskedIds.join("/");
|
|
20949
21302
|
let methodLeftBehind = false;
|
|
20950
21303
|
try {
|
|
20951
|
-
|
|
21304
|
+
const putMethod = () => this.apiGatewayClient.send(new PutMethodCommand({
|
|
20952
21305
|
restApiId,
|
|
20953
21306
|
resourceId,
|
|
20954
21307
|
httpMethod,
|
|
@@ -20961,6 +21314,22 @@ var ApiGatewayProvider = class ApiGatewayProvider {
|
|
|
20961
21314
|
requestValidatorId,
|
|
20962
21315
|
authorizationScopes
|
|
20963
21316
|
}));
|
|
21317
|
+
try {
|
|
21318
|
+
await putMethod();
|
|
21319
|
+
} catch (putError) {
|
|
21320
|
+
if (!isMethodAlreadyExists(putError) || !await this.priorAttemptLeftMethod(logicalId, physicalId, log)) throw putError;
|
|
21321
|
+
log.warn(`Replacing API Gateway Method ${logicalId} (${methodPath}), which an earlier failed attempt of it left behind`);
|
|
21322
|
+
try {
|
|
21323
|
+
await this.apiGatewayClient.send(new DeleteMethodCommand({
|
|
21324
|
+
restApiId,
|
|
21325
|
+
resourceId,
|
|
21326
|
+
httpMethod
|
|
21327
|
+
}));
|
|
21328
|
+
} catch (deleteError) {
|
|
21329
|
+
if (!(deleteError instanceof NotFoundException$1)) throw deleteError;
|
|
21330
|
+
}
|
|
21331
|
+
await putMethod();
|
|
21332
|
+
}
|
|
20964
21333
|
try {
|
|
20965
21334
|
const integration = properties["Integration"];
|
|
20966
21335
|
if (integration) await this.apiGatewayClient.send(new PutIntegrationCommand(putIntegrationInput({
|
|
@@ -20992,6 +21361,7 @@ var ApiGatewayProvider = class ApiGatewayProvider {
|
|
|
20992
21361
|
log.debug(`Cleaned up partially-created API Gateway Method ${logicalId} (${methodPath}) after wiring failure`);
|
|
20993
21362
|
} catch (cleanupError) {
|
|
20994
21363
|
methodLeftBehind = true;
|
|
21364
|
+
getPriorAttempts(logicalId)?.notePossiblyLanded();
|
|
20995
21365
|
const cleanupFailure = describeAwsFailure(cleanupError);
|
|
20996
21366
|
const cleanupHead = `Failed to clean up partially-created API Gateway Method ${logicalId} (${methodPath}): `;
|
|
20997
21367
|
if (cleanupFailure.redacted) log.debug(`${cleanupHead}${cleanupFailure.detail}`);
|
|
@@ -21011,6 +21381,18 @@ var ApiGatewayProvider = class ApiGatewayProvider {
|
|
|
21011
21381
|
throw thrown;
|
|
21012
21382
|
}
|
|
21013
21383
|
}
|
|
21384
|
+
async priorAttemptLeftMethod(logicalId, physicalId, log) {
|
|
21385
|
+
const lookup = getPriorAttempts(logicalId);
|
|
21386
|
+
if (lookup === void 0) return false;
|
|
21387
|
+
if (lookup.possiblyLanded()) return true;
|
|
21388
|
+
if (lookup.provenOrphanIds === void 0) return false;
|
|
21389
|
+
try {
|
|
21390
|
+
return (await lookup.provenOrphanIds()).includes(physicalId);
|
|
21391
|
+
} catch (error) {
|
|
21392
|
+
log.debug(`API Gateway Method ${logicalId}: rollback journal read failed: ${describeAwsFailure(error).detail}`);
|
|
21393
|
+
return false;
|
|
21394
|
+
}
|
|
21395
|
+
}
|
|
21014
21396
|
async updateMethod(logicalId, physicalId, resourceType, properties, previousProperties, log) {
|
|
21015
21397
|
const parts = physicalId.split("|");
|
|
21016
21398
|
const maskedId = parts.map((p) => log.value(p)).join("|");
|
|
@@ -21321,6 +21703,9 @@ var ApiGatewayProvider = class ApiGatewayProvider {
|
|
|
21321
21703
|
return null;
|
|
21322
21704
|
}
|
|
21323
21705
|
};
|
|
21706
|
+
function isMethodAlreadyExists(error) {
|
|
21707
|
+
return error instanceof Error && error.name === "ConflictException" && /already exists/i.test(error.message);
|
|
21708
|
+
}
|
|
21324
21709
|
function isPlainObjectBlock(value) {
|
|
21325
21710
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21326
21711
|
}
|
|
@@ -24613,6 +24998,70 @@ var StepFunctionsProvider = class {
|
|
|
24613
24998
|
throw error instanceof Error && error.name.includes("NotFound") ? markNotGone(thrown) : thrown;
|
|
24614
24999
|
}
|
|
24615
25000
|
}
|
|
25001
|
+
canonicalizeDriftProperties(_resourceType, properties) {
|
|
25002
|
+
if (properties["DefinitionString"] === void 0 && properties["DefinitionSubstitutions"] === void 0) return properties;
|
|
25003
|
+
const substitutions = properties["DefinitionSubstitutions"];
|
|
25004
|
+
const maskedNames = substitutions !== null && typeof substitutions === "object" && !Array.isArray(substitutions) ? Object.keys(substitutions).filter((name) => substitutions[name] === "***") : [];
|
|
25005
|
+
const body = inlineDefinitionBody(properties, maskedNames.length === 0 ? void 0 : {
|
|
25006
|
+
...substitutions,
|
|
25007
|
+
...Object.fromEntries(maskedNames.map((name) => [name, MASKED_SUBSTITUTION_SENTINEL]))
|
|
25008
|
+
});
|
|
25009
|
+
if (body === void 0) return properties;
|
|
25010
|
+
let definition;
|
|
25011
|
+
try {
|
|
25012
|
+
definition = JSON.parse(body);
|
|
25013
|
+
} catch {
|
|
25014
|
+
definition = body;
|
|
25015
|
+
}
|
|
25016
|
+
if (maskedNames.length > 0) definition = maskSentinelLeaves(definition);
|
|
25017
|
+
const folded = {
|
|
25018
|
+
...properties,
|
|
25019
|
+
Definition: definition
|
|
25020
|
+
};
|
|
25021
|
+
delete folded["DefinitionString"];
|
|
25022
|
+
delete folded["DefinitionSubstitutions"];
|
|
25023
|
+
return folded;
|
|
25024
|
+
}
|
|
25025
|
+
async canonicalizeDriftPair(resourceType, baseline, aws) {
|
|
25026
|
+
return {
|
|
25027
|
+
baseline: this.canonicalizeDriftProperties(resourceType, baseline),
|
|
25028
|
+
aws
|
|
25029
|
+
};
|
|
25030
|
+
}
|
|
25031
|
+
getDriftSecretPathAliases(_resourceType, properties, secretPaths) {
|
|
25032
|
+
const substitutions = properties["DefinitionSubstitutions"];
|
|
25033
|
+
if (substitutions === null || typeof substitutions !== "object" || Array.isArray(substitutions)) return [];
|
|
25034
|
+
const secretNames = Object.keys(substitutions).filter((name) => secretPaths.has("DefinitionSubstitutions") || [...secretPaths].some((p) => p === `DefinitionSubstitutions.${name}` || p.startsWith(`DefinitionSubstitutions.${name}.`)));
|
|
25035
|
+
if (secretNames.length === 0) return [];
|
|
25036
|
+
const definitionString = properties["DefinitionString"];
|
|
25037
|
+
const raw = definitionString !== void 0 ? definitionString : properties["Definition"];
|
|
25038
|
+
let body = raw;
|
|
25039
|
+
if (typeof raw === "string") try {
|
|
25040
|
+
body = JSON.parse(raw);
|
|
25041
|
+
} catch {
|
|
25042
|
+
return ["Definition"];
|
|
25043
|
+
}
|
|
25044
|
+
if (body === void 0 || body === null || typeof body !== "object") return ["Definition"];
|
|
25045
|
+
const tokens = secretNames.map((name) => `\${${name}}`);
|
|
25046
|
+
const carries = (text) => tokens.some((t) => text.includes(t));
|
|
25047
|
+
const aliases = [];
|
|
25048
|
+
const walk = (value, path, arrayPath) => {
|
|
25049
|
+
if (typeof value === "string") {
|
|
25050
|
+
if (carries(value)) aliases.push(arrayPath ?? path);
|
|
25051
|
+
return;
|
|
25052
|
+
}
|
|
25053
|
+
if (Array.isArray(value)) {
|
|
25054
|
+
value.forEach((item, i) => walk(item, `${path}.${i}`, arrayPath ?? path));
|
|
25055
|
+
return;
|
|
25056
|
+
}
|
|
25057
|
+
if (value !== null && typeof value === "object") for (const [key, child] of Object.entries(value)) {
|
|
25058
|
+
if (carries(key)) aliases.push(arrayPath ?? path);
|
|
25059
|
+
walk(child, `${path}.${key}`, arrayPath);
|
|
25060
|
+
}
|
|
25061
|
+
};
|
|
25062
|
+
walk(body, "Definition", void 0);
|
|
25063
|
+
return [...new Set(aliases)];
|
|
25064
|
+
}
|
|
24616
25065
|
async readCurrentState(physicalId, _logicalId, _resourceType) {
|
|
24617
25066
|
let resp;
|
|
24618
25067
|
try {
|
|
@@ -24708,21 +25157,11 @@ var StepFunctionsProvider = class {
|
|
|
24708
25157
|
}
|
|
24709
25158
|
}
|
|
24710
25159
|
async buildDefinitionString(properties) {
|
|
24711
|
-
const
|
|
24712
|
-
|
|
24713
|
-
|
|
24714
|
-
if (typeof definitionString === "string") return definitionString;
|
|
24715
|
-
return JSON.stringify(definitionString);
|
|
24716
|
-
}
|
|
24717
|
-
if (definition !== void 0) {
|
|
24718
|
-
if (typeof definition === "string") return definition;
|
|
24719
|
-
return JSON.stringify(definition);
|
|
24720
|
-
}
|
|
25160
|
+
const inline = inlineDefinitionBody(properties);
|
|
25161
|
+
if (inline !== void 0) return inline;
|
|
25162
|
+
const substitutions = properties["DefinitionSubstitutions"];
|
|
24721
25163
|
const s3Location = properties["DefinitionS3Location"];
|
|
24722
|
-
if (s3Location?.Bucket && s3Location.Key)
|
|
24723
|
-
const body = await this.fetchDefinitionFromS3(s3Location.Bucket, s3Location.Key, s3Location.Version);
|
|
24724
|
-
return this.applyDefinitionSubstitutions(body, properties["DefinitionSubstitutions"]);
|
|
24725
|
-
}
|
|
25164
|
+
if (s3Location?.Bucket && s3Location.Key) return applyDefinitionSubstitutions(await this.fetchDefinitionFromS3(s3Location.Bucket, s3Location.Key, s3Location.Version), substitutions);
|
|
24726
25165
|
return "{}";
|
|
24727
25166
|
}
|
|
24728
25167
|
async fetchDefinitionFromS3(bucket, key, version) {
|
|
@@ -24737,16 +25176,36 @@ var StepFunctionsProvider = class {
|
|
|
24737
25176
|
if (body.length === 0) throw new Error(`DefinitionS3Location object s3://${bucket}/${key} returned an empty body`);
|
|
24738
25177
|
return body;
|
|
24739
25178
|
}
|
|
24740
|
-
applyDefinitionSubstitutions(body, substitutions) {
|
|
24741
|
-
if (substitutions === null || typeof substitutions !== "object" || Array.isArray(substitutions)) return body;
|
|
24742
|
-
let result = body;
|
|
24743
|
-
for (const [name, value] of Object.entries(substitutions)) {
|
|
24744
|
-
if (typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean") continue;
|
|
24745
|
-
result = result.split(`\${${name}}`).join(String(value));
|
|
24746
|
-
}
|
|
24747
|
-
return result;
|
|
24748
|
-
}
|
|
24749
25179
|
};
|
|
25180
|
+
function applyDefinitionSubstitutions(body, substitutions) {
|
|
25181
|
+
if (substitutions === null || typeof substitutions !== "object" || Array.isArray(substitutions)) return body;
|
|
25182
|
+
const map = substitutions;
|
|
25183
|
+
return body.replace(/\$\{([^{}]+)\}/g, (token, name) => {
|
|
25184
|
+
if (!Object.hasOwn(map, name)) return token;
|
|
25185
|
+
const value = map[name];
|
|
25186
|
+
if (typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean") return token;
|
|
25187
|
+
return String(value);
|
|
25188
|
+
});
|
|
25189
|
+
}
|
|
25190
|
+
function inlineDefinitionBody(properties, substitutionsOverride) {
|
|
25191
|
+
const substitutions = substitutionsOverride ?? properties["DefinitionSubstitutions"];
|
|
25192
|
+
const definitionString = properties["DefinitionString"];
|
|
25193
|
+
const definition = properties["Definition"];
|
|
25194
|
+
const value = definitionString !== void 0 ? definitionString : definition;
|
|
25195
|
+
if (value === void 0) return void 0;
|
|
25196
|
+
return applyDefinitionSubstitutions(typeof value === "string" ? value : JSON.stringify(value), substitutions);
|
|
25197
|
+
}
|
|
25198
|
+
const MASKED_SUBSTITUTION_SENTINEL = "cdkd-masked-substitution";
|
|
25199
|
+
function maskSentinelLeaves(value) {
|
|
25200
|
+
if (typeof value === "string") return value.includes(MASKED_SUBSTITUTION_SENTINEL) ? "***" : value;
|
|
25201
|
+
if (Array.isArray(value)) return value.map((item) => maskSentinelLeaves(item));
|
|
25202
|
+
if (value !== null && typeof value === "object") {
|
|
25203
|
+
const entries = Object.entries(value);
|
|
25204
|
+
if (entries.some(([key]) => key.includes(MASKED_SUBSTITUTION_SENTINEL))) return "***";
|
|
25205
|
+
return Object.fromEntries(entries.map(([key, child]) => [key, maskSentinelLeaves(child)]));
|
|
25206
|
+
}
|
|
25207
|
+
return value;
|
|
25208
|
+
}
|
|
24750
25209
|
function mapEncryptionConfiguration(value) {
|
|
24751
25210
|
if (value === null || value === void 0) return void 0;
|
|
24752
25211
|
if (typeof value !== "object") return void 0;
|
|
@@ -30819,14 +31278,9 @@ function sanitizeDescription(value) {
|
|
|
30819
31278
|
if (typeof value === "string" && value.length === 0) return void 0;
|
|
30820
31279
|
return value;
|
|
30821
31280
|
}
|
|
30822
|
-
function isPlainObject(value) {
|
|
31281
|
+
function isPlainObject$1(value) {
|
|
30823
31282
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
30824
31283
|
}
|
|
30825
|
-
const SDK_UNSUPPORTED_RULE_KEYS = [
|
|
30826
|
-
"PreParseTextTransformations",
|
|
30827
|
-
"Monetize",
|
|
30828
|
-
"PriceMultiplier"
|
|
30829
|
-
];
|
|
30830
31284
|
function toSdkByteMatchStatement(byteMatchStatement) {
|
|
30831
31285
|
const encoded = byteMatchStatement["SearchStringBase64"];
|
|
30832
31286
|
if (typeof encoded !== "string") return byteMatchStatement;
|
|
@@ -30843,10 +31297,10 @@ const ARN_REFERENCE_STATEMENT_KEYS = [
|
|
|
30843
31297
|
function toSdkStatement(statement) {
|
|
30844
31298
|
const converted = { ...statement };
|
|
30845
31299
|
const byteMatchStatement = converted["ByteMatchStatement"];
|
|
30846
|
-
if (isPlainObject(byteMatchStatement)) converted["ByteMatchStatement"] = toSdkByteMatchStatement(byteMatchStatement);
|
|
31300
|
+
if (isPlainObject$1(byteMatchStatement)) converted["ByteMatchStatement"] = toSdkByteMatchStatement(byteMatchStatement);
|
|
30847
31301
|
for (const key of ARN_REFERENCE_STATEMENT_KEYS) {
|
|
30848
31302
|
const reference = converted[key];
|
|
30849
|
-
if (!isPlainObject(reference) || !("Arn" in reference)) continue;
|
|
31303
|
+
if (!isPlainObject$1(reference) || !("Arn" in reference)) continue;
|
|
30850
31304
|
const { Arn: arn, ...rest } = reference;
|
|
30851
31305
|
converted[key] = {
|
|
30852
31306
|
...rest,
|
|
@@ -30854,28 +31308,28 @@ function toSdkStatement(statement) {
|
|
|
30854
31308
|
};
|
|
30855
31309
|
}
|
|
30856
31310
|
const notStatement = converted["NotStatement"];
|
|
30857
|
-
if (isPlainObject(notStatement)) {
|
|
31311
|
+
if (isPlainObject$1(notStatement)) {
|
|
30858
31312
|
const nested = notStatement["Statement"];
|
|
30859
|
-
if (isPlainObject(nested)) converted["NotStatement"] = {
|
|
31313
|
+
if (isPlainObject$1(nested)) converted["NotStatement"] = {
|
|
30860
31314
|
...notStatement,
|
|
30861
31315
|
Statement: toSdkStatement(nested)
|
|
30862
31316
|
};
|
|
30863
31317
|
}
|
|
30864
31318
|
for (const key of ["AndStatement", "OrStatement"]) {
|
|
30865
31319
|
const combined = converted[key];
|
|
30866
|
-
if (!isPlainObject(combined)) continue;
|
|
31320
|
+
if (!isPlainObject$1(combined)) continue;
|
|
30867
31321
|
const nested = combined["Statements"];
|
|
30868
31322
|
if (!Array.isArray(nested)) continue;
|
|
30869
31323
|
converted[key] = {
|
|
30870
31324
|
...combined,
|
|
30871
|
-
Statements: nested.map((item) => isPlainObject(item) ? toSdkStatement(item) : item)
|
|
31325
|
+
Statements: nested.map((item) => isPlainObject$1(item) ? toSdkStatement(item) : item)
|
|
30872
31326
|
};
|
|
30873
31327
|
}
|
|
30874
31328
|
for (const key of ["RateBasedStatement", "ManagedRuleGroupStatement"]) {
|
|
30875
31329
|
const scoping = converted[key];
|
|
30876
|
-
if (!isPlainObject(scoping)) continue;
|
|
31330
|
+
if (!isPlainObject$1(scoping)) continue;
|
|
30877
31331
|
const nested = scoping["ScopeDownStatement"];
|
|
30878
|
-
if (!isPlainObject(nested)) continue;
|
|
31332
|
+
if (!isPlainObject$1(nested)) continue;
|
|
30879
31333
|
converted[key] = {
|
|
30880
31334
|
...scoping,
|
|
30881
31335
|
ScopeDownStatement: toSdkStatement(nested)
|
|
@@ -30887,9 +31341,9 @@ function toSdkRules(rules) {
|
|
|
30887
31341
|
if (!rules) return [];
|
|
30888
31342
|
if (!Array.isArray(rules)) return rules;
|
|
30889
31343
|
return rules.map((rule) => {
|
|
30890
|
-
if (!isPlainObject(rule)) return rule;
|
|
31344
|
+
if (!isPlainObject$1(rule)) return rule;
|
|
30891
31345
|
const statement = rule["Statement"];
|
|
30892
|
-
if (!isPlainObject(statement)) return rule;
|
|
31346
|
+
if (!isPlainObject$1(statement)) return rule;
|
|
30893
31347
|
return {
|
|
30894
31348
|
...rule,
|
|
30895
31349
|
Statement: toSdkStatement(statement)
|
|
@@ -30901,7 +31355,7 @@ function toCfnByteMatchStatement(byteMatchStatement, baseline) {
|
|
|
30901
31355
|
if (raw === void 0) return byteMatchStatement;
|
|
30902
31356
|
const bytes = raw instanceof Uint8Array ? Buffer.from(raw) : typeof raw === "string" ? Buffer.from(raw, "utf8") : void 0;
|
|
30903
31357
|
if (!bytes) return byteMatchStatement;
|
|
30904
|
-
const base = isPlainObject(baseline) ? baseline : void 0;
|
|
31358
|
+
const base = isPlainObject$1(baseline) ? baseline : void 0;
|
|
30905
31359
|
const baseEncoded = base?.["SearchStringBase64"];
|
|
30906
31360
|
const basePlain = base?.["SearchString"];
|
|
30907
31361
|
const converted = { ...byteMatchStatement };
|
|
@@ -30926,12 +31380,12 @@ function toCfnByteMatchStatement(byteMatchStatement, baseline) {
|
|
|
30926
31380
|
}
|
|
30927
31381
|
function toCfnStatement(statement, baseline) {
|
|
30928
31382
|
const converted = { ...statement };
|
|
30929
|
-
const base = isPlainObject(baseline) ? baseline : void 0;
|
|
31383
|
+
const base = isPlainObject$1(baseline) ? baseline : void 0;
|
|
30930
31384
|
const byteMatchStatement = converted["ByteMatchStatement"];
|
|
30931
|
-
if (isPlainObject(byteMatchStatement)) converted["ByteMatchStatement"] = toCfnByteMatchStatement(byteMatchStatement, base?.["ByteMatchStatement"]);
|
|
31385
|
+
if (isPlainObject$1(byteMatchStatement)) converted["ByteMatchStatement"] = toCfnByteMatchStatement(byteMatchStatement, base?.["ByteMatchStatement"]);
|
|
30932
31386
|
for (const key of ARN_REFERENCE_STATEMENT_KEYS) {
|
|
30933
31387
|
const reference = converted[key];
|
|
30934
|
-
if (!isPlainObject(reference) || !("ARN" in reference)) continue;
|
|
31388
|
+
if (!isPlainObject$1(reference) || !("ARN" in reference)) continue;
|
|
30935
31389
|
const { ARN: arn, ...rest } = reference;
|
|
30936
31390
|
converted[key] = {
|
|
30937
31391
|
...rest,
|
|
@@ -30939,37 +31393,37 @@ function toCfnStatement(statement, baseline) {
|
|
|
30939
31393
|
};
|
|
30940
31394
|
}
|
|
30941
31395
|
const notStatement = converted["NotStatement"];
|
|
30942
|
-
if (isPlainObject(notStatement)) {
|
|
31396
|
+
if (isPlainObject$1(notStatement)) {
|
|
30943
31397
|
const nested = notStatement["Statement"];
|
|
30944
|
-
if (isPlainObject(nested)) {
|
|
31398
|
+
if (isPlainObject$1(nested)) {
|
|
30945
31399
|
const baseNot = base?.["NotStatement"];
|
|
30946
31400
|
converted["NotStatement"] = {
|
|
30947
31401
|
...notStatement,
|
|
30948
|
-
Statement: toCfnStatement(nested, isPlainObject(baseNot) ? baseNot["Statement"] : void 0)
|
|
31402
|
+
Statement: toCfnStatement(nested, isPlainObject$1(baseNot) ? baseNot["Statement"] : void 0)
|
|
30949
31403
|
};
|
|
30950
31404
|
}
|
|
30951
31405
|
}
|
|
30952
31406
|
for (const key of ["AndStatement", "OrStatement"]) {
|
|
30953
31407
|
const combined = converted[key];
|
|
30954
|
-
if (!isPlainObject(combined)) continue;
|
|
31408
|
+
if (!isPlainObject$1(combined)) continue;
|
|
30955
31409
|
const nested = combined["Statements"];
|
|
30956
31410
|
if (!Array.isArray(nested)) continue;
|
|
30957
31411
|
const baseCombined = base?.[key];
|
|
30958
|
-
const baseList = isPlainObject(baseCombined) && Array.isArray(baseCombined["Statements"]) ? baseCombined["Statements"] : void 0;
|
|
31412
|
+
const baseList = isPlainObject$1(baseCombined) && Array.isArray(baseCombined["Statements"]) ? baseCombined["Statements"] : void 0;
|
|
30959
31413
|
converted[key] = {
|
|
30960
31414
|
...combined,
|
|
30961
|
-
Statements: nested.map((item, i) => isPlainObject(item) ? toCfnStatement(item, baseList?.[i]) : item)
|
|
31415
|
+
Statements: nested.map((item, i) => isPlainObject$1(item) ? toCfnStatement(item, baseList?.[i]) : item)
|
|
30962
31416
|
};
|
|
30963
31417
|
}
|
|
30964
31418
|
for (const key of ["RateBasedStatement", "ManagedRuleGroupStatement"]) {
|
|
30965
31419
|
const scoping = converted[key];
|
|
30966
|
-
if (!isPlainObject(scoping)) continue;
|
|
31420
|
+
if (!isPlainObject$1(scoping)) continue;
|
|
30967
31421
|
const nested = scoping["ScopeDownStatement"];
|
|
30968
|
-
if (!isPlainObject(nested)) continue;
|
|
31422
|
+
if (!isPlainObject$1(nested)) continue;
|
|
30969
31423
|
const baseScoping = base?.[key];
|
|
30970
31424
|
converted[key] = {
|
|
30971
31425
|
...scoping,
|
|
30972
|
-
ScopeDownStatement: toCfnStatement(nested, isPlainObject(baseScoping) ? baseScoping["ScopeDownStatement"] : void 0)
|
|
31426
|
+
ScopeDownStatement: toCfnStatement(nested, isPlainObject$1(baseScoping) ? baseScoping["ScopeDownStatement"] : void 0)
|
|
30973
31427
|
};
|
|
30974
31428
|
}
|
|
30975
31429
|
return converted;
|
|
@@ -30978,27 +31432,16 @@ function toCfnRules(rules, baselineRules) {
|
|
|
30978
31432
|
if (!Array.isArray(rules)) return [];
|
|
30979
31433
|
const baseList = Array.isArray(baselineRules) ? baselineRules : void 0;
|
|
30980
31434
|
return rules.map((rule, i) => {
|
|
30981
|
-
if (!isPlainObject(rule)) return rule;
|
|
31435
|
+
if (!isPlainObject$1(rule)) return rule;
|
|
30982
31436
|
const statement = rule["Statement"];
|
|
30983
|
-
if (!isPlainObject(statement)) return rule;
|
|
31437
|
+
if (!isPlainObject$1(statement)) return rule;
|
|
30984
31438
|
const baseRule = baseList?.[i];
|
|
30985
31439
|
return {
|
|
30986
31440
|
...rule,
|
|
30987
|
-
Statement: toCfnStatement(statement, isPlainObject(baseRule) ? baseRule["Statement"] : void 0)
|
|
31441
|
+
Statement: toCfnStatement(statement, isPlainObject$1(baseRule) ? baseRule["Statement"] : void 0)
|
|
30988
31442
|
};
|
|
30989
31443
|
});
|
|
30990
31444
|
}
|
|
30991
|
-
function collectSdkUnsupportedRuleKeys(value, found) {
|
|
30992
|
-
if (Array.isArray(value)) {
|
|
30993
|
-
for (const item of value) collectSdkUnsupportedRuleKeys(item, found);
|
|
30994
|
-
return;
|
|
30995
|
-
}
|
|
30996
|
-
if (!isPlainObject(value)) return;
|
|
30997
|
-
for (const [key, nested] of Object.entries(value)) {
|
|
30998
|
-
if (SDK_UNSUPPORTED_RULE_KEYS.includes(key)) found.add(key);
|
|
30999
|
-
collectSdkUnsupportedRuleKeys(nested, found);
|
|
31000
|
-
}
|
|
31001
|
-
}
|
|
31002
31445
|
var WAFv2WebACLProvider = class {
|
|
31003
31446
|
wafv2Client;
|
|
31004
31447
|
createClient;
|
|
@@ -31040,7 +31483,6 @@ var WAFv2WebACLProvider = class {
|
|
|
31040
31483
|
const desiredTags = refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId);
|
|
31041
31484
|
const name = properties["Name"] || generatedNameFor("AWS::WAFv2::WebACL", logicalId);
|
|
31042
31485
|
const scope = requireConfigString(properties["Scope"], "REGIONAL", "AWS::WAFv2::WebACL Scope", replayWarn(this.logger, context));
|
|
31043
|
-
this.warnOnSdkUnsupportedRuleKeys(logicalId, properties["Rules"]);
|
|
31044
31486
|
try {
|
|
31045
31487
|
const tags = desiredTags.map((tag) => ({
|
|
31046
31488
|
Key: tag.Key,
|
|
@@ -31090,7 +31532,6 @@ var WAFv2WebACLProvider = class {
|
|
|
31090
31532
|
this.logger.debug(`Updating WAFv2 WebACL ${logicalId}: ${physicalId}`);
|
|
31091
31533
|
assertRegionMatch(context?.expectedRegion ? await this.getClient().config.region() : void 0, context?.expectedRegion, resourceType, logicalId, physicalId, "pre-update");
|
|
31092
31534
|
refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId);
|
|
31093
|
-
this.warnOnSdkUnsupportedRuleKeys(logicalId, properties["Rules"]);
|
|
31094
31535
|
try {
|
|
31095
31536
|
const { id, name, scope } = parseWebACLArn(physicalId);
|
|
31096
31537
|
const getResponse = await this.getClient().send(new GetWebACLCommand({
|
|
@@ -31169,16 +31610,6 @@ var WAFv2WebACLProvider = class {
|
|
|
31169
31610
|
throw error instanceof Error && error.name.includes("NotFound") ? markNotGone(thrown) : thrown;
|
|
31170
31611
|
}
|
|
31171
31612
|
}
|
|
31172
|
-
warnOnSdkUnsupportedRuleKeys(logicalId, rules) {
|
|
31173
|
-
const found = /* @__PURE__ */ new Set();
|
|
31174
|
-
collectSdkUnsupportedRuleKeys(rules, found);
|
|
31175
|
-
if (found.size === 0) return;
|
|
31176
|
-
const sorted = [...found].sort();
|
|
31177
|
-
const names = sorted.join(", ");
|
|
31178
|
-
const subject = sorted.length === 1 ? "property" : "properties";
|
|
31179
|
-
const verb = sorted.length === 1 ? "has" : "have";
|
|
31180
|
-
this.logger.warn(`WAFv2 WebACL ${logicalId}: rule ${subject} ${names} ${verb} no member in the installed AWS SDK WAFv2 model and will NOT be sent to AWS. Upgrade cdkd once its @aws-sdk/client-wafv2 dependency carries the ${subject}.`);
|
|
31181
|
-
}
|
|
31182
31613
|
async applyTagDiff(arn, resourceType, logicalId, oldTagsRaw, newTagsRaw) {
|
|
31183
31614
|
const plan = planTagDiff(oldTagsRaw, newTagsRaw);
|
|
31184
31615
|
const tagWarning = tagPlanWarning(plan, resourceType, logicalId);
|
|
@@ -31355,6 +31786,44 @@ const STANDARD_USER_POOL_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
|
31355
31786
|
"website",
|
|
31356
31787
|
"zoneinfo"
|
|
31357
31788
|
]);
|
|
31789
|
+
function createTimeOnlyChanges(properties, previousProperties) {
|
|
31790
|
+
return [
|
|
31791
|
+
[
|
|
31792
|
+
"UsernameAttributes",
|
|
31793
|
+
properties["UsernameAttributes"],
|
|
31794
|
+
previousProperties["UsernameAttributes"],
|
|
31795
|
+
"list"
|
|
31796
|
+
],
|
|
31797
|
+
[
|
|
31798
|
+
"AliasAttributes",
|
|
31799
|
+
properties["AliasAttributes"],
|
|
31800
|
+
previousProperties["AliasAttributes"],
|
|
31801
|
+
"list"
|
|
31802
|
+
],
|
|
31803
|
+
[
|
|
31804
|
+
"UsernameConfiguration",
|
|
31805
|
+
properties["UsernameConfiguration"],
|
|
31806
|
+
previousProperties["UsernameConfiguration"],
|
|
31807
|
+
"object"
|
|
31808
|
+
]
|
|
31809
|
+
].filter(([, desired, previous, shape]) => canonicalCreateTimeOnlyValue(shape, desired) !== canonicalCreateTimeOnlyValue(shape, previous)).map(([name]) => name);
|
|
31810
|
+
}
|
|
31811
|
+
function withPreviousCreateTimeOnly(bag, previousProperties, kept) {
|
|
31812
|
+
if (kept.length === 0) return bag;
|
|
31813
|
+
const out = { ...bag };
|
|
31814
|
+
for (const key of kept) if (previousProperties[key] === void 0) delete out[key];
|
|
31815
|
+
else out[key] = previousProperties[key];
|
|
31816
|
+
return out;
|
|
31817
|
+
}
|
|
31818
|
+
function canonicalCreateTimeOnlyValue(shape, declared) {
|
|
31819
|
+
const value = declared ?? (shape === "object" ? {} : []);
|
|
31820
|
+
if (Array.isArray(value)) return JSON.stringify(value.map((v) => JSON.stringify(v)).sort());
|
|
31821
|
+
if (typeof value === "object") {
|
|
31822
|
+
const entries = Object.entries(value).filter(([, v]) => v !== void 0).map(([k, v]) => [k, typeof v === "boolean" ? String(v) : v]).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
|
|
31823
|
+
return JSON.stringify(entries);
|
|
31824
|
+
}
|
|
31825
|
+
return JSON.stringify(value);
|
|
31826
|
+
}
|
|
31358
31827
|
function isEmptyObjectPlaceholder(value) {
|
|
31359
31828
|
return value !== null && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === 0;
|
|
31360
31829
|
}
|
|
@@ -31837,6 +32306,13 @@ var CognitoUserPoolProvider = class {
|
|
|
31837
32306
|
throw new ProvisioningError(`${describeAwsFailure(error).detail}. Nothing was applied to user pool ${physicalId}`, resourceType, logicalId, physicalId, error instanceof Error ? error : void 0);
|
|
31838
32307
|
}
|
|
31839
32308
|
this.warnOnBlankMfaConfiguration(properties["MfaConfiguration"]);
|
|
32309
|
+
const createTimeOnly = createTimeOnlyChanges(properties, previousProperties);
|
|
32310
|
+
const keptCreateTimeOnly = stateBorneDesired ? createTimeOnly : [];
|
|
32311
|
+
if (createTimeOnly.length > 0) {
|
|
32312
|
+
const changed = createTimeOnly.join(", ");
|
|
32313
|
+
if (stateBorneDesired) this.logger.warn(safeMsg`Cognito User Pool ${logicalId} (${physicalId}): ${changed} cannot be changed in place ` + safeMsg`(UpdateUserPool has no such member), so the pool keeps its current value and cdkd ` + safeMsg`records that value.`);
|
|
32314
|
+
else throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `${changed} cannot be changed on an existing user pool — UpdateUserPool has no such member, and CloudFormation refuses the same change ("Updates are not allowed for property"). Nothing was applied to user pool ${physicalId}. ` + this.replacementRemedy(physicalId, previousProperties["DeletionProtection"] === "ACTIVE"));
|
|
32315
|
+
}
|
|
31840
32316
|
const liveFirstAuthFactors = mfaPreflightNeedsLiveSignInPolicy(properties, mfaConfiguration) ? await this.readLiveAllowedFirstAuthFactors(physicalId) : void 0;
|
|
31841
32317
|
this.assertMfaCombinationApplicable(logicalId, resourceType, physicalId, properties, mfaConfiguration, liveFirstAuthFactors);
|
|
31842
32318
|
const liveMfa = mfaConfiguration === "" && hasMfaConfigProps(properties) ? await this.readLiveMfaConfiguration(physicalId) : void 0;
|
|
@@ -31844,6 +32320,7 @@ var CognitoUserPoolProvider = class {
|
|
|
31844
32320
|
const mfaFirstPrior = mfaMayNeedToPrecedeUpdateUserPool(properties, mfaConfiguration) ? await this.readMfaFirstPrior(physicalId) : void 0;
|
|
31845
32321
|
try {
|
|
31846
32322
|
const updateParams = { UserPoolId: physicalId };
|
|
32323
|
+
if (typeof properties["UserPoolName"] === "string" && properties["UserPoolName"] !== "") updateParams.PoolName = properties["UserPoolName"];
|
|
31847
32324
|
if (properties["Policies"]) {
|
|
31848
32325
|
const sdkPolicies = this.toSdkUserPoolPolicies(properties["Policies"]);
|
|
31849
32326
|
if (sdkPolicies) updateParams.Policies = sdkPolicies;
|
|
@@ -31889,7 +32366,7 @@ var CognitoUserPoolProvider = class {
|
|
|
31889
32366
|
const { urlSuffix } = derivePartitionAndUrlSuffix(region);
|
|
31890
32367
|
const providerName = `cognito-idp.${region}.${urlSuffix}/${physicalId}`;
|
|
31891
32368
|
const providerUrl = `https://cognito-idp.${region}.${urlSuffix}/${physicalId}`;
|
|
31892
|
-
const effectiveProperties = narrowMfaConfiguration(properties);
|
|
32369
|
+
const effectiveProperties = withPreviousCreateTimeOnly(narrowMfaConfiguration(properties), previousProperties, keptCreateTimeOnly);
|
|
31893
32370
|
return {
|
|
31894
32371
|
physicalId,
|
|
31895
32372
|
wasReplaced: false,
|
|
@@ -31932,20 +32409,7 @@ var CognitoUserPoolProvider = class {
|
|
|
31932
32409
|
...modified.map((n) => `modified attribute '${n}'`),
|
|
31933
32410
|
...addedStandard.map((n) => `added standard attribute '${n}'`)
|
|
31934
32411
|
];
|
|
31935
|
-
if (immutableChanges.length > 0) {
|
|
31936
|
-
const replaceFlags = "cdkd deploy --replace --force-stateful-recreation";
|
|
31937
|
-
const remedy = deletionProtected ? protectedReplacementAdvice({
|
|
31938
|
-
evidence: "cdkd's properties for this user pool carry DeletionProtection: ACTIVE",
|
|
31939
|
-
replaceFlags,
|
|
31940
|
-
disable: {
|
|
31941
|
-
before: "aws cognito-idp update-user-pool --user-pool-id",
|
|
31942
|
-
identifier: physicalId,
|
|
31943
|
-
after: "--deletion-protection INACTIVE",
|
|
31944
|
-
caveat: "Note UpdateUserPool resets some members a call omits (self sign-up, Lambda triggers, advanced security and AutoVerifiedAttributes among them), so send your complete pool configuration alongside that flag rather than the flag alone."
|
|
31945
|
-
}
|
|
31946
|
-
}) : `AWS::Cognito::UserPool is a stateful type, so re-run with ${replaceFlags} to recreate it (this deletes all users in the pool).`;
|
|
31947
|
-
throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `the Schema change (${immutableChanges.join("; ")}) is immutable on AWS — AWS can only ADD custom attributes in place, so removing or modifying an attribute requires recreating the pool. ${remedy}`);
|
|
31948
|
-
}
|
|
32412
|
+
if (immutableChanges.length > 0) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `the Schema change (${immutableChanges.join("; ")}) is immutable on AWS — AWS can only ADD custom attributes in place, so removing or modifying an attribute requires recreating the pool. ${this.replacementRemedy(physicalId, deletionProtected)}`);
|
|
31949
32413
|
const addedCustom = added.filter((a) => a.Name !== void 0 && !STANDARD_USER_POOL_ATTRIBUTES.has(a.Name));
|
|
31950
32414
|
if (addedCustom.length === 0) return;
|
|
31951
32415
|
this.logger.debug(`Adding ${addedCustom.length} custom attribute(s) to ${physicalId}: ` + addedCustom.map((a) => a.Name).join(", "));
|
|
@@ -31954,6 +32418,19 @@ var CognitoUserPoolProvider = class {
|
|
|
31954
32418
|
CustomAttributes: addedCustom
|
|
31955
32419
|
}));
|
|
31956
32420
|
}
|
|
32421
|
+
replacementRemedy(physicalId, deletionProtected) {
|
|
32422
|
+
const replaceFlags = "cdkd deploy --replace --force-stateful-recreation";
|
|
32423
|
+
return deletionProtected ? protectedReplacementAdvice({
|
|
32424
|
+
evidence: "cdkd's properties for this user pool carry DeletionProtection: ACTIVE",
|
|
32425
|
+
replaceFlags,
|
|
32426
|
+
disable: {
|
|
32427
|
+
before: "aws cognito-idp update-user-pool --user-pool-id",
|
|
32428
|
+
identifier: physicalId,
|
|
32429
|
+
after: "--deletion-protection INACTIVE",
|
|
32430
|
+
caveat: "Note UpdateUserPool resets some members a call omits (self sign-up, Lambda triggers, advanced security and AutoVerifiedAttributes among them), so send your complete pool configuration alongside that flag rather than the flag alone."
|
|
32431
|
+
}
|
|
32432
|
+
}) : `AWS::Cognito::UserPool is a stateful type, so re-run with ${replaceFlags} to recreate it (this deletes all users in the pool).`;
|
|
32433
|
+
}
|
|
31957
32434
|
async delete(logicalId, physicalId, resourceType, _properties, context) {
|
|
31958
32435
|
let flipRecord;
|
|
31959
32436
|
await deleteWithProtectionCompensation({
|
|
@@ -32805,6 +33282,16 @@ function sameAsRecorded(desired, recorded) {
|
|
|
32805
33282
|
}
|
|
32806
33283
|
return isDeepStrictEqual(desired, recorded);
|
|
32807
33284
|
}
|
|
33285
|
+
function unappliedDnsConfigMembers(properties, previousProperties, changedProperties) {
|
|
33286
|
+
if (changedProperties !== void 0 && !changedProperties.has("DnsConfig")) return [];
|
|
33287
|
+
const desired = properties["DnsConfig"];
|
|
33288
|
+
const previous = previousProperties["DnsConfig"];
|
|
33289
|
+
if (!isPlainObject(desired) || !isPlainObject(previous)) return [];
|
|
33290
|
+
return ["NamespaceId", "RoutingPolicy"].filter((member) => !sameAsRecorded(desired[member], previous[member]));
|
|
33291
|
+
}
|
|
33292
|
+
function isPlainObject(value) {
|
|
33293
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
33294
|
+
}
|
|
32808
33295
|
function isRecordedStandIn(value) {
|
|
32809
33296
|
return dynamicReferenceTokens(value).length > 0 || value.includes("***");
|
|
32810
33297
|
}
|
|
@@ -33169,14 +33656,13 @@ var ServiceDiscoveryProvider = class ServiceDiscoveryProvider {
|
|
|
33169
33656
|
this.logger.debug(`Creating service discovery service ${logicalId}`);
|
|
33170
33657
|
const tags = refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId);
|
|
33171
33658
|
const client = this.getClient();
|
|
33172
|
-
const name = properties["Name"];
|
|
33659
|
+
const name = properties["Name"] || generatedNameFor("AWS::ServiceDiscovery::Service", logicalId);
|
|
33173
33660
|
const namespaceId = properties["NamespaceId"];
|
|
33174
33661
|
const description = properties["Description"];
|
|
33175
33662
|
const dnsConfig = properties["DnsConfig"];
|
|
33176
33663
|
const healthCheckCustomConfig = properties["HealthCheckCustomConfig"];
|
|
33177
33664
|
const healthCheckConfig = properties["HealthCheckConfig"];
|
|
33178
33665
|
const type = properties["Type"];
|
|
33179
|
-
if (!name) throw new ProvisioningError(`Name is required for ServiceDiscovery Service ${logicalId}`, resourceType, logicalId);
|
|
33180
33666
|
let leftBehindServiceId;
|
|
33181
33667
|
try {
|
|
33182
33668
|
const watch = startInterruptWatch(`Cloud Map service ${logicalId}`);
|
|
@@ -33274,8 +33760,10 @@ var ServiceDiscoveryProvider = class ServiceDiscoveryProvider {
|
|
|
33274
33760
|
const hasTagChange = tagPlan.set.size > 0 || tagPlan.remove.length > 0;
|
|
33275
33761
|
const tagWarning = tagPlanWarning(tagPlan, resourceType, logicalId);
|
|
33276
33762
|
if (tagWarning !== void 0) this.logger.warn(tagWarning);
|
|
33763
|
+
const unapplied = unappliedDnsConfigMembers(properties, previousProperties, changedProperties);
|
|
33277
33764
|
if (!hasServiceChange && !hasAttrUpsert && !hasAttrRemove && !hasTagChange) {
|
|
33278
33765
|
this.logger.debug(`No mutable diff for ServiceDiscovery Service ${logicalId}, skipping update`);
|
|
33766
|
+
await this.warnUnappliedDnsConfigMembers(logicalId, physicalId, properties, unapplied);
|
|
33279
33767
|
return {
|
|
33280
33768
|
physicalId,
|
|
33281
33769
|
wasReplaced: false
|
|
@@ -33336,6 +33824,7 @@ var ServiceDiscoveryProvider = class ServiceDiscoveryProvider {
|
|
|
33336
33824
|
}));
|
|
33337
33825
|
}
|
|
33338
33826
|
this.logger.debug(`Successfully updated service discovery service ${logicalId}`);
|
|
33827
|
+
await this.warnUnappliedDnsConfigMembers(logicalId, physicalId, properties, unapplied);
|
|
33339
33828
|
return {
|
|
33340
33829
|
physicalId,
|
|
33341
33830
|
wasReplaced: false
|
|
@@ -33364,6 +33853,30 @@ var ServiceDiscoveryProvider = class ServiceDiscoveryProvider {
|
|
|
33364
33853
|
keepRemovedFromLive: true
|
|
33365
33854
|
};
|
|
33366
33855
|
}
|
|
33856
|
+
async warnUnappliedDnsConfigMembers(logicalId, physicalId, properties, candidates) {
|
|
33857
|
+
if (candidates.length === 0) return;
|
|
33858
|
+
let members = candidates;
|
|
33859
|
+
try {
|
|
33860
|
+
const live = (await this.getClient().send(new GetServiceCommand({ Id: physicalId }))).Service;
|
|
33861
|
+
const dns = properties["DnsConfig"];
|
|
33862
|
+
const desired = {
|
|
33863
|
+
NamespaceId: dns.NamespaceId ?? properties["NamespaceId"],
|
|
33864
|
+
RoutingPolicy: dns.RoutingPolicy
|
|
33865
|
+
};
|
|
33866
|
+
const held = {
|
|
33867
|
+
NamespaceId: live?.NamespaceId ?? live?.DnsConfig?.NamespaceId,
|
|
33868
|
+
RoutingPolicy: live?.DnsConfig?.RoutingPolicy
|
|
33869
|
+
};
|
|
33870
|
+
members = candidates.filter((m) => desired[m] === void 0 || desired[m] !== held[m]);
|
|
33871
|
+
} catch {
|
|
33872
|
+
this.logger.debug(safeMsg`Could not read service discovery service ${logicalId} back to confirm its DnsConfig; warning unconfirmed`);
|
|
33873
|
+
}
|
|
33874
|
+
if (members.length === 0) return;
|
|
33875
|
+
const paths = members.map((m) => `DnsConfig.${m}`).join(" and ");
|
|
33876
|
+
const [it, value] = members.length > 1 ? ["them", "values"] : ["it", "value"];
|
|
33877
|
+
const remedy = members.includes("NamespaceId") ? "To move the service, declare the namespace in the top-level NamespaceId: a change there replaces the service." : "To change it, replace the service, for example by giving it a new Name.";
|
|
33878
|
+
this.logger.warn(safeMsg`${logicalId} (AWS::ServiceDiscovery::Service): ${paths} changed, but Cloud Map cannot change ${it} on an existing service, so the service keeps its current ${value}, as CloudFormation does. ${remedy}`);
|
|
33879
|
+
}
|
|
33367
33880
|
async keepUndeclaredServiceFields(physicalId, serviceChange) {
|
|
33368
33881
|
if (serviceChange.Description !== void 0 && serviceChange.HealthCheckConfig !== void 0) return;
|
|
33369
33882
|
const live = (await this.getClient().send(new GetServiceCommand({ Id: physicalId }))).Service;
|
|
@@ -33915,31 +34428,19 @@ var AppSyncProvider = class {
|
|
|
33915
34428
|
deepEqual(a, b) {
|
|
33916
34429
|
return JSON.stringify(a) === JSON.stringify(b);
|
|
33917
34430
|
}
|
|
33918
|
-
async
|
|
33919
|
-
if (
|
|
34431
|
+
async unchangedGraphqlApiName(apiId, resourceType, logicalId, desired, recorded, mask) {
|
|
34432
|
+
if (desired === void 0 || desired === recorded) return recorded;
|
|
33920
34433
|
let liveName;
|
|
33921
34434
|
try {
|
|
33922
|
-
liveName = (await this.getClient().send(new GetGraphqlApiCommand({ apiId
|
|
34435
|
+
liveName = (await this.getClient().send(new GetGraphqlApiCommand({ apiId }))).graphqlApi?.name;
|
|
33923
34436
|
} catch (error) {
|
|
33924
|
-
throw this.
|
|
34437
|
+
throw this.wrapUpdateError(error, resourceType, logicalId, apiId, "GraphqlApi", mask);
|
|
33925
34438
|
}
|
|
33926
|
-
if (liveName === void 0) throw
|
|
33927
|
-
return
|
|
33928
|
-
resourceType,
|
|
33929
|
-
key: "Name",
|
|
33930
|
-
desired,
|
|
33931
|
-
previous,
|
|
33932
|
-
physicalName: liveName
|
|
33933
|
-
});
|
|
33934
|
-
}
|
|
33935
|
-
wrapGraphQLApiNameLookupError(error, logicalId, physicalId, resourceType, mask) {
|
|
33936
|
-
const failureClass = error === void 0 ? "an answer with no name" : error instanceof Error && error.name !== "" ? error.name : "an unreadable failure";
|
|
33937
|
-
const next = failureClass === "NotFoundException" ? `the API ${physicalId} no longer exists; check it with 'cdkd drift' before deploying again` : "re-run once the lookup can succeed";
|
|
33938
|
-
return markRedactedCause(new ProvisioningError(`Name of AWS::AppSync::GraphQLApi ${logicalId} is secret-derived, and whether the value its secret resolves to is still the API's name could not be confirmed (${mask(failureClass)}) — ${next}`, resourceType, logicalId, physicalId, error instanceof Error ? error : void 0));
|
|
34439
|
+
if (liveName === void 0 || liveName === "") throw new ProvisioningError(`Could not read the current name of AppSync GraphqlApi ${apiId} to update it without renaming it`, resourceType, logicalId, apiId);
|
|
34440
|
+
return liveName;
|
|
33939
34441
|
}
|
|
33940
34442
|
async updateGraphQLApi(logicalId, physicalId, resourceType, properties, previousProperties, context) {
|
|
33941
34443
|
refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId);
|
|
33942
|
-
if (properties["Name"] !== void 0 && previousProperties["Name"] !== void 0 && properties["Name"] !== previousProperties["Name"] && !await this.graphQLApiNameUnchangedBehindSecret(logicalId, physicalId, resourceType, properties["Name"], previousProperties["Name"], maskerOrIdentity(context?.maskSecrets))) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "AWS AppSync GraphqlApi.Name is immutable — destroy + redeploy to rename");
|
|
33943
34444
|
for (const immutable of ["ApiType", "Visibility"]) if (properties[immutable] !== void 0 && previousProperties[immutable] !== void 0 && properties[immutable] !== previousProperties[immutable]) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `AWS AppSync GraphqlApi.${immutable} is immutable — destroy + redeploy to change it`);
|
|
33944
34445
|
if (context?.replayingState !== true && context?.desiredFromAwsReadback !== true) this.refuseChangedMalformedGraphQLApiBlocks(properties, previousProperties, logicalId, physicalId, resourceType);
|
|
33945
34446
|
const newAuthType = properties["AuthenticationType"];
|
|
@@ -33952,10 +34453,11 @@ var AppSyncProvider = class {
|
|
|
33952
34453
|
const hasAuthDiff = ("AuthenticationType" in properties || "AuthenticationType" in previousProperties) && newAuthType !== oldAuthType;
|
|
33953
34454
|
const hasLogDiff = ("LogConfig" in properties || "LogConfig" in previousProperties) && !this.deepEqual(newLog, oldLog);
|
|
33954
34455
|
const hasConfigDiff = MUTABLE_GRAPHQL_API_CONFIG_PROPERTIES.some((key) => (key in properties || key in previousProperties) && !this.deepEqual(properties[key], previousProperties[key]));
|
|
33955
|
-
|
|
34456
|
+
const hasNameDiff = properties["Name"] !== void 0 && (context?.changedProperties !== void 0 ? context.changedProperties.has("Name") : properties["Name"] !== previousProperties["Name"]);
|
|
34457
|
+
if (hasNameDiff || hasAuthDiff || hasXrayDiff || hasLogDiff || hasConfigDiff) {
|
|
33956
34458
|
const input = {
|
|
33957
34459
|
apiId: physicalId,
|
|
33958
|
-
name: properties["Name"]
|
|
34460
|
+
name: hasNameDiff ? properties["Name"] : await this.unchangedGraphqlApiName(physicalId, resourceType, logicalId, properties["Name"], previousProperties["Name"], maskerOrIdentity(context?.maskSecrets)),
|
|
33959
34461
|
authenticationType: newAuthType ?? oldAuthType ?? "API_KEY"
|
|
33960
34462
|
};
|
|
33961
34463
|
if (newXray !== void 0) input.xrayEnabled = newXray;
|
|
@@ -33996,6 +34498,14 @@ var AppSyncProvider = class {
|
|
|
33996
34498
|
};
|
|
33997
34499
|
}
|
|
33998
34500
|
async updateGraphQLSchema(logicalId, physicalId, resourceType, properties, previousProperties, mask = maskerOrIdentity(void 0)) {
|
|
34501
|
+
if (properties["ApiId"] !== void 0 && previousProperties["ApiId"] !== void 0 && properties["ApiId"] !== previousProperties["ApiId"] && !await unchangedBehindSecretReference({
|
|
34502
|
+
resourceType,
|
|
34503
|
+
key: "ApiId",
|
|
34504
|
+
desired: properties["ApiId"],
|
|
34505
|
+
previous: previousProperties["ApiId"],
|
|
34506
|
+
physicalName: physicalId,
|
|
34507
|
+
maskSecrets: mask
|
|
34508
|
+
})) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "AWS AppSync GraphQLSchema.ApiId cannot move a schema to another API in place (CloudFormation fails a template change of it too) — deploy with --replace, or give the schema a new logical ID, to create it on the new API");
|
|
33999
34509
|
const newDef = properties["Definition"];
|
|
34000
34510
|
const oldDef = previousProperties["Definition"];
|
|
34001
34511
|
const newLoc = properties["DefinitionS3Location"];
|
|
@@ -34034,11 +34544,7 @@ var AppSyncProvider = class {
|
|
|
34034
34544
|
}
|
|
34035
34545
|
async updateDataSource(logicalId, physicalId, resourceType, properties, previousProperties, mask) {
|
|
34036
34546
|
const [idApiId, idName] = physicalId.split("|");
|
|
34037
|
-
for (const field of [
|
|
34038
|
-
"ApiId",
|
|
34039
|
-
"Name",
|
|
34040
|
-
"Type"
|
|
34041
|
-
]) {
|
|
34547
|
+
for (const field of ["ApiId", "Name"]) {
|
|
34042
34548
|
const next = properties[field];
|
|
34043
34549
|
const prev = previousProperties[field];
|
|
34044
34550
|
if (next !== void 0 && prev !== void 0 && next !== prev && !await unchangedBehindSecretReference({
|
|
@@ -34046,7 +34552,7 @@ var AppSyncProvider = class {
|
|
|
34046
34552
|
key: field,
|
|
34047
34553
|
desired: next,
|
|
34048
34554
|
previous: prev,
|
|
34049
|
-
physicalName: field === "ApiId" ? idApiId :
|
|
34555
|
+
physicalName: field === "ApiId" ? idApiId : idName,
|
|
34050
34556
|
maskSecrets: mask
|
|
34051
34557
|
})) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `AWS AppSync DataSource.${field} is immutable — destroy + redeploy to change`);
|
|
34052
34558
|
}
|
|
@@ -34054,6 +34560,7 @@ var AppSyncProvider = class {
|
|
|
34054
34560
|
if (!apiId || !name) throw new ProvisioningError(compositeIdFormatMessage(APPSYNC_DATASOURCE_ID_FORMAT, logicalId, physicalId), resourceType, logicalId, physicalId);
|
|
34055
34561
|
const type = properties["Type"] ?? previousProperties["Type"];
|
|
34056
34562
|
if (![
|
|
34563
|
+
"Type",
|
|
34057
34564
|
"Description",
|
|
34058
34565
|
"ServiceRoleArn",
|
|
34059
34566
|
"DynamoDBConfig",
|
|
@@ -36580,7 +37087,7 @@ async function fetchGlueTags(client, stsClient, resource, name, accountId, logge
|
|
|
36580
37087
|
const resp = await client.send(new GetTagsCommand({ ResourceArn: arn }));
|
|
36581
37088
|
return normalizeAwsTagsToCfn(resp.Tags);
|
|
36582
37089
|
} catch (err) {
|
|
36583
|
-
logger.debug(`GetTags failed for ${resource}
|
|
37090
|
+
logger.debug(`GetTags failed for a Glue ${resource}: ${describeAwsFailure(err).summary}`);
|
|
36584
37091
|
return [];
|
|
36585
37092
|
}
|
|
36586
37093
|
}
|
|
@@ -37190,13 +37697,28 @@ function toCfnCrawlerTargets(targets) {
|
|
|
37190
37697
|
var GlueConnectionProvider = class {
|
|
37191
37698
|
client;
|
|
37192
37699
|
createClient;
|
|
37700
|
+
stsClient;
|
|
37193
37701
|
providerRegion = ambientRegion();
|
|
37194
37702
|
callerAccountId = makeCallerAccountResolver(this.providerRegion);
|
|
37195
37703
|
logger = getLogger().child("GlueConnectionProvider");
|
|
37196
37704
|
wrapMaskedError(mask, error, build) {
|
|
37197
37705
|
return wrapGlueError(mask, (message) => this.logger.debug(message), error, build);
|
|
37198
37706
|
}
|
|
37199
|
-
handledProperties = /* @__PURE__ */ new Map([["AWS::Glue::Connection", /* @__PURE__ */ new Set([
|
|
37707
|
+
handledProperties = /* @__PURE__ */ new Map([["AWS::Glue::Connection", /* @__PURE__ */ new Set([
|
|
37708
|
+
"ConnectionInput",
|
|
37709
|
+
"CatalogId",
|
|
37710
|
+
"Tags"
|
|
37711
|
+
])]]);
|
|
37712
|
+
getStsClient() {
|
|
37713
|
+
if (!this.stsClient) this.stsClient = new STSClient({
|
|
37714
|
+
...ambientClientDefaults(),
|
|
37715
|
+
...this.providerRegion ? { region: this.providerRegion } : {}
|
|
37716
|
+
});
|
|
37717
|
+
return this.stsClient;
|
|
37718
|
+
}
|
|
37719
|
+
resourceArn(name, catalogIdValue) {
|
|
37720
|
+
return buildGlueResourceArn(this.getClient(), this.getStsClient(), "connection", name, catalogIdForApi(catalogIdValue));
|
|
37721
|
+
}
|
|
37200
37722
|
getClient() {
|
|
37201
37723
|
if (!this.client) ({client: this.client, createClient: this.createClient} = newGlueClients(this.providerRegion));
|
|
37202
37724
|
return this.client;
|
|
@@ -37211,12 +37733,14 @@ var GlueConnectionProvider = class {
|
|
|
37211
37733
|
log.debug(`Creating Glue Connection ${logicalId}`);
|
|
37212
37734
|
const connectionInput = properties["ConnectionInput"];
|
|
37213
37735
|
if (!connectionInput) throw new ProvisioningError(`ConnectionInput is required for Glue Connection ${logicalId}`, resourceType, logicalId);
|
|
37736
|
+
const tags = desiredGlueTags(properties["Tags"], resourceType, logicalId);
|
|
37214
37737
|
const name = connectionInput["Name"] ?? generatedNameFor("AWS::Glue::Connection", logicalId);
|
|
37215
37738
|
const catalogId = properties["CatalogId"];
|
|
37216
37739
|
try {
|
|
37217
37740
|
await this.getCreateClient().send(new CreateConnectionCommand({
|
|
37218
37741
|
...catalogId && { CatalogId: catalogId },
|
|
37219
|
-
ConnectionInput: buildConnectionInput(connectionInput, name)
|
|
37742
|
+
ConnectionInput: buildConnectionInput(connectionInput, name),
|
|
37743
|
+
...tags && { Tags: tags }
|
|
37220
37744
|
}));
|
|
37221
37745
|
log.debug(`Successfully created Glue Connection ${logicalId}: ${v(name)}`);
|
|
37222
37746
|
return {
|
|
@@ -37259,6 +37783,7 @@ var GlueConnectionProvider = class {
|
|
|
37259
37783
|
debug: log.debug,
|
|
37260
37784
|
mask: log.mask
|
|
37261
37785
|
});
|
|
37786
|
+
desiredGlueTags(properties["Tags"], resourceType, logicalId, physicalId);
|
|
37262
37787
|
const catalogId = updateCatalogId(properties["CatalogId"]);
|
|
37263
37788
|
try {
|
|
37264
37789
|
await this.getClient().send(new UpdateConnectionCommand({
|
|
@@ -37266,6 +37791,7 @@ var GlueConnectionProvider = class {
|
|
|
37266
37791
|
Name: physicalId,
|
|
37267
37792
|
ConnectionInput: buildConnectionInput(connectionInput, physicalId)
|
|
37268
37793
|
}));
|
|
37794
|
+
await applyGlueTagDiff(this.getClient(), () => this.resourceArn(physicalId, properties["CatalogId"]), previousProperties?.["Tags"], properties["Tags"], resourceType, logicalId, log.warn);
|
|
37269
37795
|
return {
|
|
37270
37796
|
physicalId,
|
|
37271
37797
|
wasReplaced: false
|
|
@@ -37316,7 +37842,7 @@ var GlueConnectionProvider = class {
|
|
|
37316
37842
|
throw err;
|
|
37317
37843
|
}
|
|
37318
37844
|
if (!conn) return void 0;
|
|
37319
|
-
|
|
37845
|
+
const ci = {
|
|
37320
37846
|
Name: conn.Name ?? physicalId,
|
|
37321
37847
|
ConnectionType: conn.ConnectionType ?? "",
|
|
37322
37848
|
Description: conn.Description ?? "",
|
|
@@ -37326,7 +37852,12 @@ var GlueConnectionProvider = class {
|
|
|
37326
37852
|
AthenaProperties: conn.AthenaProperties ?? {},
|
|
37327
37853
|
PythonProperties: conn.PythonProperties ?? {},
|
|
37328
37854
|
PhysicalConnectionRequirements: conn.PhysicalConnectionRequirements ? pickDefined(conn.PhysicalConnectionRequirements) : {}
|
|
37329
|
-
}
|
|
37855
|
+
};
|
|
37856
|
+
const name = conn.Name ?? physicalId;
|
|
37857
|
+
return withRecordedCatalogId({
|
|
37858
|
+
ConnectionInput: ci,
|
|
37859
|
+
Tags: await fetchGlueTags(this.getClient(), this.getStsClient(), "connection", name, catalogId, this.logger)
|
|
37860
|
+
}, properties);
|
|
37330
37861
|
}
|
|
37331
37862
|
async import(input) {
|
|
37332
37863
|
const explicitName = input.knownPhysicalId ?? input.properties["ConnectionInput"]?.["Name"];
|
|
@@ -37673,9 +38204,9 @@ var KMSProvider = class {
|
|
|
37673
38204
|
const keySpec = properties["KeySpec"];
|
|
37674
38205
|
const keyUsage = properties["KeyUsage"];
|
|
37675
38206
|
const enableKeyRotation = templateBool(properties["EnableKeyRotation"]);
|
|
37676
|
-
const multiRegion = properties["MultiRegion"];
|
|
38207
|
+
const multiRegion = templateBool(properties["MultiRegion"]);
|
|
37677
38208
|
const origin = properties["Origin"];
|
|
37678
|
-
const bypassPolicyLockoutSafetyCheck = properties["BypassPolicyLockoutSafetyCheck"];
|
|
38209
|
+
const bypassPolicyLockoutSafetyCheck = templateBool(properties["BypassPolicyLockoutSafetyCheck"]);
|
|
37679
38210
|
const input = {
|
|
37680
38211
|
Description: description,
|
|
37681
38212
|
KeySpec: keySpec,
|
|
@@ -38282,7 +38813,7 @@ function isoDate(value) {
|
|
|
38282
38813
|
else if (typeof value === "string" && /^\d+$/.test(value)) {
|
|
38283
38814
|
const n = Number(value);
|
|
38284
38815
|
date = new Date(n < 0xe8d4a51000 ? n * 1e3 : n);
|
|
38285
|
-
} else if (typeof value === "string") date =
|
|
38816
|
+
} else if (typeof value === "string") date = parseCfnTimestamp(value);
|
|
38286
38817
|
else if (value instanceof Date) date = value;
|
|
38287
38818
|
else return void 0;
|
|
38288
38819
|
return Number.isNaN(date.getTime()) ? void 0 : date.toISOString();
|
|
@@ -38452,7 +38983,7 @@ var BudgetsBudgetProvider = class {
|
|
|
38452
38983
|
else if (typeof raw === "string" && /^\d+$/.test(raw)) {
|
|
38453
38984
|
const num = Number(raw);
|
|
38454
38985
|
date = new Date(num < 0xe8d4a51000 ? num * 1e3 : num);
|
|
38455
|
-
} else if (typeof raw === "string") date =
|
|
38986
|
+
} else if (typeof raw === "string") date = parseCfnTimestamp(raw);
|
|
38456
38987
|
else throw new ProvisioningError(`Invalid TimePeriod.${field} for budget ${logicalId}: expected a date string or epoch timestamp, got ${JSON.stringify(maskDeep(raw, mask))}`, resourceType, logicalId);
|
|
38457
38988
|
if (Number.isNaN(date.getTime())) throw new ProvisioningError(`Invalid TimePeriod.${field} for budget ${logicalId}: ${JSON.stringify(maskDeep(raw, mask))} is not a parseable date`, resourceType, logicalId);
|
|
38458
38989
|
return date;
|
|
@@ -39101,6 +39632,18 @@ function comparableRecordSize(value, mask) {
|
|
|
39101
39632
|
const read = readMaxRecordSize(value, mask);
|
|
39102
39633
|
return read.kind === "usable" ? read.size : void 0;
|
|
39103
39634
|
}
|
|
39635
|
+
const DEFAULT_RECORD_DISTRIBUTION_STRATEGY = "USER_PARTITION_KEY";
|
|
39636
|
+
function readDistributionStrategy(value, mask) {
|
|
39637
|
+
if (value == null) return { kind: "absent" };
|
|
39638
|
+
if (typeof value === "string" && value.trim() !== "") return {
|
|
39639
|
+
kind: "usable",
|
|
39640
|
+
strategy: value
|
|
39641
|
+
};
|
|
39642
|
+
return {
|
|
39643
|
+
kind: "unusable",
|
|
39644
|
+
reason: `AWS::Kinesis::Stream RecordDistributionStrategy must be a non-empty string, got ${JSON.stringify(maskDeep(value, mask))}`
|
|
39645
|
+
};
|
|
39646
|
+
}
|
|
39104
39647
|
const KINESIS_DELETE_POLL_INTERVAL_MS = 2e3;
|
|
39105
39648
|
const KINESIS_DELETE_MAX_WAIT_MS = 3e5;
|
|
39106
39649
|
function isStreamName(id) {
|
|
@@ -39119,8 +39662,10 @@ var KinesisStreamProvider = class {
|
|
|
39119
39662
|
"RetentionPeriodHours",
|
|
39120
39663
|
"StreamEncryption",
|
|
39121
39664
|
"DesiredShardLevelMetrics",
|
|
39122
|
-
"MaxRecordSizeInKiB"
|
|
39665
|
+
"MaxRecordSizeInKiB",
|
|
39666
|
+
"RecordDistributionStrategy"
|
|
39123
39667
|
])]]);
|
|
39668
|
+
unhandledByDesign = /* @__PURE__ */ new Map([["AWS::Kinesis::Stream", /* @__PURE__ */ new Map([["WarmThroughputMiBps", "AWS accepts it only on an account enrolled in the Kinesis minimum throughput billing commitment, so the SDK path is not wired (go-to-k/cdkd#1695); Cloud Control forwards it."]])]]);
|
|
39124
39669
|
getClient() {
|
|
39125
39670
|
if (!this.client) this.client = new KinesisClient({
|
|
39126
39671
|
...ambientClientDefaults(),
|
|
@@ -39158,6 +39703,11 @@ var KinesisStreamProvider = class {
|
|
|
39158
39703
|
}
|
|
39159
39704
|
const encryptionRead = readEncryptionKeyId(properties["StreamEncryption"], mask);
|
|
39160
39705
|
if (encryptionRead.kind === "unusable") throw new ProvisioningError(encryptionRead.reason, resourceType, logicalId, streamName);
|
|
39706
|
+
const strategyRead = readDistributionStrategy(properties["RecordDistributionStrategy"], mask);
|
|
39707
|
+
if (strategyRead.kind === "unusable") {
|
|
39708
|
+
if (context?.replayingState !== true) throw new ProvisioningError(strategyRead.reason, resourceType, logicalId, streamName);
|
|
39709
|
+
warn(`${strategyRead.reason}. Replaying a state record, so ${streamName} is created with AWS's default record distribution strategy rather than refusing the restore`);
|
|
39710
|
+
}
|
|
39161
39711
|
let streamCreated = false;
|
|
39162
39712
|
try {
|
|
39163
39713
|
const streamModeDetails = properties["StreamModeDetails"];
|
|
@@ -39171,6 +39721,7 @@ var KinesisStreamProvider = class {
|
|
|
39171
39721
|
...shardCount !== void 0 && { ShardCount: shardCount },
|
|
39172
39722
|
StreamModeDetails: { StreamMode: streamMode },
|
|
39173
39723
|
...maxRecordSizeInKiB !== void 0 && { MaxRecordSizeInKiB: maxRecordSizeInKiB },
|
|
39724
|
+
...strategyRead.kind === "usable" && { RecordDistributionStrategy: strategyRead.strategy },
|
|
39174
39725
|
...Object.keys(tags).length > 0 && { Tags: tags }
|
|
39175
39726
|
}));
|
|
39176
39727
|
streamCreated = true;
|
|
@@ -39310,6 +39861,7 @@ var KinesisStreamProvider = class {
|
|
|
39310
39861
|
}));
|
|
39311
39862
|
await this.waitForStreamActive(physicalId);
|
|
39312
39863
|
}
|
|
39864
|
+
await this.reconcileDistributionStrategy(physicalId, streamMode, properties, previousProperties, mask, warn);
|
|
39313
39865
|
const desiredRead = readShardLevelMetrics(properties["DesiredShardLevelMetrics"], mask);
|
|
39314
39866
|
let desiredMetrics;
|
|
39315
39867
|
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`);
|
|
@@ -39430,6 +39982,30 @@ var KinesisStreamProvider = class {
|
|
|
39430
39982
|
throw error;
|
|
39431
39983
|
}
|
|
39432
39984
|
}
|
|
39985
|
+
async reconcileDistributionStrategy(physicalId, streamMode, properties, previousProperties, mask, warn) {
|
|
39986
|
+
const desired = readDistributionStrategy(properties["RecordDistributionStrategy"], mask);
|
|
39987
|
+
if (desired.kind === "unusable") {
|
|
39988
|
+
warn(`${desired.reason}. Leaving the record distribution strategy on ${physicalId} unchanged; the same value is REFUSED on a template-path create`);
|
|
39989
|
+
return;
|
|
39990
|
+
}
|
|
39991
|
+
const previous = readDistributionStrategy(previousProperties["RecordDistributionStrategy"], mask);
|
|
39992
|
+
const recorded = previous.kind === "usable" ? previous.strategy : void 0;
|
|
39993
|
+
let target;
|
|
39994
|
+
if (desired.kind === "usable") {
|
|
39995
|
+
if (desired.strategy === recorded) return;
|
|
39996
|
+
target = desired.strategy;
|
|
39997
|
+
} else {
|
|
39998
|
+
if (recorded === void 0 || recorded === DEFAULT_RECORD_DISTRIBUTION_STRATEGY) return;
|
|
39999
|
+
if (streamMode !== "ON_DEMAND") return;
|
|
40000
|
+
target = DEFAULT_RECORD_DISTRIBUTION_STRATEGY;
|
|
40001
|
+
}
|
|
40002
|
+
this.logger.debug(mask(safeMsg`Updating record distribution strategy for ${physicalId}: from ${recorded ?? "no value"} to ${target}`));
|
|
40003
|
+
await this.getClient().send(new UpdateStreamRecordDistributionStrategyCommand({
|
|
40004
|
+
StreamARN: await this.resolveStreamArn(physicalId),
|
|
40005
|
+
RecordDistributionStrategy: target
|
|
40006
|
+
}));
|
|
40007
|
+
await this.waitForStreamActive(physicalId);
|
|
40008
|
+
}
|
|
39433
40009
|
effectiveMetricsProperties(properties, expanded) {
|
|
39434
40010
|
if (expanded === void 0) return {};
|
|
39435
40011
|
if (expanded === properties["DesiredShardLevelMetrics"]) return {};
|
|
@@ -39496,8 +40072,11 @@ var KinesisStreamProvider = class {
|
|
|
39496
40072
|
}
|
|
39497
40073
|
result["DesiredShardLevelMetrics"] = (stream.EnhancedMonitoring ?? []).flatMap((entry) => entry.ShardLevelMetrics ?? []);
|
|
39498
40074
|
try {
|
|
39499
|
-
const
|
|
40075
|
+
const summaryResp = await this.getClient().send(new DescribeStreamSummaryCommand({ StreamName: physicalId }));
|
|
40076
|
+
const maxRecordSize = summaryResp.StreamDescriptionSummary?.MaxRecordSizeInKiB;
|
|
39500
40077
|
if (maxRecordSize !== void 0) result["MaxRecordSizeInKiB"] = maxRecordSize;
|
|
40078
|
+
const strategy = summaryResp.StreamDescriptionSummary?.RecordDistributionStrategy;
|
|
40079
|
+
if (strategy !== void 0) result["RecordDistributionStrategy"] = strategy;
|
|
39501
40080
|
} catch (err) {
|
|
39502
40081
|
if (err instanceof ResourceNotFoundException$12) return RESOURCE_NOT_FOUND;
|
|
39503
40082
|
throw err;
|
|
@@ -39843,8 +40422,8 @@ var SchedulerScheduleProvider = class {
|
|
|
39843
40422
|
Target: this.toSdkTarget(properties["Target"]),
|
|
39844
40423
|
...properties["Description"] !== void 0 && { Description: properties["Description"] },
|
|
39845
40424
|
...properties["ScheduleExpressionTimezone"] !== void 0 && { ScheduleExpressionTimezone: properties["ScheduleExpressionTimezone"] },
|
|
39846
|
-
...properties["StartDate"] !== void 0 && { StartDate:
|
|
39847
|
-
...properties["EndDate"] !== void 0 && { EndDate:
|
|
40425
|
+
...properties["StartDate"] !== void 0 && { StartDate: parseCfnTimestamp(properties["StartDate"]) },
|
|
40426
|
+
...properties["EndDate"] !== void 0 && { EndDate: parseCfnTimestamp(properties["EndDate"]) },
|
|
39848
40427
|
...properties["State"] !== void 0 && { State: properties["State"] },
|
|
39849
40428
|
...properties["KmsKeyArn"] !== void 0 && { KmsKeyArn: properties["KmsKeyArn"] }
|
|
39850
40429
|
};
|
|
@@ -40357,7 +40936,7 @@ function toSdkSourceParameters(value) {
|
|
|
40357
40936
|
...source,
|
|
40358
40937
|
KinesisStreamParameters: {
|
|
40359
40938
|
...kinesis,
|
|
40360
|
-
StartingPositionTimestamp:
|
|
40939
|
+
StartingPositionTimestamp: parseCfnTimestamp(kinesis["StartingPositionTimestamp"])
|
|
40361
40940
|
}
|
|
40362
40941
|
};
|
|
40363
40942
|
}
|
|
@@ -44188,6 +44767,46 @@ var EMRInstanceFleetConfigProvider = class {
|
|
|
44188
44767
|
|
|
44189
44768
|
//#endregion
|
|
44190
44769
|
//#region src/provisioning/providers/firehose-provider.ts
|
|
44770
|
+
const ENCRYPTION_KEY = "DeliveryStreamEncryptionConfigurationInput";
|
|
44771
|
+
function readEncryptionInput(value, emptyIsAbsent) {
|
|
44772
|
+
if (value === void 0 || value === null) return { kind: "absent" };
|
|
44773
|
+
if (typeof value !== "object" || Array.isArray(value)) return { kind: "unusable" };
|
|
44774
|
+
const block = value;
|
|
44775
|
+
if (emptyIsAbsent && Object.keys(block).length === 0) return { kind: "absent" };
|
|
44776
|
+
const keyType = block["KeyType"];
|
|
44777
|
+
const keyArn = block["KeyArn"] || block["KeyARN"];
|
|
44778
|
+
if (typeof keyType !== "string" || keyType.length === 0) return { kind: "unusable" };
|
|
44779
|
+
if (keyArn !== void 0 && keyArn !== null && keyArn !== "" && typeof keyArn !== "string") return { kind: "unusable" };
|
|
44780
|
+
return typeof keyArn === "string" && keyArn.length > 0 ? {
|
|
44781
|
+
kind: "usable",
|
|
44782
|
+
keyType,
|
|
44783
|
+
keyArn
|
|
44784
|
+
} : {
|
|
44785
|
+
kind: "usable",
|
|
44786
|
+
keyType
|
|
44787
|
+
};
|
|
44788
|
+
}
|
|
44789
|
+
function sameEncryptionInput(next, nextRead, prev) {
|
|
44790
|
+
const b = readEncryptionInput(prev, true);
|
|
44791
|
+
if (nextRead.kind === "unusable" || b.kind === "unusable") return JSON.stringify(next) === JSON.stringify(prev);
|
|
44792
|
+
if (nextRead.kind === "absent" || b.kind === "absent") return nextRead.kind === b.kind;
|
|
44793
|
+
return nextRead.keyType === b.keyType && nextRead.keyArn === b.keyArn;
|
|
44794
|
+
}
|
|
44795
|
+
function encryptionMatches(live, desired) {
|
|
44796
|
+
if (live?.Status !== "ENABLED" || live.KeyType !== desired.keyType) return false;
|
|
44797
|
+
return desired.keyType !== "CUSTOMER_MANAGED_CMK" || live.KeyARN === desired.keyArn;
|
|
44798
|
+
}
|
|
44799
|
+
function liveEncryptionAsCfn(live) {
|
|
44800
|
+
const status = live?.Status;
|
|
44801
|
+
if (status !== "ENABLED" && status !== "ENABLING" && status !== "DISABLING_FAILED") return {};
|
|
44802
|
+
return {
|
|
44803
|
+
...live?.KeyARN !== void 0 && { KeyARN: live.KeyARN },
|
|
44804
|
+
...live?.KeyType !== void 0 && { KeyType: live.KeyType }
|
|
44805
|
+
};
|
|
44806
|
+
}
|
|
44807
|
+
const ENCRYPTION_POLL_INTERVAL_MS = 5e3;
|
|
44808
|
+
const ENCRYPTION_POLL_MAX_ATTEMPTS = 120;
|
|
44809
|
+
const terminalEncryptionFailures = /* @__PURE__ */ new WeakSet();
|
|
44191
44810
|
function isReadableTagList(value) {
|
|
44192
44811
|
if (value === void 0 || value === null) return true;
|
|
44193
44812
|
return Array.isArray(value) && value.every((t) => typeof t === "object" && t !== null && !Array.isArray(t) && typeof t.Key === "string" && t.Key.length > 0 && !holdsSecretDerivedEntry(t.Key));
|
|
@@ -44412,15 +45031,24 @@ var FirehoseProvider = class {
|
|
|
44412
45031
|
async update(logicalId, physicalId, resourceType, properties, previousProperties, context) {
|
|
44413
45032
|
assertRegionMatch(context?.expectedRegion ? await this.getClient().config.region() : void 0, context?.expectedRegion, resourceType, logicalId, physicalId, "pre-update");
|
|
44414
45033
|
try {
|
|
44415
|
-
return await this.applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties);
|
|
45034
|
+
return await this.applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, context);
|
|
44416
45035
|
} catch (error) {
|
|
44417
45036
|
if (error instanceof CdkdError) throw error;
|
|
44418
45037
|
const cause = error instanceof Error ? error : void 0;
|
|
44419
45038
|
throw this.wrapCaughtError(maskerOrIdentity(context?.maskSecrets), error, (text) => new ProvisioningError(`Failed to update Firehose delivery stream ${logicalId}: ${text}`, resourceType, logicalId, physicalId, cause));
|
|
44420
45039
|
}
|
|
44421
45040
|
}
|
|
44422
|
-
async applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
45041
|
+
async applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, context) {
|
|
44423
45042
|
this.logger.debug(`Updating Firehose delivery stream ${logicalId}: ${physicalId}`);
|
|
45043
|
+
const desiredEncryption = readEncryptionInput(properties[ENCRYPTION_KEY], context?.desiredFromAwsReadback === true);
|
|
45044
|
+
const encryptionChanged = !sameEncryptionInput(properties[ENCRYPTION_KEY], desiredEncryption, previousProperties[ENCRYPTION_KEY]);
|
|
45045
|
+
let encryptionSkipped = false;
|
|
45046
|
+
if (encryptionChanged && desiredEncryption.kind === "unusable") {
|
|
45047
|
+
const message = `${ENCRYPTION_KEY} of Firehose delivery stream ${logicalId} is not an object with a string KeyType (and a string KeyARN, if any)`;
|
|
45048
|
+
if (context?.replayingState !== true) throw markNonRetryable(new ProvisioningError(`${message} — nothing was updated`, resourceType, logicalId, physicalId));
|
|
45049
|
+
this.logger.warn(safeMsg`${message}; its encryption is left unchanged`);
|
|
45050
|
+
encryptionSkipped = true;
|
|
45051
|
+
}
|
|
44424
45052
|
const destKey = this.findDestinationKey(properties);
|
|
44425
45053
|
const prevDestKey = this.findDestinationKey(previousProperties);
|
|
44426
45054
|
if (destKey && prevDestKey && destKey !== prevDestKey) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `Switching Firehose destination type from '${prevDestKey}' to '${destKey}' is not supported in-place — AWS UpdateDestination requires the same destination type as the original CreateDeliveryStream. Re-deploy with cdkd deploy --replace.`);
|
|
@@ -44482,11 +45110,21 @@ var FirehoseProvider = class {
|
|
|
44482
45110
|
const prevDest = previousProperties[activeDest] ?? {};
|
|
44483
45111
|
if (JSON.stringify(nextDest) !== JSON.stringify(prevDest)) await this.applySnowflakeDestinationUpdate(logicalId, physicalId, nextDest);
|
|
44484
45112
|
}
|
|
45113
|
+
if (encryptionChanged && desiredEncryption.kind !== "unusable") await this.applyEncryptionUpdate(logicalId, physicalId, resourceType, desiredEncryption, maskerOrIdentity(context?.maskSecrets));
|
|
44485
45114
|
const desc = (await this.getClient().send(new DescribeDeliveryStreamCommand({ DeliveryStreamName: physicalId }))).DeliveryStreamDescription;
|
|
44486
45115
|
return {
|
|
44487
45116
|
physicalId,
|
|
44488
45117
|
wasReplaced: false,
|
|
44489
|
-
attributes: { ...desc?.DeliveryStreamARN !== void 0 && { Arn: desc.DeliveryStreamARN } }
|
|
45118
|
+
attributes: { ...desc?.DeliveryStreamARN !== void 0 && { Arn: desc.DeliveryStreamARN } },
|
|
45119
|
+
...encryptionSkipped && { effectiveProperties: this.withRecordedEncryption(properties, previousProperties[ENCRYPTION_KEY], desc?.DeliveryStreamEncryptionConfiguration) }
|
|
45120
|
+
};
|
|
45121
|
+
}
|
|
45122
|
+
withRecordedEncryption(properties, previous, live) {
|
|
45123
|
+
const { [ENCRYPTION_KEY]: _skipped, ...rest } = properties;
|
|
45124
|
+
if (previous === void 0 || previous === null) return rest;
|
|
45125
|
+
return {
|
|
45126
|
+
...rest,
|
|
45127
|
+
[ENCRYPTION_KEY]: liveEncryptionAsCfn(live)
|
|
44490
45128
|
};
|
|
44491
45129
|
}
|
|
44492
45130
|
async applyExtendedS3DestinationUpdate(logicalId, physicalId, nextConfig) {
|
|
@@ -44529,6 +45167,87 @@ var FirehoseProvider = class {
|
|
|
44529
45167
|
}))
|
|
44530
45168
|
}));
|
|
44531
45169
|
}
|
|
45170
|
+
async applyEncryptionUpdate(logicalId, physicalId, resourceType, desired, mask) {
|
|
45171
|
+
const settled = await this.waitForEncryption(logicalId, physicalId, resourceType, mask, {
|
|
45172
|
+
what: "settle",
|
|
45173
|
+
done: (enc) => enc?.Status !== "ENABLING" && enc?.Status !== "DISABLING"
|
|
45174
|
+
});
|
|
45175
|
+
if (desired.kind === "absent") {
|
|
45176
|
+
if (settled?.Status !== "ENABLED" && settled?.Status !== "DISABLING_FAILED") return;
|
|
45177
|
+
this.refuseToStartTransition(logicalId, physicalId, resourceType, "disable");
|
|
45178
|
+
await this.getClient().send(new StopDeliveryStreamEncryptionCommand({ DeliveryStreamName: physicalId }));
|
|
45179
|
+
await this.warnIfUnfinished(logicalId, "StopDeliveryStreamEncryption", () => this.waitForEncryption(logicalId, physicalId, resourceType, mask, {
|
|
45180
|
+
what: "disable",
|
|
45181
|
+
done: (enc) => enc === void 0 || enc.Status === "DISABLED",
|
|
45182
|
+
inProgress: "DISABLING",
|
|
45183
|
+
failed: "DISABLING_FAILED",
|
|
45184
|
+
staleFailure: settled.Status === "DISABLING_FAILED"
|
|
45185
|
+
}));
|
|
45186
|
+
return;
|
|
45187
|
+
}
|
|
45188
|
+
if (encryptionMatches(settled, desired)) return;
|
|
45189
|
+
this.refuseToStartTransition(logicalId, physicalId, resourceType, "enable");
|
|
45190
|
+
await this.getClient().send(new StartDeliveryStreamEncryptionCommand({
|
|
45191
|
+
DeliveryStreamName: physicalId,
|
|
45192
|
+
DeliveryStreamEncryptionConfigurationInput: {
|
|
45193
|
+
KeyType: desired.keyType,
|
|
45194
|
+
...desired.keyArn !== void 0 && { KeyARN: desired.keyArn }
|
|
45195
|
+
}
|
|
45196
|
+
}));
|
|
45197
|
+
await this.warnIfUnfinished(logicalId, "StartDeliveryStreamEncryption", () => this.waitForEncryption(logicalId, physicalId, resourceType, mask, {
|
|
45198
|
+
what: "enable",
|
|
45199
|
+
done: (enc) => encryptionMatches(enc, desired),
|
|
45200
|
+
inProgress: "ENABLING",
|
|
45201
|
+
failed: "ENABLING_FAILED",
|
|
45202
|
+
staleFailure: settled?.Status === "ENABLING_FAILED"
|
|
45203
|
+
}));
|
|
45204
|
+
}
|
|
45205
|
+
async warnIfUnfinished(logicalId, call, wait) {
|
|
45206
|
+
try {
|
|
45207
|
+
return await wait();
|
|
45208
|
+
} catch (error) {
|
|
45209
|
+
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";
|
|
45210
|
+
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.`);
|
|
45211
|
+
throw error;
|
|
45212
|
+
}
|
|
45213
|
+
}
|
|
45214
|
+
refuseToStartTransition(logicalId, physicalId, resourceType, what) {
|
|
45215
|
+
const watch = startInterruptWatch(`Firehose ${logicalId} encryption ${what}`);
|
|
45216
|
+
try {
|
|
45217
|
+
if (watch.isInterrupted()) throw watch.onInterrupted();
|
|
45218
|
+
} finally {
|
|
45219
|
+
watch.dispose();
|
|
45220
|
+
}
|
|
45221
|
+
if (!enclosingDeadlineExpired() && enclosingDeadlineRemainingMs() > 0) return;
|
|
45222
|
+
throw markNonRetryable(new ProvisioningError(`The resource timeout expired before encryption could be ${what}d on Firehose delivery stream ${logicalId}; no encryption call was sent`, resourceType, logicalId, physicalId));
|
|
45223
|
+
}
|
|
45224
|
+
async waitForEncryption(logicalId, physicalId, resourceType, mask, opts) {
|
|
45225
|
+
const { what, done, inProgress, failed } = opts;
|
|
45226
|
+
const watch = startInterruptWatch(`Firehose ${logicalId} encryption ${what}`);
|
|
45227
|
+
try {
|
|
45228
|
+
let last;
|
|
45229
|
+
let sawInProgress = false;
|
|
45230
|
+
for (let attempt = 1; attempt <= ENCRYPTION_POLL_MAX_ATTEMPTS; attempt++) {
|
|
45231
|
+
if (watch.isInterrupted()) throw watch.onInterrupted();
|
|
45232
|
+
if (enclosingDeadlineRemainingMs() <= 0) throw markNonRetryable(new ProvisioningError(`The resource timeout expired while waiting to ${what} encryption on Firehose delivery stream ${logicalId} (last status: ${last ?? "none reported"})`, resourceType, logicalId, physicalId));
|
|
45233
|
+
const enc = (await this.getClient().send(new DescribeDeliveryStreamCommand({ DeliveryStreamName: physicalId }))).DeliveryStreamDescription?.DeliveryStreamEncryptionConfiguration;
|
|
45234
|
+
if (done(enc)) return enc;
|
|
45235
|
+
last = enc?.Status;
|
|
45236
|
+
if (last !== void 0 && last === inProgress) sawInProgress = true;
|
|
45237
|
+
if (failed !== void 0 && last === failed && (sawInProgress || !opts.staleFailure)) {
|
|
45238
|
+
const failure = enc?.FailureDescription;
|
|
45239
|
+
const terminal = markNonRetryable(new ProvisioningError(`Failed to ${what} encryption on Firehose delivery stream ${logicalId}: AWS reports ${failed}` + (failure ? ` (${mask(`${failure.Type ?? ""}: ${failure.Details ?? ""}`)})` : ""), resourceType, logicalId, physicalId));
|
|
45240
|
+
terminalEncryptionFailures.add(terminal);
|
|
45241
|
+
throw terminal;
|
|
45242
|
+
}
|
|
45243
|
+
if (watch.isInterrupted()) throw watch.onInterrupted();
|
|
45244
|
+
await new Promise((resolve) => setTimeout(resolve, Math.max(0, Math.min(ENCRYPTION_POLL_INTERVAL_MS, enclosingDeadlineRemainingMs()))));
|
|
45245
|
+
}
|
|
45246
|
+
throw markNonRetryable(new ProvisioningError(`Timed out waiting to ${what} encryption on Firehose delivery stream ${logicalId} (last status: ${last ?? "none reported"})`, resourceType, logicalId, physicalId));
|
|
45247
|
+
} finally {
|
|
45248
|
+
watch.dispose();
|
|
45249
|
+
}
|
|
45250
|
+
}
|
|
44532
45251
|
findDestinationKey(properties) {
|
|
44533
45252
|
for (const key of [
|
|
44534
45253
|
"ExtendedS3DestinationConfiguration",
|
|
@@ -44934,11 +45653,7 @@ var FirehoseProvider = class {
|
|
|
44934
45653
|
else if (dest?.AmazonOpenSearchServerlessDestinationDescription) result["AmazonOpenSearchServerlessDestinationConfiguration"] = mapNonS3DestinationToCfn(dest.AmazonOpenSearchServerlessDestinationDescription);
|
|
44935
45654
|
else if (dest?.SplunkDestinationDescription) result["SplunkDestinationConfiguration"] = mapNonS3DestinationToCfn(dest.SplunkDestinationDescription);
|
|
44936
45655
|
else if (dest?.HttpEndpointDestinationDescription) result["HttpEndpointDestinationConfiguration"] = mapHttpEndpointDescriptionToCfn(dest.HttpEndpointDestinationDescription);
|
|
44937
|
-
|
|
44938
|
-
const encOut = {};
|
|
44939
|
-
if (enc?.KeyARN !== void 0) encOut["KeyARN"] = enc.KeyARN;
|
|
44940
|
-
if (enc?.KeyType !== void 0) encOut["KeyType"] = enc.KeyType;
|
|
44941
|
-
result["DeliveryStreamEncryptionConfigurationInput"] = encOut;
|
|
45656
|
+
result["DeliveryStreamEncryptionConfigurationInput"] = liveEncryptionAsCfn(desc.DeliveryStreamEncryptionConfiguration);
|
|
44942
45657
|
try {
|
|
44943
45658
|
const tagsResp = await this.getClient().send(new ListTagsForDeliveryStreamCommand({ DeliveryStreamName: physicalId }));
|
|
44944
45659
|
result["Tags"] = normalizeAwsTagsToCfn(tagsResp.Tags);
|
|
@@ -45456,6 +46171,22 @@ var CloudTrailProvider = class {
|
|
|
45456
46171
|
|
|
45457
46172
|
//#endregion
|
|
45458
46173
|
//#region src/provisioning/providers/codebuild-provider.ts
|
|
46174
|
+
const DEFAULT_PROJECT_VISIBILITY = "PRIVATE";
|
|
46175
|
+
function readVisibility(properties, mask) {
|
|
46176
|
+
const visibility = properties["Visibility"];
|
|
46177
|
+
const role = properties["ResourceAccessRole"];
|
|
46178
|
+
const refuse = (key, value) => ({
|
|
46179
|
+
kind: "unusable",
|
|
46180
|
+
reason: `AWS::CodeBuild::Project ${key} must be a non-empty string, got ${JSON.stringify(maskDeep(value, mask))}`
|
|
46181
|
+
});
|
|
46182
|
+
if (visibility != null && (typeof visibility !== "string" || visibility.trim() === "")) return refuse("Visibility", visibility);
|
|
46183
|
+
if (role != null && (typeof role !== "string" || role !== "" && role.trim() === "")) return refuse("ResourceAccessRole", role);
|
|
46184
|
+
return {
|
|
46185
|
+
kind: "usable",
|
|
46186
|
+
visibility: visibility ?? DEFAULT_PROJECT_VISIBILITY,
|
|
46187
|
+
...typeof role === "string" && role !== "" && { resourceAccessRole: role }
|
|
46188
|
+
};
|
|
46189
|
+
}
|
|
45459
46190
|
var CodeBuildProvider = class {
|
|
45460
46191
|
client;
|
|
45461
46192
|
createClient;
|
|
@@ -45484,7 +46215,9 @@ var CodeBuildProvider = class {
|
|
|
45484
46215
|
"BuildBatchConfig",
|
|
45485
46216
|
"BadgeEnabled",
|
|
45486
46217
|
"SourceVersion",
|
|
45487
|
-
"AutoRetryLimit"
|
|
46218
|
+
"AutoRetryLimit",
|
|
46219
|
+
"Visibility",
|
|
46220
|
+
"ResourceAccessRole"
|
|
45488
46221
|
])]]);
|
|
45489
46222
|
getClient() {
|
|
45490
46223
|
if (!this.client) {
|
|
@@ -45675,29 +46408,59 @@ var CodeBuildProvider = class {
|
|
|
45675
46408
|
}
|
|
45676
46409
|
async create(logicalId, resourceType, properties, context) {
|
|
45677
46410
|
this.logger.debug(`Creating CodeBuild Project ${logicalId}`);
|
|
46411
|
+
const mask = maskerOrIdentity(context?.maskSecrets);
|
|
46412
|
+
const visibilityRead = readVisibility(properties, mask);
|
|
46413
|
+
if (visibilityRead.kind === "unusable") {
|
|
46414
|
+
if (context?.replayingState !== true) throw new ProvisioningError(visibilityRead.reason, resourceType, logicalId);
|
|
46415
|
+
this.logger.warn(mask(`${visibilityRead.reason}. Replaying a state record, so CodeBuild Project ${logicalId} is left ${DEFAULT_PROJECT_VISIBILITY} with no resource access role rather than refusing the restore`));
|
|
46416
|
+
}
|
|
46417
|
+
let createdName;
|
|
45678
46418
|
try {
|
|
45679
46419
|
const input = this.mapProperties(() => generatedNameFor("AWS::CodeBuild::Project", logicalId), properties);
|
|
45680
46420
|
const result = await this.getCreateClient().send(new CreateProjectCommand(input));
|
|
45681
46421
|
const projectName = result.project.name;
|
|
45682
46422
|
const projectArn = result.project.arn;
|
|
46423
|
+
createdName = projectName;
|
|
46424
|
+
if (visibilityRead.kind === "usable" && (visibilityRead.visibility !== DEFAULT_PROJECT_VISIBILITY || visibilityRead.resourceAccessRole !== void 0)) await this.applyVisibility(projectArn, visibilityRead);
|
|
45683
46425
|
this.logger.debug(`Successfully created CodeBuild Project ${logicalId}: ${projectName}`);
|
|
45684
46426
|
return {
|
|
45685
46427
|
physicalId: projectName,
|
|
45686
46428
|
attributes: { Arn: projectArn }
|
|
45687
46429
|
};
|
|
45688
46430
|
} catch (error) {
|
|
46431
|
+
if (createdName !== void 0) markAuxiliaryFailure(error, logicalId);
|
|
45689
46432
|
const cause = error instanceof Error ? error : void 0;
|
|
45690
|
-
|
|
46433
|
+
const thrown = this.wrapCaughtError(mask, error, (text) => new ProvisioningError(`Failed to create CodeBuild Project ${logicalId}: ${text}`, resourceType, logicalId, void 0, cause));
|
|
46434
|
+
if (createdName !== void 0) markCreatedBeforeFailure(thrown, logicalId, resourceType, createdName);
|
|
46435
|
+
throw thrown;
|
|
45691
46436
|
}
|
|
45692
46437
|
}
|
|
46438
|
+
async applyVisibility(projectArn, read) {
|
|
46439
|
+
await this.getClient().send(new UpdateProjectVisibilityCommand({
|
|
46440
|
+
projectArn,
|
|
46441
|
+
projectVisibility: read.visibility,
|
|
46442
|
+
...read.resourceAccessRole !== void 0 && { resourceAccessRole: read.resourceAccessRole }
|
|
46443
|
+
}));
|
|
46444
|
+
}
|
|
45693
46445
|
async update(logicalId, physicalId, resourceType, properties, previousProperties, context) {
|
|
45694
46446
|
this.logger.debug(`Updating CodeBuild Project ${logicalId}: ${physicalId}`);
|
|
46447
|
+
const mask = maskerOrIdentity(context?.maskSecrets);
|
|
45695
46448
|
assertRegionMatch(context?.expectedRegion ? await this.getClient().config.region() : void 0, context?.expectedRegion, resourceType, logicalId, physicalId, "pre-update");
|
|
45696
46449
|
try {
|
|
45697
46450
|
const input = this.mapProperties(() => physicalId, properties);
|
|
45698
46451
|
input.name = physicalId;
|
|
45699
46452
|
if (properties["BuildBatchConfig"] == null && previousProperties["BuildBatchConfig"] != null) input.buildBatchConfig = {};
|
|
45700
|
-
await this.getClient().send(new UpdateProjectCommand(input));
|
|
46453
|
+
const updated = await this.getClient().send(new UpdateProjectCommand(input));
|
|
46454
|
+
const desiredVisibility = readVisibility(properties, mask);
|
|
46455
|
+
const recorded = readVisibility(previousProperties, mask);
|
|
46456
|
+
if (desiredVisibility.kind === "unusable") {
|
|
46457
|
+
const kept = recorded.kind === "usable" ? ` (recorded ${recorded.visibility})` : "";
|
|
46458
|
+
this.logger.warn(mask(`${desiredVisibility.reason}. Leaving the visibility of CodeBuild Project ${physicalId} unchanged${kept}; the same value is REFUSED on a template-path create`));
|
|
46459
|
+
} else if (recorded.kind !== "usable" || recorded.visibility !== desiredVisibility.visibility || recorded.resourceAccessRole !== desiredVisibility.resourceAccessRole) {
|
|
46460
|
+
const projectArn = updated.project?.arn;
|
|
46461
|
+
if (projectArn === void 0) throw new Error("UpdateProject returned no project ARN for the visibility update");
|
|
46462
|
+
await this.applyVisibility(projectArn, desiredVisibility);
|
|
46463
|
+
}
|
|
45701
46464
|
this.logger.debug(`Successfully updated CodeBuild Project ${logicalId}`);
|
|
45702
46465
|
return {
|
|
45703
46466
|
physicalId,
|
|
@@ -45705,7 +46468,7 @@ var CodeBuildProvider = class {
|
|
|
45705
46468
|
};
|
|
45706
46469
|
} catch (error) {
|
|
45707
46470
|
const cause = error instanceof Error ? error : void 0;
|
|
45708
|
-
throw this.wrapCaughtError(
|
|
46471
|
+
throw this.wrapCaughtError(mask, error, (text) => new ProvisioningError(`Failed to update CodeBuild Project ${logicalId}: ${text}`, resourceType, logicalId, physicalId, cause));
|
|
45709
46472
|
}
|
|
45710
46473
|
}
|
|
45711
46474
|
wrapCaughtError(mask, error, build) {
|
|
@@ -45902,6 +46665,7 @@ var CodeBuildProvider = class {
|
|
|
45902
46665
|
result["BuildBatchConfig"] = bbc;
|
|
45903
46666
|
} else result["BuildBatchConfig"] = {};
|
|
45904
46667
|
result["ResourceAccessRole"] = project.resourceAccessRole ?? "";
|
|
46668
|
+
if (project.projectVisibility !== void 0) result["Visibility"] = project.projectVisibility;
|
|
45905
46669
|
result["Tags"] = normalizeAwsTagsToCfn(project.tags);
|
|
45906
46670
|
return result;
|
|
45907
46671
|
}
|
|
@@ -47310,16 +48074,32 @@ var S3TablesProvider = class {
|
|
|
47310
48074
|
assertRegionMatch(context?.expectedRegion ? await this.getClient().config.region() : void 0, context?.expectedRegion, resourceType, logicalId, physicalId, "pre-update");
|
|
47311
48075
|
if (resourceType === "AWS::S3Tables::Table" || resourceType === "AWS::S3Tables::TableBucket") refuseMalformedDesiredTags(properties["Tags"], resourceType, logicalId, physicalId);
|
|
47312
48076
|
try {
|
|
47313
|
-
return await this.applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, context?.maskSecrets);
|
|
48077
|
+
return await this.applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, context?.maskSecrets, context?.recordedAttributes);
|
|
47314
48078
|
} catch (error) {
|
|
47315
48079
|
if (error instanceof CdkdError) throw error;
|
|
47316
48080
|
const cause = error instanceof Error ? error : void 0;
|
|
47317
48081
|
throw this.wrapCaughtError(context?.maskSecrets, error, (text) => new ProvisioningError(`Failed to update S3 Tables resource ${logicalId}: ${text}`, resourceType, logicalId, physicalId, cause));
|
|
47318
48082
|
}
|
|
47319
48083
|
}
|
|
47320
|
-
async applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, mask) {
|
|
47321
|
-
if (resourceType === "AWS::S3Tables::Table")
|
|
47322
|
-
|
|
48084
|
+
async applyUpdate(logicalId, physicalId, resourceType, properties, previousProperties, mask, recordedAttributes) {
|
|
48085
|
+
if (resourceType === "AWS::S3Tables::Table") {
|
|
48086
|
+
const rename = await this.planTableRename(logicalId, physicalId, resourceType, properties, mask);
|
|
48087
|
+
await this.applyTableTagsDiff(logicalId, physicalId, resourceType, previousProperties["Tags"], properties["Tags"], mask);
|
|
48088
|
+
if (rename === void 0) return {
|
|
48089
|
+
physicalId,
|
|
48090
|
+
wasReplaced: false
|
|
48091
|
+
};
|
|
48092
|
+
try {
|
|
48093
|
+
await this.getClient().send(rename.command);
|
|
48094
|
+
} catch (error) {
|
|
48095
|
+
if (!(error instanceof NotFoundException$7) || !await this.renameAlreadyApplied(rename.target, recordedAttributes)) throw error;
|
|
48096
|
+
}
|
|
48097
|
+
this.logger.debug(safeMsg`Renamed S3 Tables Table ${logicalId}: ${physicalId} -> ${rename.physicalId}`);
|
|
48098
|
+
return {
|
|
48099
|
+
physicalId: rename.physicalId,
|
|
48100
|
+
wasReplaced: false
|
|
48101
|
+
};
|
|
48102
|
+
} else if (resourceType === "AWS::S3Tables::TableBucket") await this.applyTableBucketTagsDiff(logicalId, physicalId, resourceType, previousProperties["Tags"], properties["Tags"], mask);
|
|
47323
48103
|
else this.logger.debug(`Update is no-op for ${resourceType} ${logicalId}`);
|
|
47324
48104
|
return {
|
|
47325
48105
|
physicalId,
|
|
@@ -47822,6 +48602,59 @@ var S3TablesProvider = class {
|
|
|
47822
48602
|
for (const t of tags) map[t.Key] = t.Value;
|
|
47823
48603
|
return map;
|
|
47824
48604
|
}
|
|
48605
|
+
async planTableRename(logicalId, physicalId, resourceType, properties, mask) {
|
|
48606
|
+
const desiredString = (key, value) => {
|
|
48607
|
+
if (value === void 0) return void 0;
|
|
48608
|
+
if (typeof value === "string" && value.length > 0) return value;
|
|
48609
|
+
throw new ProvisioningError(safeMsg`${key} for S3 Tables Table ${logicalId} must be a non-empty string; refusing the update`, resourceType, logicalId, physicalId);
|
|
48610
|
+
};
|
|
48611
|
+
const desiredNamespace = desiredString("Namespace", properties["Namespace"]);
|
|
48612
|
+
const desiredName = desiredString("TableName", properties["TableName"] ?? properties["Name"]);
|
|
48613
|
+
if (desiredNamespace === void 0 && desiredName === void 0) return void 0;
|
|
48614
|
+
const current = await this.resolveTableParts(physicalId);
|
|
48615
|
+
if (current === "not-found" || current === "unparseable") throw new ProvisioningError(current === "not-found" ? safeMsg`S3 Tables Table '${physicalId}' no longer exists (state is out of sync); ` + `refusing to record a rename that did not happen` : compositeIdFormatMessage(S3_TABLES_TABLE_ID_FORMAT, logicalId, physicalId), resourceType, logicalId, physicalId);
|
|
48616
|
+
const newNamespace = desiredNamespace ?? current.namespace;
|
|
48617
|
+
const newName = desiredName ?? current.name;
|
|
48618
|
+
if (newNamespace === current.namespace && newName === current.name) return void 0;
|
|
48619
|
+
return {
|
|
48620
|
+
physicalId: physicalId.includes("|") ? packCompositeId(resourceType, logicalId, [
|
|
48621
|
+
{
|
|
48622
|
+
name: "tableBucketARN",
|
|
48623
|
+
value: current.tableBucketARN
|
|
48624
|
+
},
|
|
48625
|
+
{
|
|
48626
|
+
name: "namespace",
|
|
48627
|
+
value: newNamespace
|
|
48628
|
+
},
|
|
48629
|
+
{
|
|
48630
|
+
name: "name",
|
|
48631
|
+
value: newName
|
|
48632
|
+
}
|
|
48633
|
+
], { maskSecrets: mask }) : physicalId,
|
|
48634
|
+
target: {
|
|
48635
|
+
tableBucketARN: current.tableBucketARN,
|
|
48636
|
+
namespace: newNamespace,
|
|
48637
|
+
name: newName
|
|
48638
|
+
},
|
|
48639
|
+
command: new RenameTableCommand({
|
|
48640
|
+
tableBucketARN: current.tableBucketARN,
|
|
48641
|
+
namespace: current.namespace,
|
|
48642
|
+
name: current.name,
|
|
48643
|
+
...newNamespace !== current.namespace && { newNamespaceName: newNamespace },
|
|
48644
|
+
...newName !== current.name && { newName }
|
|
48645
|
+
})
|
|
48646
|
+
};
|
|
48647
|
+
}
|
|
48648
|
+
async renameAlreadyApplied(target, recordedAttributes) {
|
|
48649
|
+
const recordedArn = recordedAttributes?.["TableARN"];
|
|
48650
|
+
if (typeof recordedArn !== "string" || recordedArn.length === 0) return false;
|
|
48651
|
+
try {
|
|
48652
|
+
return await this.lookupTableArn(target.tableBucketARN, target.namespace, target.name) === recordedArn;
|
|
48653
|
+
} catch (lookupError) {
|
|
48654
|
+
this.logger.debug(safeMsg`Could not check whether the rename of ${target.name} was already applied: ${describeAwsFailure(lookupError).summary}`);
|
|
48655
|
+
return false;
|
|
48656
|
+
}
|
|
48657
|
+
}
|
|
47825
48658
|
async lookupTableArn(tableBucketARN, namespace, name) {
|
|
47826
48659
|
try {
|
|
47827
48660
|
return (await this.getClient().send(new GetTableCommand$1({
|
|
@@ -49018,4 +49851,4 @@ var ACMCertificateProvider = class {
|
|
|
49018
49851
|
|
|
49019
49852
|
//#endregion
|
|
49020
49853
|
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 };
|
|
49021
|
-
//# sourceMappingURL=provider-classes-
|
|
49854
|
+
//# sourceMappingURL=provider-classes-CPMW_2-R.js.map
|