@go-to-k/cdkd 0.106.0 → 0.108.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/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { a as setAwsClients, i as resetAwsClients, r as getAwsClients, t as AwsClients } from "./aws-clients-CuHRHcyW.js";
|
|
3
|
-
import { A as resolveApp, B as CdkdError, C as AssetPublisher, D as Synthesizer, E as buildDockerImage, F as warnDeprecatedNoPrefixCliFlag, G as PartialFailureError, I as AssemblyReader, J as ResourceUpdateNotSupportedError, K as ProvisioningError, M as resolveSkipPrefix, N as resolveStateBucketWithDefault, O as getDefaultStateBucketName, P as resolveStateBucketWithDefaultAndSource, R as resolveBucketRegion, S as shouldRetainResource, T as WorkGraph, U as LocalInvokeBuildError, X as StackHasActiveImportsError, Y as RouteDiscoveryError, Z as StackTerminationProtectionError, _ as DiffCalculator, a as withRetry, at as getLogger, b as LockManager, c as collectInlinePolicyNamesManagedBySiblings, ct as getLiveRenderer, d as normalizeAwsTagsToCfn, dt as generateResourceName, f as resolveExplicitPhysicalId, ft as generateResourceNameWithFallback, g as IntrinsicFunctionResolver, h as assertRegionMatch, i as withResourceDeadline, j as resolveCaptureObservedState, k as getLegacyStateBucketName, l as CDK_PATH_TAG, lt as PATTERN_B_NAME_PROPERTIES, m as CloudControlProvider, mt as withStackName, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as normalizeAwsError, o as IMPLICIT_DELETE_DEPENDENCIES, p as ProviderRegistry, pt as withSkipPrefix, q as ResourceTimeoutError, r as DeployEngine, rt as withErrorHandling, s as IAMRoleProvider, st as runStackBuffered, t as DEFAULT_RESOURCE_TIMEOUT_MS, u as matchesCdkPath, ut as PATTERN_B_RESOURCE_TYPES, v as DagBuilder, w as stringifyValue, x as S3StateBackend, y as TemplateParser } from "./deploy-engine-
|
|
3
|
+
import { A as resolveApp, B as CdkdError, C as AssetPublisher, D as Synthesizer, E as buildDockerImage, F as warnDeprecatedNoPrefixCliFlag, G as PartialFailureError, I as AssemblyReader, J as ResourceUpdateNotSupportedError, K as ProvisioningError, M as resolveSkipPrefix, N as resolveStateBucketWithDefault, O as getDefaultStateBucketName, P as resolveStateBucketWithDefaultAndSource, R as resolveBucketRegion, S as shouldRetainResource, T as WorkGraph, U as LocalInvokeBuildError, X as StackHasActiveImportsError, Y as RouteDiscoveryError, Z as StackTerminationProtectionError, _ as DiffCalculator, a as withRetry, at as getLogger, b as LockManager, c as collectInlinePolicyNamesManagedBySiblings, ct as getLiveRenderer, d as normalizeAwsTagsToCfn, dt as generateResourceName, f as resolveExplicitPhysicalId, ft as generateResourceNameWithFallback, g as IntrinsicFunctionResolver, h as assertRegionMatch, i as withResourceDeadline, j as resolveCaptureObservedState, k as getLegacyStateBucketName, l as CDK_PATH_TAG, lt as PATTERN_B_NAME_PROPERTIES, m as CloudControlProvider, mt as withStackName, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nt as normalizeAwsError, o as IMPLICIT_DELETE_DEPENDENCIES, p as ProviderRegistry, pt as withSkipPrefix, q as ResourceTimeoutError, r as DeployEngine, rt as withErrorHandling, s as IAMRoleProvider, st as runStackBuffered, t as DEFAULT_RESOURCE_TIMEOUT_MS, u as matchesCdkPath, ut as PATTERN_B_RESOURCE_TYPES, v as DagBuilder, w as stringifyValue, x as S3StateBackend, y as TemplateParser } from "./deploy-engine-Br8DvrvB.js";
|
|
4
4
|
import { createHash, createPublicKey, createVerify, randomBytes, randomUUID } from "node:crypto";
|
|
5
5
|
import { CopyObjectCommand, CreateBucketCommand, DeleteBucketAnalyticsConfigurationCommand, DeleteBucketCommand, DeleteBucketCorsCommand, DeleteBucketIntelligentTieringConfigurationCommand, DeleteBucketInventoryConfigurationCommand, DeleteBucketLifecycleCommand, DeleteBucketMetricsConfigurationCommand, DeleteBucketPolicyCommand, DeleteBucketReplicationCommand, DeleteBucketTaggingCommand, DeleteBucketWebsiteCommand, DeleteObjectCommand, DeleteObjectsCommand, GetBucketAccelerateConfigurationCommand, GetBucketCorsCommand, GetBucketEncryptionCommand, GetBucketLifecycleConfigurationCommand, GetBucketLocationCommand, GetBucketLoggingCommand, GetBucketNotificationConfigurationCommand, GetBucketPolicyCommand, GetBucketReplicationCommand, GetBucketTaggingCommand, GetBucketVersioningCommand, GetBucketWebsiteCommand, GetObjectCommand, GetObjectLockConfigurationCommand, GetPublicAccessBlockCommand, HeadBucketCommand, ListBucketAnalyticsConfigurationsCommand, ListBucketIntelligentTieringConfigurationsCommand, ListBucketInventoryConfigurationsCommand, ListBucketMetricsConfigurationsCommand, ListBucketsCommand, ListDirectoryBucketsCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchBucket, PutBucketAccelerateConfigurationCommand, PutBucketAnalyticsConfigurationCommand, PutBucketCorsCommand, PutBucketEncryptionCommand, PutBucketIntelligentTieringConfigurationCommand, PutBucketInventoryConfigurationCommand, PutBucketLifecycleConfigurationCommand, PutBucketLoggingCommand, PutBucketMetricsConfigurationCommand, PutBucketNotificationConfigurationCommand, PutBucketOwnershipControlsCommand, PutBucketPolicyCommand, PutBucketReplicationCommand, PutBucketTaggingCommand, PutBucketVersioningCommand, PutBucketWebsiteCommand, PutObjectCommand, PutObjectLockConfigurationCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
|
|
6
6
|
import { AddRoleToInstanceProfileCommand, AddUserToGroupCommand, AttachGroupPolicyCommand, AttachUserPolicyCommand, CreateGroupCommand, CreateInstanceProfileCommand, CreateLoginProfileCommand, CreateUserCommand, DeleteAccessKeyCommand, DeleteGroupCommand, DeleteGroupPolicyCommand, DeleteInstanceProfileCommand, DeleteLoginProfileCommand, DeleteRolePolicyCommand, DeleteUserCommand, DeleteUserPermissionsBoundaryCommand, DeleteUserPolicyCommand, DetachGroupPolicyCommand, DetachUserPolicyCommand, GetGroupCommand, GetGroupPolicyCommand, GetInstanceProfileCommand, GetRolePolicyCommand, GetUserCommand, GetUserPolicyCommand, IAMClient, ListAccessKeysCommand, ListAttachedGroupPoliciesCommand, ListAttachedUserPoliciesCommand, ListGroupPoliciesCommand, ListGroupsForUserCommand, ListInstanceProfilesCommand, ListUserPoliciesCommand, ListUserTagsCommand, ListUsersCommand, NoSuchEntityException, PutGroupPolicyCommand, PutRolePolicyCommand, PutUserPermissionsBoundaryCommand, PutUserPolicyCommand, RemoveRoleFromInstanceProfileCommand, RemoveUserFromGroupCommand, TagUserCommand, UntagUserCommand, UpdateLoginProfileCommand } from "@aws-sdk/client-iam";
|
|
@@ -30,12 +30,12 @@ import { CreateAliasCommand, CreateKeyCommand, DeleteAliasCommand, DescribeKeyCo
|
|
|
30
30
|
import { promisify } from "node:util";
|
|
31
31
|
import { CreateRepositoryCommand, DeleteLifecyclePolicyCommand, DeleteRepositoryCommand, DeleteRepositoryPolicyCommand, DescribeRepositoriesCommand, ECRClient, GetAuthorizationTokenCommand, GetLifecyclePolicyCommand, LifecyclePolicyNotFoundException, ListTagsForResourceCommand as ListTagsForResourceCommand$7, PutImageScanningConfigurationCommand, PutImageTagMutabilityCommand, PutLifecyclePolicyCommand, RepositoryNotFoundException, SetRepositoryPolicyCommand, TagResourceCommand as TagResourceCommand$9 } from "@aws-sdk/client-ecr";
|
|
32
32
|
import graphlib from "graphlib";
|
|
33
|
-
import { AddTagsToResourceCommand as AddTagsToResourceCommand$1, CreateDBClusterCommand, CreateDBInstanceCommand, CreateDBProxyCommand, CreateDBSubnetGroupCommand, DBProxyNotFoundFault, DBProxyTargetGroupNotFoundFault, DBProxyTargetNotFoundFault, DeleteDBClusterCommand, DeleteDBInstanceCommand, DeleteDBProxyCommand, DeleteDBSubnetGroupCommand, DeregisterDBProxyTargetsCommand, DescribeDBClustersCommand, DescribeDBInstancesCommand, DescribeDBProxiesCommand, DescribeDBProxyTargetGroupsCommand, DescribeDBSubnetGroupsCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$8, ModifyDBClusterCommand, ModifyDBInstanceCommand, ModifyDBProxyCommand, ModifyDBProxyTargetGroupCommand, ModifyDBSubnetGroupCommand, RDSClient, RegisterDBProxyTargetsCommand, RemoveTagsFromResourceCommand as RemoveTagsFromResourceCommand$1 } from "@aws-sdk/client-rds";
|
|
33
|
+
import { AddTagsToResourceCommand as AddTagsToResourceCommand$1, CreateDBClusterCommand, CreateDBInstanceCommand, CreateDBProxyCommand, CreateDBProxyEndpointCommand, CreateDBSubnetGroupCommand, DBProxyEndpointNotFoundFault, DBProxyNotFoundFault, DBProxyTargetGroupNotFoundFault, DBProxyTargetNotFoundFault, DeleteDBClusterCommand, DeleteDBInstanceCommand, DeleteDBProxyCommand, DeleteDBProxyEndpointCommand, DeleteDBSubnetGroupCommand, DeregisterDBProxyTargetsCommand, DescribeDBClustersCommand, DescribeDBInstancesCommand, DescribeDBProxiesCommand, DescribeDBProxyEndpointsCommand, DescribeDBProxyTargetGroupsCommand, DescribeDBSubnetGroupsCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$8, ModifyDBClusterCommand, ModifyDBInstanceCommand, ModifyDBProxyCommand, ModifyDBProxyEndpointCommand, ModifyDBProxyTargetGroupCommand, ModifyDBSubnetGroupCommand, RDSClient, RegisterDBProxyTargetsCommand, RemoveTagsFromResourceCommand as RemoveTagsFromResourceCommand$1 } from "@aws-sdk/client-rds";
|
|
34
34
|
import { Command, Option } from "commander";
|
|
35
35
|
import { writeFileSync as writeFileSync$1 } from "fs";
|
|
36
36
|
import { join as join$1 } from "path";
|
|
37
37
|
import * as zlib from "node:zlib";
|
|
38
|
-
import { ApplicationAutoScalingClient, DescribeScalingPoliciesCommand } from "@aws-sdk/client-application-auto-scaling";
|
|
38
|
+
import { ApplicationAutoScalingClient, DescribeScalableTargetsCommand, DescribeScalingPoliciesCommand } from "@aws-sdk/client-application-auto-scaling";
|
|
39
39
|
import { ApiGatewayV2Client, CreateApiCommand, CreateAuthorizerCommand as CreateAuthorizerCommand$1, CreateIntegrationCommand, CreateRouteCommand as CreateRouteCommand$1, CreateStageCommand as CreateStageCommand$1, DeleteApiCommand, DeleteAuthorizerCommand as DeleteAuthorizerCommand$1, DeleteIntegrationCommand, DeleteRouteCommand as DeleteRouteCommand$1, DeleteStageCommand as DeleteStageCommand$1, GetApiCommand, GetApisCommand, GetAuthorizerCommand as GetAuthorizerCommand$1, GetIntegrationCommand, GetRouteCommand, GetStageCommand as GetStageCommand$1, NotFoundException as NotFoundException$3, UpdateApiCommand, UpdateAuthorizerCommand as UpdateAuthorizerCommand$1, UpdateIntegrationCommand, UpdateRouteCommand, UpdateStageCommand as UpdateStageCommand$1 } from "@aws-sdk/client-apigatewayv2";
|
|
40
40
|
import { CreateStateMachineCommand, DeleteStateMachineCommand, DescribeStateMachineCommand, ListStateMachinesCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$9, SFNClient, StateMachineDoesNotExist, TagResourceCommand as TagResourceCommand$10, UntagResourceCommand as UntagResourceCommand$9, UpdateStateMachineCommand } from "@aws-sdk/client-sfn";
|
|
41
41
|
import { CreateClusterCommand, CreateServiceCommand, DeleteClusterCommand, DeleteServiceCommand, DeregisterTaskDefinitionCommand, DescribeClustersCommand, DescribeServicesCommand, DescribeTaskDefinitionCommand, ECSClient, ListClustersCommand, ListServicesCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$10, PutClusterCapacityProvidersCommand, RegisterTaskDefinitionCommand, TagResourceCommand as TagResourceCommand$11, UntagResourceCommand as UntagResourceCommand$10, UpdateClusterCommand, UpdateServiceCommand } from "@aws-sdk/client-ecs";
|
|
@@ -7899,6 +7899,18 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
7899
7899
|
*/
|
|
7900
7900
|
regionalClientCache = /* @__PURE__ */ new Map();
|
|
7901
7901
|
/**
|
|
7902
|
+
* Caches per-region `ApplicationAutoScalingClient` instances for
|
|
7903
|
+
* per-replica `ReadCapacityAutoScalingSettings` reverse-mapping in
|
|
7904
|
+
* `readCurrentState`. Same lifetime / shape as `regionalClientCache`
|
|
7905
|
+
* — one per region for the duration of the provider instance.
|
|
7906
|
+
*
|
|
7907
|
+
* Issue #395: per-replica read capacity autoscaling lives in the
|
|
7908
|
+
* replica's region (each replica has its own scaling target +
|
|
7909
|
+
* policy registered against `application-autoscaling` in that
|
|
7910
|
+
* region), so we cannot reuse the local-region client.
|
|
7911
|
+
*/
|
|
7912
|
+
regionalAutoScalingClientCache = /* @__PURE__ */ new Map();
|
|
7913
|
+
/**
|
|
7902
7914
|
* Caches `getAttribute(physicalId, attribute)` results for the lifetime
|
|
7903
7915
|
* of this provider instance (one deploy run). Safe under the current
|
|
7904
7916
|
* `update()` contract because `update()` cannot mid-deploy mutate
|
|
@@ -7954,6 +7966,24 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
7954
7966
|
return client;
|
|
7955
7967
|
}
|
|
7956
7968
|
/**
|
|
7969
|
+
* Return an `ApplicationAutoScalingClient` pinned to the given region,
|
|
7970
|
+
* caching per region for the lifetime of this provider instance. Mirrors
|
|
7971
|
+
* `getRegionalClient` but for the application-autoscaling service.
|
|
7972
|
+
*
|
|
7973
|
+
* Used by `readAutoScalingSettings` (Issue #395) to recover per-replica
|
|
7974
|
+
* `ReadCapacityAutoScalingSettings` shapes — each cross-region replica's
|
|
7975
|
+
* scaling target + policy are registered with the autoscaling control
|
|
7976
|
+
* plane in the replica's region, so cross-region drift reads need a
|
|
7977
|
+
* region-scoped client.
|
|
7978
|
+
*/
|
|
7979
|
+
getRegionalAutoScalingClient(region) {
|
|
7980
|
+
const cached = this.regionalAutoScalingClientCache.get(region);
|
|
7981
|
+
if (cached) return cached;
|
|
7982
|
+
const client = new ApplicationAutoScalingClient({ region });
|
|
7983
|
+
this.regionalAutoScalingClientCache.set(region, client);
|
|
7984
|
+
return client;
|
|
7985
|
+
}
|
|
7986
|
+
/**
|
|
7957
7987
|
* Construct the regional table ARN for a cross-region replica of a
|
|
7958
7988
|
* GlobalTable. AWS replicates the same `TableName` across every
|
|
7959
7989
|
* replica region, with each replica's ARN differing only in the
|
|
@@ -8493,13 +8523,17 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
8493
8523
|
* - StreamSpecification / SSESpecification follow the existing
|
|
8494
8524
|
* DynamoDB::Table provider's Class 1 guard: only surfaced when AWS
|
|
8495
8525
|
* reports the feature actually enabled.
|
|
8496
|
-
* - `
|
|
8497
|
-
* `
|
|
8498
|
-
*
|
|
8499
|
-
*
|
|
8500
|
-
* `
|
|
8501
|
-
* `
|
|
8502
|
-
*
|
|
8526
|
+
* - `WriteProvisionedThroughputSettings` reverse-maps both shapes:
|
|
8527
|
+
* flat `{WriteCapacityUnits}` (no autoscaling) and full
|
|
8528
|
+
* `{WriteCapacityAutoScalingSettings}` (Issue #395; recovered from
|
|
8529
|
+
* application-autoscaling's `DescribeScalableTargets` +
|
|
8530
|
+
* `DescribeScalingPolicies` for the
|
|
8531
|
+
* `dynamodb:table:WriteCapacityUnits` dimension).
|
|
8532
|
+
* - Per-replica `ReadProvisionedThroughputSettings` reverse-maps the
|
|
8533
|
+
* `{ReadCapacityAutoScalingSettings}` shape only — there is no
|
|
8534
|
+
* per-replica flat read capacity in `DescribeTable`'s response
|
|
8535
|
+
* (the local `ProvisionedThroughput` block is table-level, not
|
|
8536
|
+
* replica-level), so non-autoscaled replicas omit the key.
|
|
8503
8537
|
*
|
|
8504
8538
|
* Per-replica sub-specifications (`ContributorInsightsSpecification` /
|
|
8505
8539
|
* `PointInTimeRecoverySpecification` / `KinesisStreamSpecification`)
|
|
@@ -8555,15 +8589,23 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
8555
8589
|
}
|
|
8556
8590
|
}
|
|
8557
8591
|
else entry["Tags"] = [];
|
|
8592
|
+
if (billingMode === "PROVISIONED") {
|
|
8593
|
+
const replicaAutoScalingClient = isLocal ? void 0 : this.getRegionalAutoScalingClient(regionLabel);
|
|
8594
|
+
const readAutoScaling = await this.readAutoScalingSettings(tableNameForSubs, "dynamodb:table:ReadCapacityUnits", replicaAutoScalingClient);
|
|
8595
|
+
if (readAutoScaling) entry["ReadProvisionedThroughputSettings"] = { ReadCapacityAutoScalingSettings: readAutoScaling };
|
|
8596
|
+
}
|
|
8558
8597
|
return entry;
|
|
8559
8598
|
}));
|
|
8560
8599
|
if (table.OnDemandThroughput?.MaxWriteRequestUnits !== void 0) result["WriteOnDemandThroughputSettings"] = { MaxWriteRequestUnits: table.OnDemandThroughput.MaxWriteRequestUnits };
|
|
8561
8600
|
else result["WriteOnDemandThroughputSettings"] = {};
|
|
8562
8601
|
if (billingMode === "PROVISIONED") {
|
|
8563
|
-
const
|
|
8564
|
-
if (
|
|
8565
|
-
else
|
|
8566
|
-
|
|
8602
|
+
const autoScaling = await this.readAutoScalingSettings(tableNameForSubs, "dynamodb:table:WriteCapacityUnits");
|
|
8603
|
+
if (autoScaling) result["WriteProvisionedThroughputSettings"] = { WriteCapacityAutoScalingSettings: autoScaling };
|
|
8604
|
+
else {
|
|
8605
|
+
const writeCapacity = table.ProvisionedThroughput?.WriteCapacityUnits;
|
|
8606
|
+
if (writeCapacity !== void 0) result["WriteProvisionedThroughputSettings"] = { WriteCapacityUnits: writeCapacity };
|
|
8607
|
+
else result["WriteProvisionedThroughputSettings"] = {};
|
|
8608
|
+
}
|
|
8567
8609
|
} else result["WriteProvisionedThroughputSettings"] = {};
|
|
8568
8610
|
try {
|
|
8569
8611
|
const ttlDesc = (await this.dynamoDBClient.send(new DescribeTimeToLiveCommand({ TableName: tableNameForSubs }))).TimeToLiveDescription;
|
|
@@ -8629,29 +8671,90 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
8629
8671
|
return out;
|
|
8630
8672
|
}
|
|
8631
8673
|
/**
|
|
8632
|
-
*
|
|
8633
|
-
*
|
|
8634
|
-
*
|
|
8635
|
-
*
|
|
8636
|
-
*
|
|
8637
|
-
*
|
|
8638
|
-
*
|
|
8639
|
-
*
|
|
8640
|
-
*
|
|
8641
|
-
*
|
|
8642
|
-
*
|
|
8643
|
-
*
|
|
8644
|
-
|
|
8645
|
-
|
|
8646
|
-
|
|
8647
|
-
|
|
8674
|
+
* Reverse-map application-autoscaling state for the given DynamoDB table
|
|
8675
|
+
* dimension into the CFn `*CapacityAutoScalingSettings` shape (Issue
|
|
8676
|
+
* #395). Used for BOTH the table-level write dimension
|
|
8677
|
+
* (`dynamodb:table:WriteCapacityUnits`) and the per-replica read
|
|
8678
|
+
* dimension (`dynamodb:table:ReadCapacityUnits`); the CFn shape is
|
|
8679
|
+
* symmetric.
|
|
8680
|
+
*
|
|
8681
|
+
* Returns shape (CFn-canonical PascalCase keys, verified via `cdk synth`
|
|
8682
|
+
* on a real `TableV2` with `Capacity.autoscaled(...)` on 2026-05-16 —
|
|
8683
|
+
* see PR notes for the probe transcript):
|
|
8684
|
+
*
|
|
8685
|
+
* ```
|
|
8686
|
+
* {
|
|
8687
|
+
* MinCapacity: number;
|
|
8688
|
+
* MaxCapacity: number;
|
|
8689
|
+
* TargetTrackingScalingPolicyConfiguration: {
|
|
8690
|
+
* TargetValue: number;
|
|
8691
|
+
* DisableScaleIn?: boolean;
|
|
8692
|
+
* ScaleInCooldown?: number;
|
|
8693
|
+
* ScaleOutCooldown?: number;
|
|
8694
|
+
* };
|
|
8695
|
+
* }
|
|
8696
|
+
* ```
|
|
8697
|
+
*
|
|
8698
|
+
* `SeedCapacity` is intentionally NOT round-tripped — it is a CFn
|
|
8699
|
+
* create-only field with no corresponding application-autoscaling
|
|
8700
|
+
* surface (AWS does not retain the initial seed value once the
|
|
8701
|
+
* scaling target is registered).
|
|
8702
|
+
*
|
|
8703
|
+
* Resolution order:
|
|
8704
|
+
* 1. `DescribeScalableTargets` → recover `MinCapacity` / `MaxCapacity`
|
|
8705
|
+
* for the matching `ScalableDimension`. Returns `null` when no
|
|
8706
|
+
* target is registered (= no autoscaling in play for this
|
|
8707
|
+
* dimension — caller falls back to the flat capacity surface).
|
|
8708
|
+
* 2. `DescribeScalingPolicies` → find the `TargetTrackingScaling`
|
|
8709
|
+
* policy (filter out `StepScaling` / `PredictiveScaling` — CFn's
|
|
8710
|
+
* shape only carries the target-tracking variant). Returns `null`
|
|
8711
|
+
* when no `TargetTrackingScaling` policy is present (a scaling
|
|
8712
|
+
* target without a target-tracking policy is not cdkd-managed
|
|
8713
|
+
* drift territory; surface the flat capacity instead).
|
|
8714
|
+
*
|
|
8715
|
+
* Best-effort: any error (permissions gap, throttle, network) returns
|
|
8716
|
+
* `null` and the caller falls back to the flat-capacity branch. Logged
|
|
8717
|
+
* at debug so a real permissions misconfiguration is still visible
|
|
8718
|
+
* under `--verbose`.
|
|
8719
|
+
*
|
|
8720
|
+
* @param tableName DynamoDB table name (the `physicalId`).
|
|
8721
|
+
* @param scalableDimension `'dynamodb:table:WriteCapacityUnits'` or
|
|
8722
|
+
* `'dynamodb:table:ReadCapacityUnits'`.
|
|
8723
|
+
* @param client Pre-built region-scoped autoscaling client. Defaults to
|
|
8724
|
+
* a fresh client in the local region — pass an explicit client when
|
|
8725
|
+
* reading from a cross-region replica.
|
|
8726
|
+
*/
|
|
8727
|
+
async readAutoScalingSettings(tableName, scalableDimension, client) {
|
|
8728
|
+
try {
|
|
8729
|
+
const asClient = client ?? new ApplicationAutoScalingClient({ region: await this.dynamoDBClient.config.region() ?? "" });
|
|
8730
|
+
const targets = (await asClient.send(new DescribeScalableTargetsCommand({
|
|
8731
|
+
ServiceNamespace: "dynamodb",
|
|
8732
|
+
ResourceIds: [`table/${tableName}`],
|
|
8733
|
+
ScalableDimension: scalableDimension
|
|
8734
|
+
}))).ScalableTargets ?? [];
|
|
8735
|
+
if (targets.length === 0) return null;
|
|
8736
|
+
const target = targets[0];
|
|
8737
|
+
if (target.MinCapacity === void 0 || target.MaxCapacity === void 0) return null;
|
|
8738
|
+
const targetTracking = ((await asClient.send(new DescribeScalingPoliciesCommand({
|
|
8648
8739
|
ServiceNamespace: "dynamodb",
|
|
8649
8740
|
ResourceId: `table/${tableName}`,
|
|
8650
|
-
ScalableDimension:
|
|
8651
|
-
}))).ScalingPolicies ?? []).
|
|
8741
|
+
ScalableDimension: scalableDimension
|
|
8742
|
+
}))).ScalingPolicies ?? []).find((p) => p.PolicyType === "TargetTrackingScaling");
|
|
8743
|
+
if (!targetTracking) return null;
|
|
8744
|
+
const cfg = targetTracking.TargetTrackingScalingPolicyConfiguration;
|
|
8745
|
+
if (!cfg || cfg.TargetValue === void 0) return null;
|
|
8746
|
+
const tttConfig = { TargetValue: cfg.TargetValue };
|
|
8747
|
+
if (cfg.DisableScaleIn !== void 0) tttConfig["DisableScaleIn"] = cfg.DisableScaleIn;
|
|
8748
|
+
if (cfg.ScaleInCooldown !== void 0) tttConfig["ScaleInCooldown"] = cfg.ScaleInCooldown;
|
|
8749
|
+
if (cfg.ScaleOutCooldown !== void 0) tttConfig["ScaleOutCooldown"] = cfg.ScaleOutCooldown;
|
|
8750
|
+
return {
|
|
8751
|
+
MinCapacity: target.MinCapacity,
|
|
8752
|
+
MaxCapacity: target.MaxCapacity,
|
|
8753
|
+
TargetTrackingScalingPolicyConfiguration: tttConfig
|
|
8754
|
+
};
|
|
8652
8755
|
} catch (err) {
|
|
8653
|
-
this.logger.debug(`Could not
|
|
8654
|
-
return
|
|
8756
|
+
this.logger.debug(`Could not read application-autoscaling settings for ${tableName} (${scalableDimension}): ${err instanceof Error ? err.message : String(err)}`);
|
|
8757
|
+
return null;
|
|
8655
8758
|
}
|
|
8656
8759
|
}
|
|
8657
8760
|
/**
|
|
@@ -8659,13 +8762,17 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
8659
8762
|
* reverse-map. The drift comparator skips these so a templated value
|
|
8660
8763
|
* doesn't fire guaranteed false drift on every clean run.
|
|
8661
8764
|
*
|
|
8662
|
-
* Issue #389 emptied this list:
|
|
8663
|
-
* - `WriteProvisionedThroughputSettings`
|
|
8664
|
-
*
|
|
8665
|
-
*
|
|
8666
|
-
*
|
|
8667
|
-
*
|
|
8668
|
-
*
|
|
8765
|
+
* Issue #389 + #395 emptied this list:
|
|
8766
|
+
* - `WriteProvisionedThroughputSettings` reverse-maps both the flat
|
|
8767
|
+
* `{WriteCapacityUnits}` shape (no autoscaling) AND the full
|
|
8768
|
+
* `{WriteCapacityAutoScalingSettings}` shape (autoscaling-managed;
|
|
8769
|
+
* recovered from `DescribeScalableTargets` +
|
|
8770
|
+
* `DescribeScalingPolicies`). PAY_PER_REQUEST tables emit `{}`.
|
|
8771
|
+
* - Per-replica `ReadProvisionedThroughputSettings.ReadCapacityAutoScalingSettings`
|
|
8772
|
+
* reverse-maps from a region-scoped application-autoscaling client
|
|
8773
|
+
* for the `dynamodb:table:ReadCapacityUnits` dimension. Non-
|
|
8774
|
+
* autoscaled replicas omit the key (no per-replica flat read
|
|
8775
|
+
* capacity available in `DescribeTable`).
|
|
8669
8776
|
* - `WriteOnDemandThroughputSettings` is reverse-mapped from
|
|
8670
8777
|
* `Table.OnDemandThroughput.MaxWriteRequestUnits`. Always-emit
|
|
8671
8778
|
* `{}` placeholder when AWS reports no override.
|
|
@@ -18288,8 +18395,8 @@ var RDSProvider = class {
|
|
|
18288
18395
|
|
|
18289
18396
|
//#endregion
|
|
18290
18397
|
//#region src/provisioning/providers/rds-dbproxy-provider.ts
|
|
18291
|
-
const POLL_INTERVAL_MS = 5e3;
|
|
18292
|
-
const POLL_TIMEOUT_MS = 900 * 1e3;
|
|
18398
|
+
const POLL_INTERVAL_MS$1 = 5e3;
|
|
18399
|
+
const POLL_TIMEOUT_MS$1 = 900 * 1e3;
|
|
18293
18400
|
/**
|
|
18294
18401
|
* AWS RDS DBProxy Provider
|
|
18295
18402
|
*
|
|
@@ -18376,7 +18483,7 @@ var RDSDBProxyProvider = class {
|
|
|
18376
18483
|
let endpoint;
|
|
18377
18484
|
let dbProxyArn;
|
|
18378
18485
|
let vpcId;
|
|
18379
|
-
const deadline = Date.now() + POLL_TIMEOUT_MS;
|
|
18486
|
+
const deadline = Date.now() + POLL_TIMEOUT_MS$1;
|
|
18380
18487
|
let status;
|
|
18381
18488
|
while (Date.now() < deadline) {
|
|
18382
18489
|
try {
|
|
@@ -18393,7 +18500,7 @@ var RDSDBProxyProvider = class {
|
|
|
18393
18500
|
if (error instanceof DBProxyNotFoundFault) {} else if (error instanceof ProvisioningError) throw error;
|
|
18394
18501
|
else throw this.wrapError(error, "CREATE (poll)", resourceType, logicalId, dbProxyName);
|
|
18395
18502
|
}
|
|
18396
|
-
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
18503
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS$1));
|
|
18397
18504
|
}
|
|
18398
18505
|
if (!endpoint || !dbProxyArn) throw new ProvisioningError(`Timed out waiting for DBProxy ${dbProxyName} to become available (last status: ${status ?? "unknown"})`, resourceType, logicalId, dbProxyName);
|
|
18399
18506
|
return {
|
|
@@ -18407,6 +18514,11 @@ var RDSDBProxyProvider = class {
|
|
|
18407
18514
|
}
|
|
18408
18515
|
async update(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
18409
18516
|
const client = this.getClient();
|
|
18517
|
+
for (const field of [
|
|
18518
|
+
"DBProxyName",
|
|
18519
|
+
"EngineFamily",
|
|
18520
|
+
"VpcSubnetIds"
|
|
18521
|
+
]) if (JSON.stringify(properties[field]) !== JSON.stringify(previousProperties[field])) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `${field} is immutable on AWS::RDS::DBProxy — destroy + redeploy to change it`);
|
|
18410
18522
|
const input = { DBProxyName: physicalId };
|
|
18411
18523
|
let hasModify = false;
|
|
18412
18524
|
for (const key of [
|
|
@@ -18449,7 +18561,7 @@ var RDSDBProxyProvider = class {
|
|
|
18449
18561
|
}
|
|
18450
18562
|
throw this.wrapError(error, "DELETE", resourceType, logicalId, physicalId);
|
|
18451
18563
|
}
|
|
18452
|
-
const deadline = Date.now() + POLL_TIMEOUT_MS;
|
|
18564
|
+
const deadline = Date.now() + POLL_TIMEOUT_MS$1;
|
|
18453
18565
|
while (Date.now() < deadline) {
|
|
18454
18566
|
try {
|
|
18455
18567
|
await client.send(new DescribeDBProxiesCommand({ DBProxyName: physicalId }));
|
|
@@ -18460,7 +18572,7 @@ var RDSDBProxyProvider = class {
|
|
|
18460
18572
|
}
|
|
18461
18573
|
throw this.wrapError(error, "DELETE (poll)", resourceType, logicalId, physicalId);
|
|
18462
18574
|
}
|
|
18463
|
-
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
18575
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS$1));
|
|
18464
18576
|
}
|
|
18465
18577
|
throw new ProvisioningError(`Timed out waiting for DBProxy ${physicalId} to fully delete`, resourceType, logicalId, physicalId);
|
|
18466
18578
|
}
|
|
@@ -18635,6 +18747,337 @@ var RDSDBProxyProvider = class {
|
|
|
18635
18747
|
}
|
|
18636
18748
|
};
|
|
18637
18749
|
|
|
18750
|
+
//#endregion
|
|
18751
|
+
//#region src/provisioning/providers/rds-dbproxy-endpoint-provider.ts
|
|
18752
|
+
const POLL_INTERVAL_MS = 5e3;
|
|
18753
|
+
const POLL_TIMEOUT_MS = 900 * 1e3;
|
|
18754
|
+
/**
|
|
18755
|
+
* AWS RDS DBProxyEndpoint Provider
|
|
18756
|
+
*
|
|
18757
|
+
* Implements resource provisioning for `AWS::RDS::DBProxyEndpoint` — the
|
|
18758
|
+
* additional read/write or read-only endpoint that can be attached to a
|
|
18759
|
+
* parent DBProxy.
|
|
18760
|
+
*
|
|
18761
|
+
* **Why a dedicated SDK provider** (per `feedback_dedicated_provider_over_special_case.md`):
|
|
18762
|
+
* completes the RDS DBProxy family started in PR #387 (`DBProxyTargetGroup`)
|
|
18763
|
+
* and PR #394 (`DBProxy`). Keeps the whole family on one codebase so create /
|
|
18764
|
+
* update / delete handling stays consistent across the parent + endpoints +
|
|
18765
|
+
* target-group children.
|
|
18766
|
+
*
|
|
18767
|
+
* **Lifecycle**:
|
|
18768
|
+
* - `create`: validates required fields (`DBProxyName` / `VpcSubnetIds`),
|
|
18769
|
+
* issues `CreateDBProxyEndpointCommand`, then polls `DescribeDBProxyEndpoints`
|
|
18770
|
+
* until `Status === 'available'`. Returns `physicalId = DBProxyEndpointName`
|
|
18771
|
+
* plus `Endpoint` / `DBProxyEndpointArn` / `IsDefault` / `VpcId` in
|
|
18772
|
+
* `attributes`.
|
|
18773
|
+
* - `update`: `ModifyDBProxyEndpointCommand` for the mutable fields
|
|
18774
|
+
* (`VpcSecurityGroupIds` → SDK input `VpcSecurityGroupIds`,
|
|
18775
|
+
* `NewDBProxyEndpointName` via rename). Tags diff via separate
|
|
18776
|
+
* `AddTagsToResource` / `RemoveTagsFromResource` calls. DBProxyName /
|
|
18777
|
+
* VpcSubnetIds / TargetRole are immutable on AWS.
|
|
18778
|
+
* - `delete`: `DeleteDBProxyEndpointCommand`, then polls until
|
|
18779
|
+
* `DBProxyEndpointNotFoundFault`. Idempotent on NotFound (region-match
|
|
18780
|
+
* gated). `DBProxyNotFoundFault` also idempotent — if the parent DBProxy
|
|
18781
|
+
* is already gone via CASCADE, the endpoint is too.
|
|
18782
|
+
* - `getAttribute`: `Endpoint` / `DBProxyEndpointArn` / `IsDefault` / `VpcId`
|
|
18783
|
+
* via `DescribeDBProxyEndpoints`, cached per `(physicalId, attribute)`.
|
|
18784
|
+
* - `import`: explicit `--resource <id>=<DBProxyEndpointName>` first; falls
|
|
18785
|
+
* back to paginated auto-lookup via `DescribeDBProxyEndpoints` +
|
|
18786
|
+
* `ListTagsForResource` matching `aws:cdk:path`.
|
|
18787
|
+
*
|
|
18788
|
+
* **physicalId** = DBProxyEndpointName (matches CFn `primaryIdentifier`).
|
|
18789
|
+
*/
|
|
18790
|
+
var RDSDBProxyEndpointProvider = class {
|
|
18791
|
+
rdsClient;
|
|
18792
|
+
providerRegion = process.env["AWS_REGION"];
|
|
18793
|
+
logger = getLogger().child("RDSDBProxyEndpointProvider");
|
|
18794
|
+
attributeCache = /* @__PURE__ */ new Map();
|
|
18795
|
+
handledProperties = new Map([["AWS::RDS::DBProxyEndpoint", new Set([
|
|
18796
|
+
"DBProxyEndpointName",
|
|
18797
|
+
"DBProxyName",
|
|
18798
|
+
"VpcSubnetIds",
|
|
18799
|
+
"VpcSecurityGroupIds",
|
|
18800
|
+
"TargetRole",
|
|
18801
|
+
"Tags"
|
|
18802
|
+
])]]);
|
|
18803
|
+
getClient() {
|
|
18804
|
+
if (!this.rdsClient) this.rdsClient = new RDSClient(this.providerRegion ? { region: this.providerRegion } : {});
|
|
18805
|
+
return this.rdsClient;
|
|
18806
|
+
}
|
|
18807
|
+
async create(logicalId, resourceType, properties) {
|
|
18808
|
+
const dbProxyName = properties["DBProxyName"];
|
|
18809
|
+
if (!dbProxyName) throw new ProvisioningError(`DBProxyName is required for AWS::RDS::DBProxyEndpoint ${logicalId}`, resourceType, logicalId);
|
|
18810
|
+
const dbProxyEndpointName = properties["DBProxyEndpointName"] ?? generateResourceName(logicalId, { maxLength: 64 });
|
|
18811
|
+
const vpcSubnetIds = properties["VpcSubnetIds"];
|
|
18812
|
+
if (!vpcSubnetIds || vpcSubnetIds.length === 0) throw new ProvisioningError(`VpcSubnetIds (at least one) is required for AWS::RDS::DBProxyEndpoint ${logicalId}`, resourceType, logicalId);
|
|
18813
|
+
const client = this.getClient();
|
|
18814
|
+
this.logger.debug(`Creating DBProxyEndpoint ${dbProxyEndpointName} (proxy=${dbProxyName})`);
|
|
18815
|
+
try {
|
|
18816
|
+
await client.send(new CreateDBProxyEndpointCommand({
|
|
18817
|
+
DBProxyName: dbProxyName,
|
|
18818
|
+
DBProxyEndpointName: dbProxyEndpointName,
|
|
18819
|
+
VpcSubnetIds: vpcSubnetIds,
|
|
18820
|
+
VpcSecurityGroupIds: properties["VpcSecurityGroupIds"],
|
|
18821
|
+
TargetRole: properties["TargetRole"],
|
|
18822
|
+
Tags: this.toAwsTags(properties["Tags"])
|
|
18823
|
+
}));
|
|
18824
|
+
} catch (error) {
|
|
18825
|
+
throw this.wrapError(error, "CREATE", resourceType, logicalId, void 0);
|
|
18826
|
+
}
|
|
18827
|
+
let endpoint;
|
|
18828
|
+
let arn;
|
|
18829
|
+
let isDefault;
|
|
18830
|
+
let vpcId;
|
|
18831
|
+
const deadline = Date.now() + POLL_TIMEOUT_MS;
|
|
18832
|
+
let status;
|
|
18833
|
+
while (Date.now() < deadline) {
|
|
18834
|
+
try {
|
|
18835
|
+
const ep = (await client.send(new DescribeDBProxyEndpointsCommand({
|
|
18836
|
+
DBProxyName: dbProxyName,
|
|
18837
|
+
DBProxyEndpointName: dbProxyEndpointName
|
|
18838
|
+
}))).DBProxyEndpoints?.[0];
|
|
18839
|
+
status = ep?.Status;
|
|
18840
|
+
if (status === "available") {
|
|
18841
|
+
endpoint = ep?.Endpoint;
|
|
18842
|
+
arn = ep?.DBProxyEndpointArn;
|
|
18843
|
+
isDefault = ep?.IsDefault;
|
|
18844
|
+
vpcId = ep?.VpcId;
|
|
18845
|
+
break;
|
|
18846
|
+
}
|
|
18847
|
+
if (status === "incompatible-network" || status === "insufficient-resource-limits") throw new ProvisioningError(`DBProxyEndpoint ${dbProxyEndpointName} entered terminal failure state: ${status}`, resourceType, logicalId, dbProxyEndpointName);
|
|
18848
|
+
} catch (error) {
|
|
18849
|
+
if (error instanceof DBProxyEndpointNotFoundFault || error instanceof DBProxyNotFoundFault) {} else if (error instanceof ProvisioningError) throw error;
|
|
18850
|
+
else throw this.wrapError(error, "CREATE (poll)", resourceType, logicalId, dbProxyEndpointName);
|
|
18851
|
+
}
|
|
18852
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
18853
|
+
}
|
|
18854
|
+
if (!endpoint || !arn) throw new ProvisioningError(`Timed out waiting for DBProxyEndpoint ${dbProxyEndpointName} to become available (last status: ${status ?? "unknown"})`, resourceType, logicalId, dbProxyEndpointName);
|
|
18855
|
+
return {
|
|
18856
|
+
physicalId: dbProxyEndpointName,
|
|
18857
|
+
attributes: {
|
|
18858
|
+
Endpoint: endpoint,
|
|
18859
|
+
DBProxyEndpointArn: arn,
|
|
18860
|
+
IsDefault: isDefault ?? false,
|
|
18861
|
+
VpcId: vpcId ?? ""
|
|
18862
|
+
}
|
|
18863
|
+
};
|
|
18864
|
+
}
|
|
18865
|
+
async update(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
18866
|
+
const client = this.getClient();
|
|
18867
|
+
for (const field of [
|
|
18868
|
+
"DBProxyName",
|
|
18869
|
+
"DBProxyEndpointName",
|
|
18870
|
+
"VpcSubnetIds",
|
|
18871
|
+
"TargetRole"
|
|
18872
|
+
]) if (JSON.stringify(properties[field]) !== JSON.stringify(previousProperties[field])) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `${field} is immutable on AWS::RDS::DBProxyEndpoint — destroy + redeploy to change it`);
|
|
18873
|
+
const oldSG = previousProperties["VpcSecurityGroupIds"] ?? [];
|
|
18874
|
+
const newSG = properties["VpcSecurityGroupIds"] ?? [];
|
|
18875
|
+
if (JSON.stringify(oldSG) !== JSON.stringify(newSG)) {
|
|
18876
|
+
this.logger.debug(`Updating DBProxyEndpoint ${physicalId} security groups`);
|
|
18877
|
+
try {
|
|
18878
|
+
await client.send(new ModifyDBProxyEndpointCommand({
|
|
18879
|
+
DBProxyEndpointName: physicalId,
|
|
18880
|
+
VpcSecurityGroupIds: newSG
|
|
18881
|
+
}));
|
|
18882
|
+
} catch (error) {
|
|
18883
|
+
throw this.wrapError(error, "UPDATE", resourceType, logicalId, physicalId);
|
|
18884
|
+
}
|
|
18885
|
+
}
|
|
18886
|
+
await this.applyTagDiff(physicalId, previousProperties["Tags"], properties["Tags"], resourceType, logicalId);
|
|
18887
|
+
this.invalidateAttributeCache(physicalId);
|
|
18888
|
+
return {
|
|
18889
|
+
physicalId,
|
|
18890
|
+
wasReplaced: false
|
|
18891
|
+
};
|
|
18892
|
+
}
|
|
18893
|
+
async delete(logicalId, physicalId, resourceType, _properties, context) {
|
|
18894
|
+
const client = this.getClient();
|
|
18895
|
+
this.logger.debug(`Deleting DBProxyEndpoint ${physicalId}`);
|
|
18896
|
+
try {
|
|
18897
|
+
await client.send(new DeleteDBProxyEndpointCommand({ DBProxyEndpointName: physicalId }));
|
|
18898
|
+
} catch (error) {
|
|
18899
|
+
if (error instanceof DBProxyEndpointNotFoundFault || error instanceof DBProxyNotFoundFault) {
|
|
18900
|
+
assertRegionMatch(await client.config.region(), context?.expectedRegion, resourceType, logicalId, physicalId);
|
|
18901
|
+
this.logger.debug(`DBProxyEndpoint ${physicalId} or parent already gone, treating as success`);
|
|
18902
|
+
return;
|
|
18903
|
+
}
|
|
18904
|
+
throw this.wrapError(error, "DELETE", resourceType, logicalId, physicalId);
|
|
18905
|
+
}
|
|
18906
|
+
const deadline = Date.now() + POLL_TIMEOUT_MS;
|
|
18907
|
+
while (Date.now() < deadline) {
|
|
18908
|
+
try {
|
|
18909
|
+
await client.send(new DescribeDBProxyEndpointsCommand({ DBProxyEndpointName: physicalId }));
|
|
18910
|
+
} catch (error) {
|
|
18911
|
+
if (error instanceof DBProxyEndpointNotFoundFault || error instanceof DBProxyNotFoundFault) {
|
|
18912
|
+
this.logger.debug(`DBProxyEndpoint ${physicalId} fully deleted`);
|
|
18913
|
+
return;
|
|
18914
|
+
}
|
|
18915
|
+
throw this.wrapError(error, "DELETE (poll)", resourceType, logicalId, physicalId);
|
|
18916
|
+
}
|
|
18917
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
18918
|
+
}
|
|
18919
|
+
throw new ProvisioningError(`Timed out waiting for DBProxyEndpoint ${physicalId} to fully delete`, resourceType, logicalId, physicalId);
|
|
18920
|
+
}
|
|
18921
|
+
async getAttribute(physicalId, _resourceType, attributeName) {
|
|
18922
|
+
const cacheKey = `${physicalId}:${attributeName}`;
|
|
18923
|
+
const cached = this.attributeCache.get(cacheKey);
|
|
18924
|
+
if (cached !== void 0) return cached;
|
|
18925
|
+
if (attributeName !== "Endpoint" && attributeName !== "DBProxyEndpointArn" && attributeName !== "IsDefault" && attributeName !== "VpcId") {
|
|
18926
|
+
this.logger.warn(`Unknown attribute ${attributeName} for AWS::RDS::DBProxyEndpoint, returning undefined`);
|
|
18927
|
+
return;
|
|
18928
|
+
}
|
|
18929
|
+
try {
|
|
18930
|
+
const ep = (await this.getClient().send(new DescribeDBProxyEndpointsCommand({ DBProxyEndpointName: physicalId }))).DBProxyEndpoints?.[0];
|
|
18931
|
+
if (!ep) return void 0;
|
|
18932
|
+
const value = {
|
|
18933
|
+
Endpoint: ep.Endpoint,
|
|
18934
|
+
DBProxyEndpointArn: ep.DBProxyEndpointArn,
|
|
18935
|
+
IsDefault: ep.IsDefault ?? false,
|
|
18936
|
+
VpcId: ep.VpcId
|
|
18937
|
+
}[attributeName];
|
|
18938
|
+
if (value !== void 0) this.attributeCache.set(cacheKey, value);
|
|
18939
|
+
return value;
|
|
18940
|
+
} catch (error) {
|
|
18941
|
+
if (error instanceof DBProxyEndpointNotFoundFault || error instanceof DBProxyNotFoundFault) return;
|
|
18942
|
+
throw error;
|
|
18943
|
+
}
|
|
18944
|
+
}
|
|
18945
|
+
async import(input) {
|
|
18946
|
+
const explicit = resolveExplicitPhysicalId(input, "DBProxyEndpointName");
|
|
18947
|
+
if (explicit) return this.buildImportResult(explicit);
|
|
18948
|
+
const client = this.getClient();
|
|
18949
|
+
let marker;
|
|
18950
|
+
do {
|
|
18951
|
+
const describe = await client.send(new DescribeDBProxyEndpointsCommand({
|
|
18952
|
+
Marker: marker,
|
|
18953
|
+
MaxRecords: 100
|
|
18954
|
+
}));
|
|
18955
|
+
for (const ep of describe.DBProxyEndpoints ?? []) {
|
|
18956
|
+
if (!ep.DBProxyEndpointArn) continue;
|
|
18957
|
+
try {
|
|
18958
|
+
if (matchesCdkPath((await client.send(new ListTagsForResourceCommand$8({ ResourceName: ep.DBProxyEndpointArn }))).TagList ?? [], input.cdkPath)) return this.buildImportResult(ep.DBProxyEndpointName ?? "");
|
|
18959
|
+
} catch (error) {
|
|
18960
|
+
this.logger.debug(`ListTagsForResource failed for ${ep.DBProxyEndpointName}: ${error instanceof Error ? error.message : String(error)}`);
|
|
18961
|
+
}
|
|
18962
|
+
}
|
|
18963
|
+
marker = describe.Marker;
|
|
18964
|
+
} while (marker);
|
|
18965
|
+
return null;
|
|
18966
|
+
}
|
|
18967
|
+
async readCurrentState(physicalId) {
|
|
18968
|
+
const client = this.getClient();
|
|
18969
|
+
let ep;
|
|
18970
|
+
try {
|
|
18971
|
+
ep = (await client.send(new DescribeDBProxyEndpointsCommand({ DBProxyEndpointName: physicalId }))).DBProxyEndpoints?.[0];
|
|
18972
|
+
if (!ep) return void 0;
|
|
18973
|
+
} catch (error) {
|
|
18974
|
+
if (error instanceof DBProxyEndpointNotFoundFault || error instanceof DBProxyNotFoundFault) return;
|
|
18975
|
+
throw error;
|
|
18976
|
+
}
|
|
18977
|
+
const e = ep;
|
|
18978
|
+
const result = {
|
|
18979
|
+
DBProxyEndpointName: e.DBProxyEndpointName,
|
|
18980
|
+
DBProxyName: e.DBProxyName,
|
|
18981
|
+
VpcSubnetIds: e.VpcSubnetIds ?? [],
|
|
18982
|
+
VpcSecurityGroupIds: e.VpcSecurityGroupIds ?? [],
|
|
18983
|
+
TargetRole: e.TargetRole ?? "READ_WRITE"
|
|
18984
|
+
};
|
|
18985
|
+
if (e.DBProxyEndpointArn) try {
|
|
18986
|
+
result["Tags"] = normalizeAwsTagsToCfn((await client.send(new ListTagsForResourceCommand$8({ ResourceName: e.DBProxyEndpointArn }))).TagList ?? []);
|
|
18987
|
+
} catch (error) {
|
|
18988
|
+
this.logger.debug(`ListTagsForResource failed for ${physicalId}: ${error instanceof Error ? error.message : String(error)}`);
|
|
18989
|
+
result["Tags"] = [];
|
|
18990
|
+
}
|
|
18991
|
+
else result["Tags"] = [];
|
|
18992
|
+
return result;
|
|
18993
|
+
}
|
|
18994
|
+
async applyTagDiff(physicalId, oldTags, newTags, resourceType, logicalId) {
|
|
18995
|
+
const oldMap = this.toTagMap(oldTags);
|
|
18996
|
+
const newMap = this.toTagMap(newTags);
|
|
18997
|
+
if (oldMap.size === newMap.size && [...oldMap.keys()].every((k) => newMap.has(k)) && [...oldMap.entries()].every(([k, v]) => newMap.get(k) === v)) return;
|
|
18998
|
+
const client = this.getClient();
|
|
18999
|
+
const arnCacheKey = `${physicalId}:DBProxyEndpointArn`;
|
|
19000
|
+
let arn = this.attributeCache.get(arnCacheKey);
|
|
19001
|
+
if (!arn) try {
|
|
19002
|
+
arn = (await client.send(new DescribeDBProxyEndpointsCommand({ DBProxyEndpointName: physicalId }))).DBProxyEndpoints?.[0]?.DBProxyEndpointArn;
|
|
19003
|
+
if (arn) this.attributeCache.set(arnCacheKey, arn);
|
|
19004
|
+
} catch (error) {
|
|
19005
|
+
this.logger.debug(`Skipping tag diff for ${physicalId} (no ARN): ${error instanceof Error ? error.message : String(error)}`);
|
|
19006
|
+
return;
|
|
19007
|
+
}
|
|
19008
|
+
if (!arn) return;
|
|
19009
|
+
const toRemove = [];
|
|
19010
|
+
const toAdd = [];
|
|
19011
|
+
for (const k of oldMap.keys()) if (!newMap.has(k)) toRemove.push(k);
|
|
19012
|
+
for (const [k, v] of newMap.entries()) if (oldMap.get(k) !== v) toAdd.push({
|
|
19013
|
+
Key: k,
|
|
19014
|
+
Value: v
|
|
19015
|
+
});
|
|
19016
|
+
if (toRemove.length > 0) try {
|
|
19017
|
+
await client.send(new RemoveTagsFromResourceCommand$1({
|
|
19018
|
+
ResourceName: arn,
|
|
19019
|
+
TagKeys: toRemove
|
|
19020
|
+
}));
|
|
19021
|
+
} catch (error) {
|
|
19022
|
+
throw this.wrapError(error, "UPDATE (remove tags)", resourceType, logicalId, physicalId);
|
|
19023
|
+
}
|
|
19024
|
+
if (toAdd.length > 0) try {
|
|
19025
|
+
await client.send(new AddTagsToResourceCommand$1({
|
|
19026
|
+
ResourceName: arn,
|
|
19027
|
+
Tags: toAdd
|
|
19028
|
+
}));
|
|
19029
|
+
} catch (error) {
|
|
19030
|
+
throw this.wrapError(error, "UPDATE (add tags)", resourceType, logicalId, physicalId);
|
|
19031
|
+
}
|
|
19032
|
+
}
|
|
19033
|
+
toTagMap(tags) {
|
|
19034
|
+
const map = /* @__PURE__ */ new Map();
|
|
19035
|
+
if (Array.isArray(tags)) {
|
|
19036
|
+
for (const entry of tags) if (entry?.Key !== void 0) map.set(entry.Key, entry.Value ?? "");
|
|
19037
|
+
}
|
|
19038
|
+
return map;
|
|
19039
|
+
}
|
|
19040
|
+
toAwsTags(tags) {
|
|
19041
|
+
if (!Array.isArray(tags) || tags.length === 0) return void 0;
|
|
19042
|
+
return tags.filter((t) => t.Key !== void 0).map((t) => ({
|
|
19043
|
+
Key: t.Key,
|
|
19044
|
+
Value: t.Value ?? ""
|
|
19045
|
+
}));
|
|
19046
|
+
}
|
|
19047
|
+
async buildImportResult(physicalId) {
|
|
19048
|
+
try {
|
|
19049
|
+
const ep = (await this.getClient().send(new DescribeDBProxyEndpointsCommand({ DBProxyEndpointName: physicalId }))).DBProxyEndpoints?.[0];
|
|
19050
|
+
return {
|
|
19051
|
+
physicalId,
|
|
19052
|
+
attributes: {
|
|
19053
|
+
Endpoint: ep?.Endpoint ?? "",
|
|
19054
|
+
DBProxyEndpointArn: ep?.DBProxyEndpointArn ?? "",
|
|
19055
|
+
IsDefault: ep?.IsDefault ?? false,
|
|
19056
|
+
VpcId: ep?.VpcId ?? ""
|
|
19057
|
+
}
|
|
19058
|
+
};
|
|
19059
|
+
} catch {
|
|
19060
|
+
return {
|
|
19061
|
+
physicalId,
|
|
19062
|
+
attributes: {
|
|
19063
|
+
Endpoint: "",
|
|
19064
|
+
DBProxyEndpointArn: "",
|
|
19065
|
+
IsDefault: false,
|
|
19066
|
+
VpcId: ""
|
|
19067
|
+
}
|
|
19068
|
+
};
|
|
19069
|
+
}
|
|
19070
|
+
}
|
|
19071
|
+
invalidateAttributeCache(physicalId) {
|
|
19072
|
+
for (const key of this.attributeCache.keys()) if (key.startsWith(`${physicalId}:`)) this.attributeCache.delete(key);
|
|
19073
|
+
}
|
|
19074
|
+
wrapError(error, op, resourceType, logicalId, physicalId) {
|
|
19075
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
19076
|
+
const cause = error instanceof Error ? error : void 0;
|
|
19077
|
+
return new ProvisioningError(`${op} failed for ${logicalId}: ${message}`, resourceType, logicalId, physicalId, cause);
|
|
19078
|
+
}
|
|
19079
|
+
};
|
|
19080
|
+
|
|
18638
19081
|
//#endregion
|
|
18639
19082
|
//#region src/provisioning/providers/rds-dbproxy-targetgroup-provider.ts
|
|
18640
19083
|
/**
|
|
@@ -18754,6 +19197,12 @@ var RDSDBProxyTargetGroupProvider = class {
|
|
|
18754
19197
|
const dbProxyName = properties["DBProxyName"];
|
|
18755
19198
|
if (!dbProxyName) throw new ProvisioningError(`DBProxyName is required for AWS::RDS::DBProxyTargetGroup ${logicalId} update`, resourceType, logicalId, physicalId);
|
|
18756
19199
|
const targetGroupName = properties["TargetGroupName"] ?? "default";
|
|
19200
|
+
for (const field of ["DBProxyName", "TargetGroupName"]) {
|
|
19201
|
+
const oldVal = previousProperties[field];
|
|
19202
|
+
const newVal = properties[field];
|
|
19203
|
+
const normalize = (v) => field === "TargetGroupName" && (v === void 0 || v === "default") ? "default" : v;
|
|
19204
|
+
if (JSON.stringify(normalize(oldVal)) !== JSON.stringify(normalize(newVal))) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `${field} is immutable on AWS::RDS::DBProxyTargetGroup — destroy + redeploy to change it`);
|
|
19205
|
+
}
|
|
18757
19206
|
const client = this.getClient();
|
|
18758
19207
|
const oldPool = previousProperties["ConnectionPoolConfigurationInfo"];
|
|
18759
19208
|
const newPool = properties["ConnectionPoolConfigurationInfo"];
|
|
@@ -29596,6 +30045,7 @@ function registerAllProviders(registry) {
|
|
|
29596
30045
|
registry.register("AWS::RDS::DBCluster", rdsProvider);
|
|
29597
30046
|
registry.register("AWS::RDS::DBInstance", rdsProvider);
|
|
29598
30047
|
registry.register("AWS::RDS::DBProxy", new RDSDBProxyProvider());
|
|
30048
|
+
registry.register("AWS::RDS::DBProxyEndpoint", new RDSDBProxyEndpointProvider());
|
|
29599
30049
|
registry.register("AWS::RDS::DBProxyTargetGroup", new RDSDBProxyTargetGroupProvider());
|
|
29600
30050
|
const docdbProvider = new DocDBProvider();
|
|
29601
30051
|
registry.register("AWS::DocDB::DBSubnetGroup", docdbProvider);
|
|
@@ -44576,7 +45026,7 @@ function reorderArgs(argv) {
|
|
|
44576
45026
|
*/
|
|
44577
45027
|
async function main() {
|
|
44578
45028
|
const program = new Command();
|
|
44579
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.
|
|
45029
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.108.0");
|
|
44580
45030
|
program.addCommand(createBootstrapCommand());
|
|
44581
45031
|
program.addCommand(createSynthCommand());
|
|
44582
45032
|
program.addCommand(createListCommand());
|