@go-to-k/cdkd 0.117.0 → 0.117.2
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 +406 -53
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -44,10 +44,10 @@ import { CreateWebACLCommand, DeleteWebACLCommand, GetWebACLCommand, ListTagsFor
|
|
|
44
44
|
import { CognitoIdentityProviderClient, CreateUserPoolCommand, DeleteUserPoolCommand, DescribeUserPoolCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$14, ListUserPoolsCommand, ResourceNotFoundException as ResourceNotFoundException$6, UpdateUserPoolCommand } from "@aws-sdk/client-cognito-identity-provider";
|
|
45
45
|
import { AddTagsToResourceCommand as AddTagsToResourceCommand$4, CreateCacheClusterCommand, CreateCacheSubnetGroupCommand, DeleteCacheClusterCommand, DeleteCacheSubnetGroupCommand, DescribeCacheClustersCommand, DescribeCacheSubnetGroupsCommand, ElastiCacheClient, ListTagsForResourceCommand as ListTagsForResourceCommand$15, ModifyCacheClusterCommand, ModifyCacheSubnetGroupCommand, RemoveTagsFromResourceCommand as RemoveTagsFromResourceCommand$4 } from "@aws-sdk/client-elasticache";
|
|
46
46
|
import { CreatePrivateDnsNamespaceCommand, CreateServiceCommand as CreateServiceCommand$1, DeleteNamespaceCommand, DeleteServiceCommand as DeleteServiceCommand$1, GetNamespaceCommand, GetOperationCommand, GetServiceCommand, ListNamespacesCommand, ListServicesCommand as ListServicesCommand$1, ListTagsForResourceCommand as ListTagsForResourceCommand$16, NamespaceNotFound, ServiceDiscoveryClient, ServiceNotFound, UpdatePrivateDnsNamespaceCommand, UpdateServiceCommand as UpdateServiceCommand$1 } from "@aws-sdk/client-servicediscovery";
|
|
47
|
-
import { AppSyncClient, CreateApiKeyCommand, CreateDataSourceCommand, CreateGraphqlApiCommand, CreateResolverCommand, DeleteApiKeyCommand, DeleteDataSourceCommand, DeleteGraphqlApiCommand, DeleteResolverCommand, GetDataSourceCommand, GetGraphqlApiCommand, GetIntrospectionSchemaCommand, GetResolverCommand, ListApiKeysCommand, ListGraphqlApisCommand, NotFoundException as NotFoundException$4, StartSchemaCreationCommand } from "@aws-sdk/client-appsync";
|
|
47
|
+
import { AppSyncClient, CreateApiKeyCommand, CreateDataSourceCommand, CreateGraphqlApiCommand, CreateResolverCommand, DeleteApiKeyCommand, DeleteDataSourceCommand, DeleteGraphqlApiCommand, DeleteResolverCommand, GetDataSourceCommand, GetGraphqlApiCommand, GetIntrospectionSchemaCommand, GetResolverCommand, ListApiKeysCommand, ListGraphqlApisCommand, NotFoundException as NotFoundException$4, StartSchemaCreationCommand, TagResourceCommand as TagResourceCommand$13, UntagResourceCommand as UntagResourceCommand$12, UpdateApiKeyCommand, UpdateDataSourceCommand, UpdateGraphqlApiCommand, UpdateResolverCommand } from "@aws-sdk/client-appsync";
|
|
48
48
|
import { parse, print } from "graphql";
|
|
49
49
|
import { 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, GetDatabasesCommand, GetJobCommand, GetSecurityConfigurationCommand, GetSecurityConfigurationsCommand, GetTableCommand, GetTablesCommand, GetTagsCommand, GetTriggerCommand, GetWorkflowCommand, GlueClient, ListWorkflowsCommand, StartCrawlerScheduleCommand, StartTriggerCommand, StopCrawlerScheduleCommand, StopTriggerCommand, UpdateConnectionCommand, UpdateCrawlerCommand, UpdateDatabaseCommand, UpdateJobCommand, UpdateTableCommand as UpdateTableCommand$1, UpdateTriggerCommand, UpdateWorkflowCommand } from "@aws-sdk/client-glue";
|
|
50
|
-
import { AddTagsToStreamCommand, CreateStreamCommand, DecreaseStreamRetentionPeriodCommand, DeleteStreamCommand, DeregisterStreamConsumerCommand, DescribeStreamCommand, DescribeStreamConsumerCommand, IncreaseStreamRetentionPeriodCommand, KinesisClient, ListStreamsCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$17, ListTagsForStreamCommand, RegisterStreamConsumerCommand, RemoveTagsFromStreamCommand, ResourceNotFoundException as ResourceNotFoundException$7, StartStreamEncryptionCommand, StopStreamEncryptionCommand, TagResourceCommand as TagResourceCommand$
|
|
50
|
+
import { AddTagsToStreamCommand, CreateStreamCommand, DecreaseStreamRetentionPeriodCommand, DeleteStreamCommand, DeregisterStreamConsumerCommand, DescribeStreamCommand, DescribeStreamConsumerCommand, IncreaseStreamRetentionPeriodCommand, KinesisClient, ListStreamsCommand, ListTagsForResourceCommand as ListTagsForResourceCommand$17, ListTagsForStreamCommand, RegisterStreamConsumerCommand, RemoveTagsFromStreamCommand, ResourceNotFoundException as ResourceNotFoundException$7, StartStreamEncryptionCommand, StopStreamEncryptionCommand, TagResourceCommand as TagResourceCommand$14, UntagResourceCommand as UntagResourceCommand$13, UpdateShardCountCommand } from "@aws-sdk/client-kinesis";
|
|
51
51
|
import { AccessPointNotFound, CreateAccessPointCommand, CreateFileSystemCommand, CreateMountTargetCommand, DeleteAccessPointCommand, DeleteFileSystemCommand, DeleteMountTargetCommand, DescribeAccessPointsCommand, DescribeBackupPolicyCommand, DescribeFileSystemsCommand, DescribeLifecycleConfigurationCommand, DescribeMountTargetSecurityGroupsCommand, DescribeMountTargetsCommand, EFSClient, FileSystemNotFound, ModifyMountTargetSecurityGroupsCommand, MountTargetNotFound, UpdateFileSystemCommand } from "@aws-sdk/client-efs";
|
|
52
52
|
import { CreateDeliveryStreamCommand, DeleteDeliveryStreamCommand, DescribeDeliveryStreamCommand, FirehoseClient, ListDeliveryStreamsCommand, ListTagsForDeliveryStreamCommand, ResourceNotFoundException as ResourceNotFoundException$8 } from "@aws-sdk/client-firehose";
|
|
53
53
|
import { AddTagsCommand as AddTagsCommand$1, CloudTrailClient, CreateTrailCommand, DeleteTrailCommand, GetEventSelectorsCommand, GetInsightSelectorsCommand, GetTrailCommand, GetTrailStatusCommand, ListTagsCommand as ListTagsCommand$1, ListTrailsCommand, PutEventSelectorsCommand, PutInsightSelectorsCommand, RemoveTagsCommand as RemoveTagsCommand$1, StartLoggingCommand, StopLoggingCommand, TrailNotFoundException, UpdateTrailCommand } from "@aws-sdk/client-cloudtrail";
|
|
@@ -7375,7 +7375,7 @@ var LambdaLayerVersionProvider = class {
|
|
|
7375
7375
|
* template should re-deploy with `--replace`.
|
|
7376
7376
|
*/
|
|
7377
7377
|
async update(logicalId, _physicalId, resourceType, _properties, _previousProperties) {
|
|
7378
|
-
return Promise.reject(new ResourceUpdateNotSupportedError(resourceType, logicalId, "Lambda
|
|
7378
|
+
return Promise.reject(new ResourceUpdateNotSupportedError(resourceType, logicalId, "AWS Lambda LayerVersion is immutable on AWS — there is no UpdateLayerVersion API; every change requires PublishLayerVersion (a new version with a new LayerVersionArn). Re-deploy with cdkd deploy --replace, or change the resource definition to publish a new version."));
|
|
7379
7379
|
}
|
|
7380
7380
|
/**
|
|
7381
7381
|
* Delete a Lambda layer version
|
|
@@ -7901,11 +7901,12 @@ var DynamoDBTableProvider = class {
|
|
|
7901
7901
|
* is surfaced for BOTH the LOCAL replica AND cross-region replicas
|
|
7902
7902
|
* via per-region SDK clients (cached in `regionalClientCache` for
|
|
7903
7903
|
* the deploy run). Issue #389 lifted the v1 LOCAL-only limitation.
|
|
7904
|
-
* - Cross-region replica Tags propagation (Issue #389):
|
|
7905
|
-
*
|
|
7906
|
-
*
|
|
7907
|
-
*
|
|
7908
|
-
*
|
|
7904
|
+
* - Cross-region replica Tags propagation (Issue #389 / #441):
|
|
7905
|
+
* BOTH `create()` and `update()` resolve each non-local replica's
|
|
7906
|
+
* table ARN by swapping the region segment of the local ARN and
|
|
7907
|
+
* issue `TagResource` / `UntagResource` against a per-region
|
|
7908
|
+
* client. The shared helper `applyCrossRegionReplicaTagsDiff`
|
|
7909
|
+
* centralizes the diff + best-effort WARN-on-failure contract.
|
|
7909
7910
|
*/
|
|
7910
7911
|
var DynamoDBGlobalTableProvider = class {
|
|
7911
7912
|
dynamoDBClient;
|
|
@@ -8114,6 +8115,13 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
8114
8115
|
if (!region || region === currentRegion) continue;
|
|
8115
8116
|
await this.addReplica(tableName, replica, region, logicalId);
|
|
8116
8117
|
}
|
|
8118
|
+
for (const replica of replicas) {
|
|
8119
|
+
const region = replica["Region"];
|
|
8120
|
+
if (!region || region === currentRegion) continue;
|
|
8121
|
+
const replicaTags = replica["Tags"];
|
|
8122
|
+
if (!replicaTags || replicaTags.length === 0) continue;
|
|
8123
|
+
await this.applyCrossRegionReplicaTagsDiff(tableInfo.tableArn, region, void 0, replicaTags, tableName);
|
|
8124
|
+
}
|
|
8117
8125
|
if (properties["TimeToLiveSpecification"]) {
|
|
8118
8126
|
const ttl = properties["TimeToLiveSpecification"];
|
|
8119
8127
|
const attributeName = ttl["AttributeName"];
|
|
@@ -8299,6 +8307,8 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
8299
8307
|
const region = replica["Region"];
|
|
8300
8308
|
if (!region || region === currentRegion) continue;
|
|
8301
8309
|
await this.addReplica(physicalId, replica, region, logicalId);
|
|
8310
|
+
const newReplicaTags = replica["Tags"];
|
|
8311
|
+
await this.applyCrossRegionReplicaTagsDiff(tableArn, region, void 0, newReplicaTags, physicalId);
|
|
8302
8312
|
const newReadAutoScaling = (replica["ReadProvisionedThroughputSettings"] ?? {})["ReadCapacityAutoScalingSettings"];
|
|
8303
8313
|
if (newBilling === "PROVISIONED" && newReadAutoScaling) {
|
|
8304
8314
|
const regionalAutoScalingClient = this.getRegionalAutoScalingClient(region);
|
|
@@ -8311,16 +8321,7 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
8311
8321
|
const oldReplica = (previousProperties["Replicas"] ?? []).find((r) => r["Region"] === region);
|
|
8312
8322
|
const oldReplicaTags = oldReplica?.["Tags"];
|
|
8313
8323
|
const newReplicaTags = replica["Tags"];
|
|
8314
|
-
|
|
8315
|
-
const replicaArn = this.replicaArnForRegion(tableArn, region);
|
|
8316
|
-
if (replicaArn) try {
|
|
8317
|
-
const regionalClient = this.getRegionalClient(region);
|
|
8318
|
-
await this.applyTagDiffOnClient(regionalClient, replicaArn, oldReplicaTags, newReplicaTags);
|
|
8319
|
-
} catch (tagErr) {
|
|
8320
|
-
this.logger.warn(`Could not apply Tags diff to cross-region replica ${region} of ${physicalId}: ${tagErr instanceof Error ? tagErr.message : String(tagErr)}. The replica's Tags state will surface as drift until the next successful deploy.`);
|
|
8321
|
-
}
|
|
8322
|
-
else this.logger.warn(`Could not derive replica ARN for region ${region} from ${tableArn} — skipping Tags propagation for ${physicalId}`);
|
|
8323
|
-
} else this.logger.warn(`Local DescribeTable returned no TableArn — cannot propagate Tags to cross-region replica ${region} of ${physicalId}`);
|
|
8324
|
+
await this.applyCrossRegionReplicaTagsDiff(tableArn, region, oldReplicaTags, newReplicaTags, physicalId);
|
|
8324
8325
|
const oldReadAutoScaling = (oldReplica?.["ReadProvisionedThroughputSettings"] ?? {})["ReadCapacityAutoScalingSettings"];
|
|
8325
8326
|
const newReadAutoScaling = (replica["ReadProvisionedThroughputSettings"] ?? {})["ReadCapacityAutoScalingSettings"];
|
|
8326
8327
|
const effectiveNewReadAutoScaling = newBilling === "PAY_PER_REQUEST" ? void 0 : newReadAutoScaling;
|
|
@@ -8439,10 +8440,49 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
8439
8440
|
await this.applyTagDiffOnClient(this.dynamoDBClient, tableArn, oldTagsRaw, newTagsRaw);
|
|
8440
8441
|
}
|
|
8441
8442
|
/**
|
|
8443
|
+
* Propagate a per-replica Tags diff to ONE cross-region replica via a
|
|
8444
|
+
* per-region client (Issue #389 / #441 — closes the create-side gap).
|
|
8445
|
+
* Centralizes the common shape used by BOTH `create()` (`oldTags`
|
|
8446
|
+
* undefined → every new tag is an add) and `update()` (per-replica
|
|
8447
|
+
* modify path's old-vs-new diff). Best-effort: a failure here logs at
|
|
8448
|
+
* WARN naming the offending region + ARN + reason and the deploy
|
|
8449
|
+
* continues — the cross-region Tags state will surface as drift on
|
|
8450
|
+
* the next run (or `cdkd drift --revert`) rather than aborting the
|
|
8451
|
+
* deploy mid-flight. Mirrors the autoscaling diff's failure contract
|
|
8452
|
+
* (PR #393).
|
|
8453
|
+
*
|
|
8454
|
+
* `tableArn` is the LOCAL replica's table ARN (returned by the
|
|
8455
|
+
* post-create `waitForTableActive` or the inline `DescribeTable` in
|
|
8456
|
+
* `update()`); the helper swaps the region segment via
|
|
8457
|
+
* `replicaArnForRegion` before issuing `TagResource` / `UntagResource`
|
|
8458
|
+
* against the per-region client.
|
|
8459
|
+
*
|
|
8460
|
+
* No-op when `oldTags` deep-equals `newTags` — the caller is allowed
|
|
8461
|
+
* to invoke unconditionally without first diffing.
|
|
8462
|
+
*/
|
|
8463
|
+
async applyCrossRegionReplicaTagsDiff(tableArn, region, oldTags, newTags, physicalIdForLogs) {
|
|
8464
|
+
if (deepEqual$1(oldTags, newTags)) return;
|
|
8465
|
+
if (!tableArn) {
|
|
8466
|
+
this.logger.warn(`Local DescribeTable returned no TableArn — cannot propagate Tags to cross-region replica ${region} of ${physicalIdForLogs}`);
|
|
8467
|
+
return;
|
|
8468
|
+
}
|
|
8469
|
+
const replicaArn = this.replicaArnForRegion(tableArn, region);
|
|
8470
|
+
if (!replicaArn) {
|
|
8471
|
+
this.logger.warn(`Could not derive replica ARN for region ${region} from ${tableArn} — skipping Tags propagation for ${physicalIdForLogs}`);
|
|
8472
|
+
return;
|
|
8473
|
+
}
|
|
8474
|
+
try {
|
|
8475
|
+
const regionalClient = this.getRegionalClient(region);
|
|
8476
|
+
await this.applyTagDiffOnClient(regionalClient, replicaArn, oldTags, newTags);
|
|
8477
|
+
} catch (tagErr) {
|
|
8478
|
+
this.logger.warn(`Could not apply Tags diff to cross-region replica ${region} of ${physicalIdForLogs}: ${tagErr instanceof Error ? tagErr.message : String(tagErr)}. The replica's Tags state will surface as drift until the next successful deploy.`);
|
|
8479
|
+
}
|
|
8480
|
+
}
|
|
8481
|
+
/**
|
|
8442
8482
|
* Apply a Tags diff against the given `DynamoDBClient` (which may be
|
|
8443
8483
|
* the local client or a per-region client returned by
|
|
8444
8484
|
* `getRegionalClient`). Used by the local-replica path AND the
|
|
8445
|
-
* cross-region replica Tags propagation path (Issue #389).
|
|
8485
|
+
* cross-region replica Tags propagation path (Issue #389 / #441).
|
|
8446
8486
|
*/
|
|
8447
8487
|
async applyTagDiffOnClient(client, tableArn, oldTagsRaw, newTagsRaw) {
|
|
8448
8488
|
const toMap = (tags) => {
|
|
@@ -8732,9 +8772,12 @@ var DynamoDBGlobalTableProvider = class {
|
|
|
8732
8772
|
*
|
|
8733
8773
|
* Per-replica sub-specifications (`ContributorInsightsSpecification` /
|
|
8734
8774
|
* `PointInTimeRecoverySpecification` / `KinesisStreamSpecification`)
|
|
8735
|
-
* are surfaced
|
|
8736
|
-
*
|
|
8737
|
-
*
|
|
8775
|
+
* are surfaced for BOTH the LOCAL replica AND cross-region replicas
|
|
8776
|
+
* via per-region SDK clients cached in `regionalClientCache` (Issue
|
|
8777
|
+
* #389 lifted the v1 LOCAL-only limitation; the per-replica reads
|
|
8778
|
+
* happen in `readReplicaSubSpecs` below). Each cross-region call is
|
|
8779
|
+
* best-effort — a permissions gap in one region omits the offending
|
|
8780
|
+
* key rather than aborting the whole drift read.
|
|
8738
8781
|
*/
|
|
8739
8782
|
async readCurrentState(physicalId, _logicalId, _resourceType) {
|
|
8740
8783
|
try {
|
|
@@ -11212,7 +11255,7 @@ var EC2Provider = class {
|
|
|
11212
11255
|
case "AWS::EC2::Instance": return this.updateInstance(logicalId, physicalId, resourceType, properties, previousProperties);
|
|
11213
11256
|
case "AWS::EC2::NetworkAcl":
|
|
11214
11257
|
case "AWS::EC2::NetworkAclEntry":
|
|
11215
|
-
case "AWS::EC2::SubnetNetworkAclAssociation": throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "
|
|
11258
|
+
case "AWS::EC2::SubnetNetworkAclAssociation": throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "AWS provides no in-place Update API for this EC2 sub-resource type; every property change requires Delete + Create. Re-deploy with cdkd deploy --replace, or destroy + redeploy.");
|
|
11216
11259
|
default: throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId, physicalId);
|
|
11217
11260
|
}
|
|
11218
11261
|
}
|
|
@@ -13727,7 +13770,7 @@ var ApiGatewayProvider = class ApiGatewayProvider {
|
|
|
13727
13770
|
* `ResourceUpdateNotSupportedError` instead of silently no-op'ing.
|
|
13728
13771
|
*/
|
|
13729
13772
|
updateDeployment(logicalId, _physicalId, _resourceType) {
|
|
13730
|
-
return Promise.reject(new ResourceUpdateNotSupportedError("AWS::ApiGateway::Deployment", logicalId, "API Gateway Deployment is immutable;
|
|
13773
|
+
return Promise.reject(new ResourceUpdateNotSupportedError("AWS::ApiGateway::Deployment", logicalId, "API Gateway Deployment is immutable on AWS — there is no UpdateDeployment API for the deployment itself (UpdateStage is for the stage that points at the deployment); every change requires CreateDeployment to produce a new immutable deployment. Re-deploy with cdkd deploy --replace, or change the resource definition to create a new Deployment."));
|
|
13731
13774
|
}
|
|
13732
13775
|
/**
|
|
13733
13776
|
* Delete an API Gateway Deployment
|
|
@@ -14520,7 +14563,7 @@ var ApiGatewayV2Provider = class {
|
|
|
14520
14563
|
case "AWS::ApiGatewayV2::Integration": return this.updateIntegration(logicalId, physicalId, resourceType, properties, previousProperties);
|
|
14521
14564
|
case "AWS::ApiGatewayV2::Route": return this.updateRoute(logicalId, physicalId, resourceType, properties, previousProperties);
|
|
14522
14565
|
case "AWS::ApiGatewayV2::Authorizer": return this.updateAuthorizer(logicalId, physicalId, resourceType, properties, previousProperties);
|
|
14523
|
-
default: throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "
|
|
14566
|
+
default: throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "Unsupported API Gateway V2 resource type for in-place update in cdkd; re-deploy with cdkd deploy --replace, or destroy + redeploy the stack.");
|
|
14524
14567
|
}
|
|
14525
14568
|
}
|
|
14526
14569
|
async delete(logicalId, physicalId, resourceType, properties, context) {
|
|
@@ -16617,7 +16660,7 @@ var ECSProvider = class {
|
|
|
16617
16660
|
}
|
|
16618
16661
|
}
|
|
16619
16662
|
async updateTaskDefinition(logicalId, _physicalId, _resourceType, _properties) {
|
|
16620
|
-
return Promise.reject(new ResourceUpdateNotSupportedError("AWS::ECS::TaskDefinition", logicalId, "TaskDefinition revisions are immutable;
|
|
16663
|
+
return Promise.reject(new ResourceUpdateNotSupportedError("AWS::ECS::TaskDefinition", logicalId, "ECS TaskDefinition revisions are immutable on AWS — there is no UpdateTaskDefinition API; every change registers a new revision via RegisterTaskDefinition. Re-deploy with cdkd deploy --replace, or destroy + redeploy the stack."));
|
|
16621
16664
|
}
|
|
16622
16665
|
async deleteTaskDefinition(logicalId, physicalId, resourceType, context) {
|
|
16623
16666
|
this.logger.debug(`Deleting ECS task definition ${logicalId}: ${physicalId}`);
|
|
@@ -17398,7 +17441,7 @@ var ELBv2Provider = class {
|
|
|
17398
17441
|
for (const [k, v] of Object.entries(p)) if (!handledKeys.has(k)) out[k] = v;
|
|
17399
17442
|
return out;
|
|
17400
17443
|
};
|
|
17401
|
-
if (JSON.stringify(stripHandled(properties)) !== JSON.stringify(stripHandled(previousProperties))) throw new ResourceUpdateNotSupportedError("AWS::ElasticLoadBalancingV2::LoadBalancer", logicalId, "ELBv2 LoadBalancer
|
|
17444
|
+
if (JSON.stringify(stripHandled(properties)) !== JSON.stringify(stripHandled(previousProperties))) throw new ResourceUpdateNotSupportedError("AWS::ElasticLoadBalancingV2::LoadBalancer", logicalId, "ELBv2 LoadBalancer Name / Type / Scheme are immutable on AWS — none of the ELBv2 Modify* / Set* APIs accept these fields; they are fixed at creation. cdkd handles LoadBalancerAttributes / Subnets / SubnetMappings / SecurityGroups / IpAddressType / Tags in-place; for Name / Type / Scheme re-deploy with cdkd deploy --replace, or destroy + redeploy the stack.");
|
|
17402
17445
|
const newAttrs = properties["LoadBalancerAttributes"] ?? [];
|
|
17403
17446
|
const oldAttrs = previousProperties["LoadBalancerAttributes"] ?? [];
|
|
17404
17447
|
const newAttrMap = new Map(newAttrs.map((a) => [a.Key, a.Value]));
|
|
@@ -23242,6 +23285,20 @@ var AppSyncProvider = class {
|
|
|
23242
23285
|
client;
|
|
23243
23286
|
providerRegion = process.env["AWS_REGION"];
|
|
23244
23287
|
logger = getLogger().child("AppSyncProvider");
|
|
23288
|
+
/**
|
|
23289
|
+
* Cache of `apiId -> GraphqlApi ARN` for the lifetime of this provider
|
|
23290
|
+
* instance. Populated lazily by `applyTagDiff` and reused on subsequent
|
|
23291
|
+
* tag-diff updates against the same API so we don't pay an extra
|
|
23292
|
+
* `GetGraphqlApi` round-trip per call. Mirrors the existing
|
|
23293
|
+
* `attributeCache` pattern used elsewhere in this provider family.
|
|
23294
|
+
*
|
|
23295
|
+
* Invalidation: the ARN of a GraphqlApi is stable for the life of the
|
|
23296
|
+
* API (it embeds the apiId), so the cache never needs to be invalidated
|
|
23297
|
+
* within a process — the only way the ARN changes is if the API itself
|
|
23298
|
+
* is replaced, in which case a new `physicalId` flows through `update()`
|
|
23299
|
+
* and the old entry simply becomes unreachable.
|
|
23300
|
+
*/
|
|
23301
|
+
arnCache = /* @__PURE__ */ new Map();
|
|
23245
23302
|
handledProperties = new Map([
|
|
23246
23303
|
["AWS::AppSync::GraphQLApi", new Set([
|
|
23247
23304
|
"Name",
|
|
@@ -23298,15 +23355,307 @@ var AppSyncProvider = class {
|
|
|
23298
23355
|
}
|
|
23299
23356
|
}
|
|
23300
23357
|
/**
|
|
23301
|
-
*
|
|
23302
|
-
*
|
|
23303
|
-
*
|
|
23304
|
-
*
|
|
23305
|
-
*
|
|
23306
|
-
*
|
|
23358
|
+
* Update an AppSync resource in-place via the SDK's `Update*` calls.
|
|
23359
|
+
*
|
|
23360
|
+
* Per-type API path:
|
|
23361
|
+
* - `GraphQLApi` → `UpdateGraphqlApiCommand` (`AuthenticationType` /
|
|
23362
|
+
* `XrayEnabled` / `LogConfig`) + `TagResource` / `UntagResource`
|
|
23363
|
+
* for `Tags` diff. `Name` is immutable on AWS.
|
|
23364
|
+
* - `DataSource` → `UpdateDataSourceCommand` (`Description` /
|
|
23365
|
+
* `ServiceRoleArn` / `DynamoDBConfig` / `LambdaConfig` / `HttpConfig`).
|
|
23366
|
+
* `ApiId` / `Name` / `Type` are immutable identity fields.
|
|
23367
|
+
* - `Resolver` → `UpdateResolverCommand` (`DataSourceName` /
|
|
23368
|
+
* `RequestMappingTemplate` / `ResponseMappingTemplate` / `Kind` /
|
|
23369
|
+
* `PipelineConfig` / `Runtime` / `Code`). `ApiId` / `TypeName` /
|
|
23370
|
+
* `FieldName` are immutable identity fields.
|
|
23371
|
+
* - `ApiKey` → `UpdateApiKeyCommand` (`Description` / `Expires`).
|
|
23372
|
+
* `ApiId` is immutable; the AWS-generated key id is immutable.
|
|
23373
|
+
* - `GraphQLSchema` → `StartSchemaCreationCommand` (re-upload the
|
|
23374
|
+
* SDL; this is the canonical AppSync schema-update path).
|
|
23375
|
+
*
|
|
23376
|
+
* Every Update* call uses `!== undefined` field gates per
|
|
23377
|
+
* memory rule `feedback_update_optional_field_undefined_check.md` so
|
|
23378
|
+
* `cdkd drift --revert` can clear a console-side ADD via an empty
|
|
23379
|
+
* string / 0 / false. Identity / immutable field changes throw
|
|
23380
|
+
* `ResourceUpdateNotSupportedError` as defense-in-depth — the deploy
|
|
23381
|
+
* engine's replacement-detection layer should normally route those
|
|
23382
|
+
* through CREATE+DELETE.
|
|
23307
23383
|
*/
|
|
23308
|
-
update(logicalId,
|
|
23309
|
-
|
|
23384
|
+
async update(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
23385
|
+
switch (resourceType) {
|
|
23386
|
+
case "AWS::AppSync::GraphQLApi": return this.updateGraphQLApi(logicalId, physicalId, resourceType, properties, previousProperties);
|
|
23387
|
+
case "AWS::AppSync::GraphQLSchema": return this.updateGraphQLSchema(logicalId, physicalId, resourceType, properties, previousProperties);
|
|
23388
|
+
case "AWS::AppSync::DataSource": return this.updateDataSource(logicalId, physicalId, resourceType, properties, previousProperties);
|
|
23389
|
+
case "AWS::AppSync::Resolver": return this.updateResolver(logicalId, physicalId, resourceType, properties, previousProperties);
|
|
23390
|
+
case "AWS::AppSync::ApiKey": return this.updateApiKey(logicalId, physicalId, resourceType, properties, previousProperties);
|
|
23391
|
+
default: throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId, physicalId);
|
|
23392
|
+
}
|
|
23393
|
+
}
|
|
23394
|
+
/**
|
|
23395
|
+
* Structural equality for the small object / array shapes that ride on
|
|
23396
|
+
* AppSync update inputs. `JSON.stringify` is sufficient because none of
|
|
23397
|
+
* these shapes contain `undefined` keys at this layer (the create /
|
|
23398
|
+
* readCurrentState paths filter them out).
|
|
23399
|
+
*/
|
|
23400
|
+
deepEqual(a, b) {
|
|
23401
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
23402
|
+
}
|
|
23403
|
+
async updateGraphQLApi(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
23404
|
+
if (properties["Name"] !== void 0 && previousProperties["Name"] !== void 0 && properties["Name"] !== previousProperties["Name"]) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "AWS AppSync GraphqlApi.Name is immutable — destroy + redeploy to rename");
|
|
23405
|
+
const newAuthType = properties["AuthenticationType"];
|
|
23406
|
+
const oldAuthType = previousProperties["AuthenticationType"];
|
|
23407
|
+
const newXray = properties["XrayEnabled"];
|
|
23408
|
+
const oldXray = previousProperties["XrayEnabled"];
|
|
23409
|
+
const newLog = properties["LogConfig"];
|
|
23410
|
+
const oldLog = previousProperties["LogConfig"];
|
|
23411
|
+
const hasXrayDiff = ("XrayEnabled" in properties || "XrayEnabled" in previousProperties) && newXray !== oldXray;
|
|
23412
|
+
const hasAuthDiff = ("AuthenticationType" in properties || "AuthenticationType" in previousProperties) && newAuthType !== oldAuthType;
|
|
23413
|
+
const hasLogDiff = ("LogConfig" in properties || "LogConfig" in previousProperties) && !this.deepEqual(newLog, oldLog);
|
|
23414
|
+
if (hasAuthDiff || hasXrayDiff || hasLogDiff) {
|
|
23415
|
+
const input = {
|
|
23416
|
+
apiId: physicalId,
|
|
23417
|
+
name: properties["Name"] ?? previousProperties["Name"],
|
|
23418
|
+
authenticationType: newAuthType ?? oldAuthType ?? "API_KEY"
|
|
23419
|
+
};
|
|
23420
|
+
if (newXray !== void 0) input.xrayEnabled = newXray;
|
|
23421
|
+
if (newLog !== void 0) input.logConfig = {
|
|
23422
|
+
cloudWatchLogsRoleArn: newLog["CloudWatchLogsRoleArn"],
|
|
23423
|
+
fieldLogLevel: newLog["FieldLogLevel"],
|
|
23424
|
+
excludeVerboseContent: newLog["ExcludeVerboseContent"]
|
|
23425
|
+
};
|
|
23426
|
+
else if (oldLog !== void 0) {
|
|
23427
|
+
const existingRoleArn = oldLog["CloudWatchLogsRoleArn"];
|
|
23428
|
+
if (existingRoleArn) input.logConfig = {
|
|
23429
|
+
cloudWatchLogsRoleArn: existingRoleArn,
|
|
23430
|
+
fieldLogLevel: "NONE"
|
|
23431
|
+
};
|
|
23432
|
+
else this.logger.warn(`AppSync GraphqlApi ${logicalId}: cannot clear LogConfig — previous state has no CloudWatchLogsRoleArn to reuse for the disable call`);
|
|
23433
|
+
}
|
|
23434
|
+
try {
|
|
23435
|
+
await this.getClient().send(new UpdateGraphqlApiCommand(input));
|
|
23436
|
+
} catch (error) {
|
|
23437
|
+
throw this.wrapUpdateError(error, resourceType, logicalId, physicalId, "GraphqlApi");
|
|
23438
|
+
}
|
|
23439
|
+
}
|
|
23440
|
+
await this.applyTagDiff(physicalId, resourceType, logicalId, previousProperties["Tags"], properties["Tags"]);
|
|
23441
|
+
return {
|
|
23442
|
+
physicalId,
|
|
23443
|
+
wasReplaced: false,
|
|
23444
|
+
attributes: {}
|
|
23445
|
+
};
|
|
23446
|
+
}
|
|
23447
|
+
async updateGraphQLSchema(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
23448
|
+
const newDef = properties["Definition"];
|
|
23449
|
+
const oldDef = previousProperties["Definition"];
|
|
23450
|
+
if (newDef === void 0 || newDef === oldDef) return {
|
|
23451
|
+
physicalId,
|
|
23452
|
+
wasReplaced: false,
|
|
23453
|
+
attributes: {}
|
|
23454
|
+
};
|
|
23455
|
+
const apiId = properties["ApiId"] ?? physicalId;
|
|
23456
|
+
try {
|
|
23457
|
+
await this.getClient().send(new StartSchemaCreationCommand({
|
|
23458
|
+
apiId,
|
|
23459
|
+
definition: Buffer.from(newDef, "utf-8")
|
|
23460
|
+
}));
|
|
23461
|
+
} catch (error) {
|
|
23462
|
+
throw this.wrapUpdateError(error, resourceType, logicalId, physicalId, "GraphqlSchema");
|
|
23463
|
+
}
|
|
23464
|
+
return {
|
|
23465
|
+
physicalId,
|
|
23466
|
+
wasReplaced: false,
|
|
23467
|
+
attributes: {}
|
|
23468
|
+
};
|
|
23469
|
+
}
|
|
23470
|
+
async updateDataSource(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
23471
|
+
for (const field of [
|
|
23472
|
+
"ApiId",
|
|
23473
|
+
"Name",
|
|
23474
|
+
"Type"
|
|
23475
|
+
]) {
|
|
23476
|
+
const next = properties[field];
|
|
23477
|
+
const prev = previousProperties[field];
|
|
23478
|
+
if (next !== void 0 && prev !== void 0 && next !== prev) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `AWS AppSync DataSource.${field} is immutable — destroy + redeploy to change`);
|
|
23479
|
+
}
|
|
23480
|
+
const [apiId, name] = physicalId.split("|");
|
|
23481
|
+
if (!apiId || !name) throw new ProvisioningError(`Invalid DataSource physical ID format: ${physicalId}`, resourceType, logicalId, physicalId);
|
|
23482
|
+
const type = properties["Type"] ?? previousProperties["Type"];
|
|
23483
|
+
const newDesc = properties["Description"];
|
|
23484
|
+
const oldDesc = previousProperties["Description"];
|
|
23485
|
+
const newRole = properties["ServiceRoleArn"];
|
|
23486
|
+
const oldRole = previousProperties["ServiceRoleArn"];
|
|
23487
|
+
const newDDB = properties["DynamoDBConfig"];
|
|
23488
|
+
const oldDDB = previousProperties["DynamoDBConfig"];
|
|
23489
|
+
const newLambda = properties["LambdaConfig"];
|
|
23490
|
+
const oldLambda = previousProperties["LambdaConfig"];
|
|
23491
|
+
const newHttp = properties["HttpConfig"];
|
|
23492
|
+
const oldHttp = previousProperties["HttpConfig"];
|
|
23493
|
+
if (!(newDesc !== oldDesc || newRole !== oldRole || !this.deepEqual(newDDB, oldDDB) || !this.deepEqual(newLambda, oldLambda) || !this.deepEqual(newHttp, oldHttp))) return {
|
|
23494
|
+
physicalId,
|
|
23495
|
+
wasReplaced: false,
|
|
23496
|
+
attributes: {}
|
|
23497
|
+
};
|
|
23498
|
+
const input = {
|
|
23499
|
+
apiId,
|
|
23500
|
+
name,
|
|
23501
|
+
type
|
|
23502
|
+
};
|
|
23503
|
+
if (newDesc !== void 0) input.description = newDesc;
|
|
23504
|
+
if (newRole !== void 0) input.serviceRoleArn = newRole;
|
|
23505
|
+
if (newDDB !== void 0) input.dynamodbConfig = {
|
|
23506
|
+
tableName: newDDB["TableName"],
|
|
23507
|
+
awsRegion: newDDB["AwsRegion"],
|
|
23508
|
+
useCallerCredentials: newDDB["UseCallerCredentials"]
|
|
23509
|
+
};
|
|
23510
|
+
if (newLambda !== void 0) input.lambdaConfig = { lambdaFunctionArn: newLambda["LambdaFunctionArn"] };
|
|
23511
|
+
if (newHttp !== void 0) input.httpConfig = { endpoint: newHttp["Endpoint"] };
|
|
23512
|
+
try {
|
|
23513
|
+
await this.getClient().send(new UpdateDataSourceCommand(input));
|
|
23514
|
+
} catch (error) {
|
|
23515
|
+
throw this.wrapUpdateError(error, resourceType, logicalId, physicalId, "DataSource");
|
|
23516
|
+
}
|
|
23517
|
+
return {
|
|
23518
|
+
physicalId,
|
|
23519
|
+
wasReplaced: false,
|
|
23520
|
+
attributes: {}
|
|
23521
|
+
};
|
|
23522
|
+
}
|
|
23523
|
+
async updateResolver(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
23524
|
+
for (const field of [
|
|
23525
|
+
"ApiId",
|
|
23526
|
+
"TypeName",
|
|
23527
|
+
"FieldName"
|
|
23528
|
+
]) {
|
|
23529
|
+
const next = properties[field];
|
|
23530
|
+
const prev = previousProperties[field];
|
|
23531
|
+
if (next !== void 0 && prev !== void 0 && next !== prev) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `AWS AppSync Resolver.${field} is immutable — destroy + redeploy to change`);
|
|
23532
|
+
}
|
|
23533
|
+
const parts = physicalId.split("|");
|
|
23534
|
+
if (parts.length < 3) throw new ProvisioningError(`Invalid Resolver physical ID format: ${physicalId}`, resourceType, logicalId, physicalId);
|
|
23535
|
+
const [apiId, typeName, fieldName] = parts;
|
|
23536
|
+
if (![
|
|
23537
|
+
"DataSourceName",
|
|
23538
|
+
"RequestMappingTemplate",
|
|
23539
|
+
"ResponseMappingTemplate",
|
|
23540
|
+
"Kind",
|
|
23541
|
+
"PipelineConfig",
|
|
23542
|
+
"Runtime",
|
|
23543
|
+
"Code"
|
|
23544
|
+
].some((key) => !this.deepEqual(properties[key], previousProperties[key]))) return {
|
|
23545
|
+
physicalId,
|
|
23546
|
+
wasReplaced: false,
|
|
23547
|
+
attributes: {}
|
|
23548
|
+
};
|
|
23549
|
+
const input = {
|
|
23550
|
+
apiId,
|
|
23551
|
+
typeName,
|
|
23552
|
+
fieldName
|
|
23553
|
+
};
|
|
23554
|
+
const effectiveKind = properties["Kind"] ?? previousProperties["Kind"] ?? "UNIT";
|
|
23555
|
+
if (effectiveKind === "UNIT" && properties["DataSourceName"] !== void 0) input.dataSourceName = properties["DataSourceName"];
|
|
23556
|
+
if (properties["RequestMappingTemplate"] !== void 0) input.requestMappingTemplate = properties["RequestMappingTemplate"];
|
|
23557
|
+
if (properties["ResponseMappingTemplate"] !== void 0) input.responseMappingTemplate = properties["ResponseMappingTemplate"];
|
|
23558
|
+
if (properties["Kind"] !== void 0) input.kind = properties["Kind"];
|
|
23559
|
+
if (effectiveKind === "PIPELINE" && properties["PipelineConfig"] !== void 0) input.pipelineConfig = { functions: properties["PipelineConfig"]["Functions"] };
|
|
23560
|
+
if (properties["Runtime"] !== void 0) {
|
|
23561
|
+
const runtime = properties["Runtime"];
|
|
23562
|
+
input.runtime = {
|
|
23563
|
+
name: runtime["Name"],
|
|
23564
|
+
runtimeVersion: runtime["RuntimeVersion"]
|
|
23565
|
+
};
|
|
23566
|
+
}
|
|
23567
|
+
if (properties["Code"] !== void 0) input.code = properties["Code"];
|
|
23568
|
+
try {
|
|
23569
|
+
await this.getClient().send(new UpdateResolverCommand(input));
|
|
23570
|
+
} catch (error) {
|
|
23571
|
+
throw this.wrapUpdateError(error, resourceType, logicalId, physicalId, "Resolver");
|
|
23572
|
+
}
|
|
23573
|
+
return {
|
|
23574
|
+
physicalId,
|
|
23575
|
+
wasReplaced: false,
|
|
23576
|
+
attributes: {}
|
|
23577
|
+
};
|
|
23578
|
+
}
|
|
23579
|
+
async updateApiKey(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
23580
|
+
if (properties["ApiId"] !== void 0 && previousProperties["ApiId"] !== void 0 && properties["ApiId"] !== previousProperties["ApiId"]) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "AWS AppSync ApiKey.ApiId is immutable — destroy + redeploy to change");
|
|
23581
|
+
const [apiId, apiKeyId] = physicalId.split("|");
|
|
23582
|
+
if (!apiId || !apiKeyId) throw new ProvisioningError(`Invalid ApiKey physical ID format: ${physicalId}`, resourceType, logicalId, physicalId);
|
|
23583
|
+
const newDesc = properties["Description"];
|
|
23584
|
+
const oldDesc = previousProperties["Description"];
|
|
23585
|
+
const newExp = properties["Expires"];
|
|
23586
|
+
const oldExp = previousProperties["Expires"];
|
|
23587
|
+
if (newDesc === oldDesc && newExp === oldExp) return {
|
|
23588
|
+
physicalId,
|
|
23589
|
+
wasReplaced: false,
|
|
23590
|
+
attributes: {}
|
|
23591
|
+
};
|
|
23592
|
+
const input = {
|
|
23593
|
+
apiId,
|
|
23594
|
+
id: apiKeyId
|
|
23595
|
+
};
|
|
23596
|
+
if (newDesc !== void 0) input.description = newDesc;
|
|
23597
|
+
if (newExp !== void 0) input.expires = newExp;
|
|
23598
|
+
try {
|
|
23599
|
+
await this.getClient().send(new UpdateApiKeyCommand(input));
|
|
23600
|
+
} catch (error) {
|
|
23601
|
+
throw this.wrapUpdateError(error, resourceType, logicalId, physicalId, "ApiKey");
|
|
23602
|
+
}
|
|
23603
|
+
return {
|
|
23604
|
+
physicalId,
|
|
23605
|
+
wasReplaced: false,
|
|
23606
|
+
attributes: {}
|
|
23607
|
+
};
|
|
23608
|
+
}
|
|
23609
|
+
/**
|
|
23610
|
+
* Apply a Tags diff to a GraphqlApi via TagResource / UntagResource.
|
|
23611
|
+
*
|
|
23612
|
+
* Tags are keyed by the GraphqlApi ARN — recover it from
|
|
23613
|
+
* `GetGraphqlApi`. Failure to recover the ARN is a hard error (the API
|
|
23614
|
+
* itself just changed) rather than a silent drop, so the user knows
|
|
23615
|
+
* the tag diff was not applied.
|
|
23616
|
+
*/
|
|
23617
|
+
async applyTagDiff(apiId, resourceType, logicalId, oldTags, newTags) {
|
|
23618
|
+
const oldMap = this.tagsToMap(oldTags ?? []);
|
|
23619
|
+
const newMap = this.tagsToMap(newTags ?? []);
|
|
23620
|
+
if (this.deepEqual(oldMap, newMap)) return;
|
|
23621
|
+
let arn = this.arnCache.get(apiId);
|
|
23622
|
+
if (!arn) {
|
|
23623
|
+
try {
|
|
23624
|
+
arn = (await this.getClient().send(new GetGraphqlApiCommand({ apiId }))).graphqlApi?.arn;
|
|
23625
|
+
} catch (error) {
|
|
23626
|
+
throw this.wrapUpdateError(error, resourceType, logicalId, apiId, "GraphqlApi");
|
|
23627
|
+
}
|
|
23628
|
+
if (!arn) throw new ProvisioningError(`Could not resolve ARN for AppSync GraphqlApi ${apiId} to apply tags diff`, resourceType, logicalId, apiId);
|
|
23629
|
+
this.arnCache.set(apiId, arn);
|
|
23630
|
+
}
|
|
23631
|
+
const tagKeysToRemove = Object.keys(oldMap).filter((k) => !(k in newMap));
|
|
23632
|
+
const tagsToAdd = {};
|
|
23633
|
+
for (const [k, v] of Object.entries(newMap)) if (oldMap[k] !== v) tagsToAdd[k] = v;
|
|
23634
|
+
if (tagKeysToRemove.length > 0) try {
|
|
23635
|
+
await this.getClient().send(new UntagResourceCommand$12({
|
|
23636
|
+
resourceArn: arn,
|
|
23637
|
+
tagKeys: tagKeysToRemove
|
|
23638
|
+
}));
|
|
23639
|
+
} catch (error) {
|
|
23640
|
+
throw this.wrapUpdateError(error, resourceType, logicalId, apiId, "GraphqlApi (untag)");
|
|
23641
|
+
}
|
|
23642
|
+
if (Object.keys(tagsToAdd).length > 0) try {
|
|
23643
|
+
await this.getClient().send(new TagResourceCommand$13({
|
|
23644
|
+
resourceArn: arn,
|
|
23645
|
+
tags: tagsToAdd
|
|
23646
|
+
}));
|
|
23647
|
+
} catch (error) {
|
|
23648
|
+
throw this.wrapUpdateError(error, resourceType, logicalId, apiId, "GraphqlApi (tag)");
|
|
23649
|
+
}
|
|
23650
|
+
}
|
|
23651
|
+
tagsToMap(tags) {
|
|
23652
|
+
const out = {};
|
|
23653
|
+
for (const t of tags) if (t.Key !== void 0 && t.Value !== void 0) out[t.Key] = t.Value;
|
|
23654
|
+
return out;
|
|
23655
|
+
}
|
|
23656
|
+
wrapUpdateError(error, resourceType, logicalId, physicalId, subType) {
|
|
23657
|
+
const cause = error instanceof Error ? error : void 0;
|
|
23658
|
+
return new ProvisioningError(`Failed to update AppSync ${subType} ${logicalId}: ${error instanceof Error ? error.message : String(error)}`, resourceType, logicalId, physicalId, cause);
|
|
23310
23659
|
}
|
|
23311
23660
|
async delete(logicalId, physicalId, resourceType, _properties, context) {
|
|
23312
23661
|
switch (resourceType) {
|
|
@@ -24528,7 +24877,7 @@ var GlueSecurityConfigurationProvider = class {
|
|
|
24528
24877
|
}
|
|
24529
24878
|
}
|
|
24530
24879
|
async update(logicalId, _physicalId, resourceType, _properties, _previousProperties) {
|
|
24531
|
-
throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "AWS
|
|
24880
|
+
throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "AWS Glue SecurityConfiguration is immutable on AWS — there is no UpdateSecurityConfiguration API; every change requires DeleteSecurityConfiguration + CreateSecurityConfiguration. Use cdkd deploy --replace, or destroy + redeploy with the new EncryptionConfiguration.");
|
|
24532
24881
|
}
|
|
24533
24882
|
async delete(logicalId, physicalId, resourceType, _properties, context) {
|
|
24534
24883
|
this.logger.debug(`Deleting Glue SecurityConfiguration ${logicalId}: ${physicalId}`);
|
|
@@ -26393,7 +26742,7 @@ var KinesisStreamConsumerProvider = class {
|
|
|
26393
26742
|
const oldConsumerName = previousProperties["ConsumerName"];
|
|
26394
26743
|
const newStreamArn = properties["StreamARN"];
|
|
26395
26744
|
const oldStreamArn = previousProperties["StreamARN"];
|
|
26396
|
-
if (newConsumerName !== oldConsumerName || newStreamArn !== oldStreamArn) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "AWS::Kinesis::StreamConsumer ConsumerName / StreamARN are immutable;
|
|
26745
|
+
if (newConsumerName !== oldConsumerName || newStreamArn !== oldStreamArn) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "AWS::Kinesis::StreamConsumer ConsumerName / StreamARN are immutable on AWS — there is no UpdateStreamConsumer API; every change registers a new consumer (RegisterStreamConsumer). Re-deploy with cdkd deploy --replace, or destroy + redeploy.");
|
|
26397
26746
|
await this.applyTagDiff(physicalId, previousProperties["Tags"], properties["Tags"]);
|
|
26398
26747
|
let attrs = {};
|
|
26399
26748
|
try {
|
|
@@ -26508,14 +26857,14 @@ var KinesisStreamConsumerProvider = class {
|
|
|
26508
26857
|
const tagsToRemove = [];
|
|
26509
26858
|
for (const k of Object.keys(oldMap)) if (!(k in newMap)) tagsToRemove.push(k);
|
|
26510
26859
|
if (tagsToRemove.length > 0) {
|
|
26511
|
-
await this.getClient().send(new UntagResourceCommand$
|
|
26860
|
+
await this.getClient().send(new UntagResourceCommand$13({
|
|
26512
26861
|
ResourceARN: consumerArn,
|
|
26513
26862
|
TagKeys: tagsToRemove
|
|
26514
26863
|
}));
|
|
26515
26864
|
this.logger.debug(`Removed ${tagsToRemove.length} tag(s) from Kinesis stream consumer ${consumerArn}`);
|
|
26516
26865
|
}
|
|
26517
26866
|
if (Object.keys(tagsToAdd).length > 0) {
|
|
26518
|
-
await this.getClient().send(new TagResourceCommand$
|
|
26867
|
+
await this.getClient().send(new TagResourceCommand$14({
|
|
26519
26868
|
ResourceARN: consumerArn,
|
|
26520
26869
|
Tags: tagsToAdd
|
|
26521
26870
|
}));
|
|
@@ -26623,7 +26972,7 @@ var EFSProvider = class {
|
|
|
26623
26972
|
switch (resourceType) {
|
|
26624
26973
|
case "AWS::EFS::FileSystem": return this.updateFileSystem(logicalId, physicalId, resourceType, properties, previousProperties);
|
|
26625
26974
|
case "AWS::EFS::MountTarget": return this.updateMountTarget(logicalId, physicalId, resourceType, properties);
|
|
26626
|
-
case "AWS::EFS::AccessPoint": return Promise.reject(new ResourceUpdateNotSupportedError(resourceType, logicalId, "EFS AccessPoint is
|
|
26975
|
+
case "AWS::EFS::AccessPoint": return Promise.reject(new ResourceUpdateNotSupportedError(resourceType, logicalId, "AWS EFS AccessPoint has no in-place update API — there is no UpdateAccessPoint command; every property change requires DeleteAccessPoint + CreateAccessPoint. Re-deploy with cdkd deploy --replace, or destroy + redeploy the stack."));
|
|
26627
26976
|
default: throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId, physicalId);
|
|
26628
26977
|
}
|
|
26629
26978
|
}
|
|
@@ -26635,7 +26984,7 @@ var EFSProvider = class {
|
|
|
26635
26984
|
]) {
|
|
26636
26985
|
const next = properties[key];
|
|
26637
26986
|
const prev = previousProperties[key];
|
|
26638
|
-
if (next !== void 0 && prev !== void 0 && JSON.stringify(next) !== JSON.stringify(prev)) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `EFS FileSystem ${key} is immutable;
|
|
26987
|
+
if (next !== void 0 && prev !== void 0 && JSON.stringify(next) !== JSON.stringify(prev)) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, `AWS EFS FileSystem ${key} is immutable on AWS — UpdateFileSystem does not accept ${key}; the property is fixed at creation. Re-deploy with cdkd deploy --replace, or destroy + redeploy the stack.`);
|
|
26639
26988
|
}
|
|
26640
26989
|
const newThroughputMode = properties["ThroughputMode"];
|
|
26641
26990
|
const newProvisioned = properties["ProvisionedThroughputInMibps"];
|
|
@@ -27276,15 +27625,19 @@ var FirehoseProvider = class {
|
|
|
27276
27625
|
}
|
|
27277
27626
|
}
|
|
27278
27627
|
/**
|
|
27279
|
-
* Firehose delivery streams are treated as immutable by cdkd.
|
|
27280
|
-
*
|
|
27281
|
-
*
|
|
27282
|
-
*
|
|
27283
|
-
*
|
|
27284
|
-
*
|
|
27628
|
+
* Firehose delivery streams are treated as immutable by cdkd. AWS DOES
|
|
27629
|
+
* provide an `UpdateDestination` API, but the per-destination shape
|
|
27630
|
+
* matrix (Extended S3 / Redshift / OpenSearch / Splunk / HttpEndpoint /
|
|
27631
|
+
* Iceberg / etc.) is deep enough that the deploy engine's immutable-
|
|
27632
|
+
* property replacement path covers the common cases more reliably.
|
|
27633
|
+
* Treating the type as fully immutable for `cdkd drift --revert` is
|
|
27634
|
+
* the conservative choice; users who want in-place destination updates
|
|
27635
|
+
* should re-deploy with `cdkd deploy --replace` so the new shape is
|
|
27636
|
+
* applied via a fresh `CreateDeliveryStream`. Tracked as a follow-up
|
|
27637
|
+
* to issue (#443).
|
|
27285
27638
|
*/
|
|
27286
27639
|
update(logicalId, _physicalId, resourceType, _properties, _previousProperties) {
|
|
27287
|
-
return Promise.reject(new ResourceUpdateNotSupportedError(resourceType, logicalId, "
|
|
27640
|
+
return Promise.reject(new ResourceUpdateNotSupportedError(resourceType, logicalId, "AWS::KinesisFirehose::DeliveryStream in-place update is not implemented in cdkd; AWS provides UpdateDestination but the per-destination shape matrix is large. Re-deploy with cdkd deploy --replace, or destroy + redeploy the stack."));
|
|
27288
27641
|
}
|
|
27289
27642
|
/**
|
|
27290
27643
|
* Delete a Firehose delivery stream
|
|
@@ -29787,10 +30140,10 @@ var ASGProvider = class {
|
|
|
29787
30140
|
if (resourceType !== "AWS::AutoScaling::AutoScalingGroup") throw new ProvisioningError(`Unsupported resource type: ${resourceType}`, resourceType, logicalId, physicalId);
|
|
29788
30141
|
this.logger.debug(`Updating AutoScalingGroup ${logicalId}: ${physicalId}`);
|
|
29789
30142
|
const stringEq = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
29790
|
-
if (!stringEq(properties["AutoScalingGroupName"], previousProperties["AutoScalingGroupName"])) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "AutoScalingGroupName is immutable;
|
|
29791
|
-
if (!stringEq(properties["Tags"] ?? [], previousProperties["Tags"] ?? [])) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "Tags updates on AWS::AutoScaling::AutoScalingGroup are not yet
|
|
29792
|
-
if (!stringEq(properties["LoadBalancerNames"] ?? [], previousProperties["LoadBalancerNames"] ?? [])) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "LoadBalancerNames diffs
|
|
29793
|
-
if (!stringEq(properties["TargetGroupARNs"] ?? [], previousProperties["TargetGroupARNs"] ?? [])) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "TargetGroupARNs diffs
|
|
30143
|
+
if (!stringEq(properties["AutoScalingGroupName"], previousProperties["AutoScalingGroupName"])) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "AutoScalingGroupName is immutable on AWS — UpdateAutoScalingGroup does not accept a new name; the name is fixed at creation. Use cdkd deploy --replace to replace the group.");
|
|
30144
|
+
if (!stringEq(properties["Tags"] ?? [], previousProperties["Tags"] ?? [])) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "Tags updates on AWS::AutoScaling::AutoScalingGroup are not yet implemented in cdkd (AWS exposes CreateOrUpdateTags / DeleteTags); use cdkd deploy --replace, or update the tags via AWS console / CLI.");
|
|
30145
|
+
if (!stringEq(properties["LoadBalancerNames"] ?? [], previousProperties["LoadBalancerNames"] ?? [])) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "LoadBalancerNames diffs on AWS::AutoScaling::AutoScalingGroup are not yet implemented in cdkd (AWS exposes AttachLoadBalancers / DetachLoadBalancers); use cdkd deploy --replace.");
|
|
30146
|
+
if (!stringEq(properties["TargetGroupARNs"] ?? [], previousProperties["TargetGroupARNs"] ?? [])) throw new ResourceUpdateNotSupportedError(resourceType, logicalId, "TargetGroupARNs diffs on AWS::AutoScaling::AutoScalingGroup are not yet implemented in cdkd (AWS exposes AttachLoadBalancerTargetGroups / DetachLoadBalancerTargetGroups); use cdkd deploy --replace.");
|
|
29794
30147
|
try {
|
|
29795
30148
|
await this.applyMetricsCollectionDiff(physicalId, properties["MetricsCollection"], previousProperties["MetricsCollection"]);
|
|
29796
30149
|
await this.applyLifecycleHooksDiff(physicalId, properties["LifecycleHookSpecificationList"], previousProperties["LifecycleHookSpecificationList"]);
|
|
@@ -45721,7 +46074,7 @@ function reorderArgs(argv) {
|
|
|
45721
46074
|
*/
|
|
45722
46075
|
async function main() {
|
|
45723
46076
|
const program = new Command();
|
|
45724
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.117.
|
|
46077
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.117.2");
|
|
45725
46078
|
program.addCommand(createBootstrapCommand());
|
|
45726
46079
|
program.addCommand(createSynthCommand());
|
|
45727
46080
|
program.addCommand(createListCommand());
|