@go-to-k/cdkd 0.44.0 → 0.46.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 +747 -195
- package/dist/cli.js.map +3 -3
- package/dist/go-to-k-cdkd-0.46.0.tgz +0 -0
- package/dist/index.js +55 -3
- package/dist/index.js.map +2 -2
- package/package.json +1 -1
- package/dist/go-to-k-cdkd-0.44.0.tgz +0 -0
package/dist/cli.js
CHANGED
|
@@ -1187,6 +1187,22 @@ var PartialFailureError = class _PartialFailureError extends CdkdError {
|
|
|
1187
1187
|
Object.setPrototypeOf(this, _PartialFailureError.prototype);
|
|
1188
1188
|
}
|
|
1189
1189
|
};
|
|
1190
|
+
var ResourceUpdateNotSupportedError = class _ResourceUpdateNotSupportedError extends CdkdError {
|
|
1191
|
+
constructor(resourceType, logicalId, suggestion, cause) {
|
|
1192
|
+
const tail = suggestion ? suggestion : "use cdkd deploy with --replace, or change the resource definition to create a new version";
|
|
1193
|
+
super(
|
|
1194
|
+
`${resourceType} (${logicalId}) cannot be updated in place: ${tail}.`,
|
|
1195
|
+
"RESOURCE_UPDATE_NOT_SUPPORTED",
|
|
1196
|
+
cause
|
|
1197
|
+
);
|
|
1198
|
+
this.resourceType = resourceType;
|
|
1199
|
+
this.logicalId = logicalId;
|
|
1200
|
+
this.suggestion = suggestion;
|
|
1201
|
+
this.name = "ResourceUpdateNotSupportedError";
|
|
1202
|
+
Object.setPrototypeOf(this, _ResourceUpdateNotSupportedError.prototype);
|
|
1203
|
+
}
|
|
1204
|
+
exitCode = 2;
|
|
1205
|
+
};
|
|
1190
1206
|
function isCdkdError(error) {
|
|
1191
1207
|
return error instanceof CdkdError;
|
|
1192
1208
|
}
|
|
@@ -8494,6 +8510,31 @@ function matchesCdkPath(tags, cdkPath) {
|
|
|
8494
8510
|
}
|
|
8495
8511
|
return false;
|
|
8496
8512
|
}
|
|
8513
|
+
function normalizeAwsTagsToCfn(tags) {
|
|
8514
|
+
if (!tags)
|
|
8515
|
+
return [];
|
|
8516
|
+
const out = [];
|
|
8517
|
+
if (Array.isArray(tags)) {
|
|
8518
|
+
for (const t of tags) {
|
|
8519
|
+
const obj = t;
|
|
8520
|
+
const k = (typeof obj["Key"] === "string" ? obj["Key"] : void 0) ?? (typeof obj["TagKey"] === "string" ? obj["TagKey"] : void 0) ?? (typeof obj["key"] === "string" ? obj["key"] : void 0);
|
|
8521
|
+
const v = (typeof obj["Value"] === "string" ? obj["Value"] : void 0) ?? (typeof obj["TagValue"] === "string" ? obj["TagValue"] : void 0) ?? (typeof obj["value"] === "string" ? obj["value"] : void 0);
|
|
8522
|
+
if (typeof k !== "string" || k.length === 0)
|
|
8523
|
+
continue;
|
|
8524
|
+
if (k.startsWith("aws:"))
|
|
8525
|
+
continue;
|
|
8526
|
+
out.push({ Key: k, Value: typeof v === "string" ? v : "" });
|
|
8527
|
+
}
|
|
8528
|
+
} else {
|
|
8529
|
+
for (const [k, v] of Object.entries(tags)) {
|
|
8530
|
+
if (!k || k.startsWith("aws:"))
|
|
8531
|
+
continue;
|
|
8532
|
+
out.push({ Key: k, Value: typeof v === "string" ? v : "" });
|
|
8533
|
+
}
|
|
8534
|
+
}
|
|
8535
|
+
out.sort((a, b) => a.Key < b.Key ? -1 : a.Key > b.Key ? 1 : 0);
|
|
8536
|
+
return out;
|
|
8537
|
+
}
|
|
8497
8538
|
|
|
8498
8539
|
// src/provisioning/providers/iam-role-provider.ts
|
|
8499
8540
|
var IAMRoleProvider = class {
|
|
@@ -9053,9 +9094,10 @@ var IAMRoleProvider = class {
|
|
|
9053
9094
|
* costs one extra `GetRolePolicy` per inline policy. Out of scope for
|
|
9054
9095
|
* v1 — drift detection on inline IAM policy bodies can ship in a
|
|
9055
9096
|
* follow-up.
|
|
9056
|
-
* - `Tags` is
|
|
9057
|
-
*
|
|
9058
|
-
*
|
|
9097
|
+
* - `Tags` is surfaced via `ListRoleTags` (paginated). CDK's `aws:*`
|
|
9098
|
+
* auto-tags are filtered out by `normalizeAwsTagsToCfn` so they don't
|
|
9099
|
+
* fire false-positive drift; the result key is omitted entirely when
|
|
9100
|
+
* AWS reports no user tags (matches `create()`'s behavior).
|
|
9059
9101
|
*
|
|
9060
9102
|
* Returns `undefined` when the role is gone (`NoSuchEntityException`).
|
|
9061
9103
|
*/
|
|
@@ -9105,6 +9147,32 @@ var IAMRoleProvider = class {
|
|
|
9105
9147
|
if (!(err instanceof NoSuchEntityException))
|
|
9106
9148
|
throw err;
|
|
9107
9149
|
}
|
|
9150
|
+
try {
|
|
9151
|
+
const collected = [];
|
|
9152
|
+
let marker;
|
|
9153
|
+
while (true) {
|
|
9154
|
+
const tagsResp = await this.iamClient.send(
|
|
9155
|
+
new ListRoleTagsCommand({
|
|
9156
|
+
RoleName: physicalId,
|
|
9157
|
+
...marker ? { Marker: marker } : {}
|
|
9158
|
+
})
|
|
9159
|
+
);
|
|
9160
|
+
if (tagsResp.Tags) {
|
|
9161
|
+
for (const t of tagsResp.Tags) {
|
|
9162
|
+
collected.push({ Key: t.Key, Value: t.Value });
|
|
9163
|
+
}
|
|
9164
|
+
}
|
|
9165
|
+
if (!tagsResp.IsTruncated)
|
|
9166
|
+
break;
|
|
9167
|
+
marker = tagsResp.Marker;
|
|
9168
|
+
}
|
|
9169
|
+
const tags = normalizeAwsTagsToCfn(collected);
|
|
9170
|
+
if (tags.length > 0)
|
|
9171
|
+
result["Tags"] = tags;
|
|
9172
|
+
} catch (err) {
|
|
9173
|
+
if (!(err instanceof NoSuchEntityException))
|
|
9174
|
+
throw err;
|
|
9175
|
+
}
|
|
9108
9176
|
return result;
|
|
9109
9177
|
}
|
|
9110
9178
|
/**
|
|
@@ -12110,14 +12178,9 @@ var S3BucketProvider = class {
|
|
|
12110
12178
|
}
|
|
12111
12179
|
try {
|
|
12112
12180
|
const resp = await this.s3Client.send(new GetBucketTaggingCommand({ Bucket: physicalId }));
|
|
12113
|
-
|
|
12114
|
-
|
|
12115
|
-
|
|
12116
|
-
Value: t.Value
|
|
12117
|
-
}));
|
|
12118
|
-
if (tags.length > 0)
|
|
12119
|
-
result["Tags"] = tags;
|
|
12120
|
-
}
|
|
12181
|
+
const tags = normalizeAwsTagsToCfn(resp.TagSet);
|
|
12182
|
+
if (tags.length > 0)
|
|
12183
|
+
result["Tags"] = tags;
|
|
12121
12184
|
} catch (err) {
|
|
12122
12185
|
const e = err;
|
|
12123
12186
|
if (e.name !== "NoSuchTagSet") {
|
|
@@ -12726,9 +12789,11 @@ var SQSQueueProvider = class {
|
|
|
12726
12789
|
* `QueueName` is derived from the URL tail (the `physicalId` is the
|
|
12727
12790
|
* queue URL), not surfaced by `GetQueueAttributes`.
|
|
12728
12791
|
*
|
|
12729
|
-
* `Tags` is
|
|
12730
|
-
*
|
|
12731
|
-
*
|
|
12792
|
+
* `Tags` is surfaced via `ListQueueTags` (returns a tag-name → value map).
|
|
12793
|
+
* CDK's `aws:*` auto-tags are filtered out by `normalizeAwsTagsToCfn`; the
|
|
12794
|
+
* result key is omitted entirely when AWS reports no user tags (matches
|
|
12795
|
+
* `create()`'s behavior of only sending Tags when the template carries
|
|
12796
|
+
* them).
|
|
12732
12797
|
*
|
|
12733
12798
|
* Returns `undefined` when the queue is gone (`QueueDoesNotExist`).
|
|
12734
12799
|
*/
|
|
@@ -12796,6 +12861,18 @@ var SQSQueueProvider = class {
|
|
|
12796
12861
|
result["RedrivePolicy"] = attributes["RedrivePolicy"];
|
|
12797
12862
|
}
|
|
12798
12863
|
}
|
|
12864
|
+
try {
|
|
12865
|
+
const tagsResp = await this.sqsClient.send(
|
|
12866
|
+
new ListQueueTagsCommand({ QueueUrl: physicalId })
|
|
12867
|
+
);
|
|
12868
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.Tags);
|
|
12869
|
+
if (tags.length > 0)
|
|
12870
|
+
result["Tags"] = tags;
|
|
12871
|
+
} catch (err) {
|
|
12872
|
+
if (err instanceof QueueDoesNotExist)
|
|
12873
|
+
return void 0;
|
|
12874
|
+
throw err;
|
|
12875
|
+
}
|
|
12799
12876
|
return result;
|
|
12800
12877
|
}
|
|
12801
12878
|
/**
|
|
@@ -13415,11 +13492,16 @@ var SNSTopicProvider = class {
|
|
|
13415
13492
|
* `TopicName` is derived from the ARN tail (the `physicalId` is the
|
|
13416
13493
|
* topic ARN).
|
|
13417
13494
|
*
|
|
13418
|
-
* `Tags`
|
|
13419
|
-
* `
|
|
13420
|
-
*
|
|
13421
|
-
*
|
|
13422
|
-
*
|
|
13495
|
+
* `Tags` is surfaced via a follow-up `ListTagsForResource` call. CDK's
|
|
13496
|
+
* `aws:*` auto-tags are filtered out by `normalizeAwsTagsToCfn`; the
|
|
13497
|
+
* result key is omitted entirely when AWS reports no user tags (matches
|
|
13498
|
+
* `create()`'s behavior of only sending Tags when the template carries
|
|
13499
|
+
* them).
|
|
13500
|
+
*
|
|
13501
|
+
* `DeliveryStatusLogging` is intentionally omitted: it fans out into
|
|
13502
|
+
* per-protocol attributes (`{Protocol}SuccessFeedbackRoleArn`, etc.) whose
|
|
13503
|
+
* round-trip back to the CFn array shape needs more thought than fits in
|
|
13504
|
+
* this PR.
|
|
13423
13505
|
*
|
|
13424
13506
|
* `Subscription` is omitted because CDK manages it via separate
|
|
13425
13507
|
* `AWS::SNS::Subscription` resources, not as a Topic property.
|
|
@@ -13472,6 +13554,18 @@ var SNSTopicProvider = class {
|
|
|
13472
13554
|
}
|
|
13473
13555
|
}
|
|
13474
13556
|
}
|
|
13557
|
+
try {
|
|
13558
|
+
const tagsResp = await this.snsClient.send(
|
|
13559
|
+
new ListTagsForResourceCommand({ ResourceArn: physicalId })
|
|
13560
|
+
);
|
|
13561
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.Tags);
|
|
13562
|
+
if (tags.length > 0)
|
|
13563
|
+
result["Tags"] = tags;
|
|
13564
|
+
} catch (err) {
|
|
13565
|
+
if (err instanceof NotFoundException)
|
|
13566
|
+
return void 0;
|
|
13567
|
+
throw err;
|
|
13568
|
+
}
|
|
13475
13569
|
return result;
|
|
13476
13570
|
}
|
|
13477
13571
|
/**
|
|
@@ -14675,11 +14769,13 @@ var LambdaFunctionProvider = class {
|
|
|
14675
14769
|
* function's `CodeSha256` does live in `GetFunction` but is not what
|
|
14676
14770
|
* cdkd's `Code: { S3Bucket, S3Key }` state property carries).
|
|
14677
14771
|
*
|
|
14678
|
-
* `Tags` is
|
|
14679
|
-
*
|
|
14680
|
-
*
|
|
14681
|
-
*
|
|
14682
|
-
*
|
|
14772
|
+
* `Tags` is surfaced from the `Tags` map on the same `GetFunction`
|
|
14773
|
+
* response. CDK's auto-injected `aws:cdk:*` tags (which AWS happily
|
|
14774
|
+
* returns) are filtered out by `normalizeAwsTagsToCfn` so they don't
|
|
14775
|
+
* fire false-positive drift against state. The result key is omitted
|
|
14776
|
+
* entirely when AWS reports no user tags, matching `create()`'s
|
|
14777
|
+
* behavior of only sending `Tags` when the user explicitly passes
|
|
14778
|
+
* them.
|
|
14683
14779
|
*
|
|
14684
14780
|
* Returns `undefined` when the function is gone (`ResourceNotFoundException`).
|
|
14685
14781
|
*/
|
|
@@ -14737,6 +14833,9 @@ var LambdaFunctionProvider = class {
|
|
|
14737
14833
|
if (Object.keys(vpc).length > 0)
|
|
14738
14834
|
result["VpcConfig"] = vpc;
|
|
14739
14835
|
}
|
|
14836
|
+
const tags = normalizeAwsTagsToCfn(resp.Tags);
|
|
14837
|
+
if (tags.length > 0)
|
|
14838
|
+
result["Tags"] = tags;
|
|
14740
14839
|
return result;
|
|
14741
14840
|
} catch (err) {
|
|
14742
14841
|
if (err instanceof ResourceNotFoundException)
|
|
@@ -16219,10 +16318,12 @@ var DynamoDBTableProvider = class {
|
|
|
16219
16318
|
*
|
|
16220
16319
|
* Returns `undefined` when the table is gone (`ResourceNotFoundException`).
|
|
16221
16320
|
*
|
|
16222
|
-
* Tags are
|
|
16223
|
-
*
|
|
16224
|
-
*
|
|
16225
|
-
*
|
|
16321
|
+
* Tags are surfaced via a follow-up `ListTagsOfResource` call (DynamoDB
|
|
16322
|
+
* doesn't include tags in `DescribeTable`). CDK's `aws:*` auto-tags are
|
|
16323
|
+
* filtered out by `normalizeAwsTagsToCfn` so they don't fire false-positive
|
|
16324
|
+
* drift, and the result key is omitted entirely when AWS reports no user
|
|
16325
|
+
* tags (matches `create()`'s behavior of only sending Tags when the
|
|
16326
|
+
* template carries them).
|
|
16226
16327
|
*/
|
|
16227
16328
|
async readCurrentState(physicalId, _logicalId, _resourceType) {
|
|
16228
16329
|
try {
|
|
@@ -16279,6 +16380,20 @@ var DynamoDBTableProvider = class {
|
|
|
16279
16380
|
if (table.TableClassSummary?.TableClass) {
|
|
16280
16381
|
result["TableClass"] = table.TableClassSummary.TableClass;
|
|
16281
16382
|
}
|
|
16383
|
+
if (table.TableArn) {
|
|
16384
|
+
try {
|
|
16385
|
+
const tagsResp = await this.dynamoDBClient.send(
|
|
16386
|
+
new ListTagsOfResourceCommand({ ResourceArn: table.TableArn })
|
|
16387
|
+
);
|
|
16388
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.Tags);
|
|
16389
|
+
if (tags.length > 0)
|
|
16390
|
+
result["Tags"] = tags;
|
|
16391
|
+
} catch (err) {
|
|
16392
|
+
if (err instanceof ResourceNotFoundException6)
|
|
16393
|
+
return void 0;
|
|
16394
|
+
throw err;
|
|
16395
|
+
}
|
|
16396
|
+
}
|
|
16282
16397
|
return result;
|
|
16283
16398
|
} catch (err) {
|
|
16284
16399
|
if (err instanceof ResourceNotFoundException6)
|
|
@@ -16600,11 +16715,16 @@ var LogsLogGroupProvider = class {
|
|
|
16600
16715
|
* `RetentionInDays`).
|
|
16601
16716
|
*
|
|
16602
16717
|
* Coverage: `LogGroupName`, `KmsKeyId`, `RetentionInDays`,
|
|
16603
|
-
* `LogGroupClass`. Other handledProperties (`DataProtectionPolicy`,
|
|
16604
|
-
* `
|
|
16718
|
+
* `LogGroupClass`, `Tags`. Other handledProperties (`DataProtectionPolicy`,
|
|
16719
|
+
* `FieldIndexPolicies`, `ResourcePolicyDocument`,
|
|
16605
16720
|
* `DeletionProtectionEnabled`, `BearerTokenAuthenticationEnabled`) need
|
|
16606
16721
|
* their own per-property API call and are out of scope for v1.
|
|
16607
16722
|
*
|
|
16723
|
+
* Tags are read via `ListTagsForResource` (using the log-group ARN from
|
|
16724
|
+
* the same `DescribeLogGroups` response). CDK's `aws:*` auto-tags are
|
|
16725
|
+
* filtered out so they don't fire false-positive drift; the result key is
|
|
16726
|
+
* omitted entirely when AWS reports no user tags.
|
|
16727
|
+
*
|
|
16608
16728
|
* Returns `undefined` when the log group is gone.
|
|
16609
16729
|
*/
|
|
16610
16730
|
async readCurrentState(physicalId, _logicalId, _resourceType) {
|
|
@@ -16625,6 +16745,21 @@ var LogsLogGroupProvider = class {
|
|
|
16625
16745
|
}
|
|
16626
16746
|
if (found.logGroupClass !== void 0)
|
|
16627
16747
|
result["LogGroupClass"] = found.logGroupClass;
|
|
16748
|
+
if (found.arn) {
|
|
16749
|
+
const arnForTags = found.arn.replace(/:\*$/, "");
|
|
16750
|
+
try {
|
|
16751
|
+
const tagsResp = await this.logsClient.send(
|
|
16752
|
+
new ListTagsForResourceCommand2({ resourceArn: arnForTags })
|
|
16753
|
+
);
|
|
16754
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.tags);
|
|
16755
|
+
if (tags.length > 0)
|
|
16756
|
+
result["Tags"] = tags;
|
|
16757
|
+
} catch (err) {
|
|
16758
|
+
if (err instanceof ResourceNotFoundException7)
|
|
16759
|
+
return void 0;
|
|
16760
|
+
throw err;
|
|
16761
|
+
}
|
|
16762
|
+
}
|
|
16628
16763
|
return result;
|
|
16629
16764
|
} catch (err) {
|
|
16630
16765
|
if (err instanceof ResourceNotFoundException7)
|
|
@@ -16994,6 +17129,20 @@ var CloudWatchAlarmProvider = class {
|
|
|
16994
17129
|
if (alarm.Metrics && alarm.Metrics.length > 0) {
|
|
16995
17130
|
result["Metrics"] = alarm.Metrics.map((m) => m);
|
|
16996
17131
|
}
|
|
17132
|
+
if (alarm.AlarmArn) {
|
|
17133
|
+
try {
|
|
17134
|
+
const tagsResp = await this.cloudWatchClient.send(
|
|
17135
|
+
new ListTagsForResourceCommand3({ ResourceARN: alarm.AlarmArn })
|
|
17136
|
+
);
|
|
17137
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.Tags);
|
|
17138
|
+
if (tags.length > 0)
|
|
17139
|
+
result["Tags"] = tags;
|
|
17140
|
+
} catch (err) {
|
|
17141
|
+
this.logger.debug(
|
|
17142
|
+
`CloudWatch ListTagsForResource(${alarm.AlarmArn}) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
17143
|
+
);
|
|
17144
|
+
}
|
|
17145
|
+
}
|
|
16997
17146
|
return result;
|
|
16998
17147
|
}
|
|
16999
17148
|
async import(input) {
|
|
@@ -17332,8 +17481,10 @@ var SecretsManagerSecretProvider = class {
|
|
|
17332
17481
|
* call to avoid surfacing plaintext through drift). Cdkd state holds
|
|
17333
17482
|
* the user-supplied string verbatim; comparing against AWS would
|
|
17334
17483
|
* require pulling the value, so this is deliberately deferred.
|
|
17335
|
-
*
|
|
17336
|
-
*
|
|
17484
|
+
*
|
|
17485
|
+
* `Tags` is surfaced from the same `DescribeSecret` response (no extra
|
|
17486
|
+
* round-trip). CDK's `aws:*` auto-tags are filtered out; the result key
|
|
17487
|
+
* is omitted entirely when AWS reports no user tags.
|
|
17337
17488
|
*
|
|
17338
17489
|
* Returns `undefined` when the secret is gone (`ResourceNotFoundException`).
|
|
17339
17490
|
*/
|
|
@@ -17358,6 +17509,9 @@ var SecretsManagerSecretProvider = class {
|
|
|
17358
17509
|
return out;
|
|
17359
17510
|
});
|
|
17360
17511
|
}
|
|
17512
|
+
const tags = normalizeAwsTagsToCfn(resp.Tags);
|
|
17513
|
+
if (tags.length > 0)
|
|
17514
|
+
result["Tags"] = tags;
|
|
17361
17515
|
return result;
|
|
17362
17516
|
} catch (err) {
|
|
17363
17517
|
if (err instanceof ResourceNotFoundException8)
|
|
@@ -17644,12 +17798,12 @@ var SSMParameterProvider = class {
|
|
|
17644
17798
|
* metadata (`Description`, `AllowedPattern`, `Tier`) that `GetParameter`
|
|
17645
17799
|
* does not return.
|
|
17646
17800
|
*
|
|
17647
|
-
* `Name` is set to the physical id. `Tags`
|
|
17648
|
-
*
|
|
17649
|
-
*
|
|
17650
|
-
* `Policies`
|
|
17651
|
-
*
|
|
17652
|
-
*
|
|
17801
|
+
* `Name` is set to the physical id. `Tags` is surfaced via a follow-up
|
|
17802
|
+
* `ListTagsForResource(ResourceType=Parameter)` call, with CDK's `aws:*`
|
|
17803
|
+
* auto-tags filtered out. `Policies` is intentionally out of scope:
|
|
17804
|
+
* `DescribeParameters.Policies` returns a structured array but cdkd state
|
|
17805
|
+
* holds the raw JSON string the user typed — comparing the two accurately
|
|
17806
|
+
* needs more work.
|
|
17653
17807
|
*
|
|
17654
17808
|
* **Note**: For `SecureString` parameters, AWS returns the encrypted
|
|
17655
17809
|
* blob in `Value` (we pass `WithDecryption: false`). cdkd state usually
|
|
@@ -17701,6 +17855,18 @@ var SSMParameterProvider = class {
|
|
|
17701
17855
|
}
|
|
17702
17856
|
} catch {
|
|
17703
17857
|
}
|
|
17858
|
+
try {
|
|
17859
|
+
const tagsResp = await this.ssmClient.send(
|
|
17860
|
+
new ListTagsForResourceCommand4({
|
|
17861
|
+
ResourceType: "Parameter",
|
|
17862
|
+
ResourceId: physicalId
|
|
17863
|
+
})
|
|
17864
|
+
);
|
|
17865
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.TagList);
|
|
17866
|
+
if (tags.length > 0)
|
|
17867
|
+
result["Tags"] = tags;
|
|
17868
|
+
} catch {
|
|
17869
|
+
}
|
|
17704
17870
|
return result;
|
|
17705
17871
|
}
|
|
17706
17872
|
/**
|
|
@@ -18044,8 +18210,10 @@ var EventBridgeRuleProvider = class {
|
|
|
18044
18210
|
* it as the user typed it, typically an object), `ScheduleExpression`,
|
|
18045
18211
|
* `State`, `RoleArn`, `Targets` (CFn shape `[{Id, Arn, ...}]`).
|
|
18046
18212
|
*
|
|
18047
|
-
* `Tags` is
|
|
18048
|
-
*
|
|
18213
|
+
* `Tags` is surfaced via a follow-up `ListTagsForResource` call (using the
|
|
18214
|
+
* rule ARN — the same `physicalId` cdkd state holds). CDK's `aws:*`
|
|
18215
|
+
* auto-tags are filtered out; the result key is omitted entirely when AWS
|
|
18216
|
+
* reports no user tags.
|
|
18049
18217
|
*
|
|
18050
18218
|
* Returns `undefined` when the rule is gone (`ResourceNotFoundException`).
|
|
18051
18219
|
*/
|
|
@@ -18103,6 +18271,18 @@ var EventBridgeRuleProvider = class {
|
|
|
18103
18271
|
throw err;
|
|
18104
18272
|
}
|
|
18105
18273
|
}
|
|
18274
|
+
try {
|
|
18275
|
+
const tagsResp = await this.eventBridgeClient.send(
|
|
18276
|
+
new ListTagsForResourceCommand5({ ResourceARN: physicalId })
|
|
18277
|
+
);
|
|
18278
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.Tags);
|
|
18279
|
+
if (tags.length > 0)
|
|
18280
|
+
result["Tags"] = tags;
|
|
18281
|
+
} catch (err) {
|
|
18282
|
+
if (!(err instanceof ResourceNotFoundException9)) {
|
|
18283
|
+
throw err;
|
|
18284
|
+
}
|
|
18285
|
+
}
|
|
18106
18286
|
return result;
|
|
18107
18287
|
}
|
|
18108
18288
|
/**
|
|
@@ -18473,10 +18653,13 @@ var EventBridgeBusProvider = class {
|
|
|
18473
18653
|
* the user typed it, which may be either an object or a string — the
|
|
18474
18654
|
* comparator handles either side).
|
|
18475
18655
|
*
|
|
18476
|
-
* `Tags`
|
|
18477
|
-
*
|
|
18478
|
-
*
|
|
18479
|
-
*
|
|
18656
|
+
* `Tags` is surfaced via a follow-up `ListTagsForResource` call (using the
|
|
18657
|
+
* bus ARN from the same `DescribeEventBus` response). CDK's `aws:*`
|
|
18658
|
+
* auto-tags are filtered out; the result key is omitted when AWS reports
|
|
18659
|
+
* no user tags.
|
|
18660
|
+
*
|
|
18661
|
+
* `EventSourceName` is intentionally omitted: it is set at create time
|
|
18662
|
+
* only and not surfaced by `DescribeEventBus`.
|
|
18480
18663
|
*
|
|
18481
18664
|
* Returns `undefined` when the bus is gone (`ResourceNotFoundException`).
|
|
18482
18665
|
*/
|
|
@@ -18504,6 +18687,20 @@ var EventBridgeBusProvider = class {
|
|
|
18504
18687
|
result["Policy"] = resp.Policy;
|
|
18505
18688
|
}
|
|
18506
18689
|
}
|
|
18690
|
+
if (resp.Arn) {
|
|
18691
|
+
try {
|
|
18692
|
+
const tagsResp = await this.eventBridgeClient.send(
|
|
18693
|
+
new ListTagsForResourceCommand6({ ResourceARN: resp.Arn })
|
|
18694
|
+
);
|
|
18695
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.Tags);
|
|
18696
|
+
if (tags.length > 0)
|
|
18697
|
+
result["Tags"] = tags;
|
|
18698
|
+
} catch (err) {
|
|
18699
|
+
if (err instanceof ResourceNotFoundException10)
|
|
18700
|
+
return void 0;
|
|
18701
|
+
throw err;
|
|
18702
|
+
}
|
|
18703
|
+
}
|
|
18507
18704
|
return result;
|
|
18508
18705
|
} catch (err) {
|
|
18509
18706
|
if (err instanceof ResourceNotFoundException10)
|
|
@@ -21335,20 +21532,22 @@ var ApiGatewayProvider = class _ApiGatewayProvider {
|
|
|
21335
21532
|
}
|
|
21336
21533
|
}
|
|
21337
21534
|
/**
|
|
21338
|
-
* Update an API Gateway Authorizer
|
|
21535
|
+
* Update an API Gateway Authorizer.
|
|
21339
21536
|
*
|
|
21340
|
-
*
|
|
21341
|
-
*
|
|
21537
|
+
* AWS exposes `UpdateAuthorizer` (PATCH) but cdkd does not yet plumb the
|
|
21538
|
+
* patch-operations builder through. Authorizers are recreated by the
|
|
21539
|
+
* deploy engine's immutable-property replacement path. `cdkd drift
|
|
21540
|
+
* --revert` surfaces a clear "use --replace or re-deploy" message
|
|
21541
|
+
* instead of silently no-op'ing the revert.
|
|
21342
21542
|
*/
|
|
21343
|
-
updateAuthorizer(logicalId,
|
|
21344
|
-
|
|
21345
|
-
|
|
21346
|
-
|
|
21347
|
-
|
|
21348
|
-
|
|
21349
|
-
|
|
21350
|
-
|
|
21351
|
-
});
|
|
21543
|
+
updateAuthorizer(logicalId, _physicalId, _resourceType) {
|
|
21544
|
+
return Promise.reject(
|
|
21545
|
+
new ResourceUpdateNotSupportedError(
|
|
21546
|
+
"AWS::ApiGateway::Authorizer",
|
|
21547
|
+
logicalId,
|
|
21548
|
+
"API Gateway Authorizer updates are not yet implemented in cdkd; re-deploy with cdkd deploy --replace, or destroy + redeploy the stack"
|
|
21549
|
+
)
|
|
21550
|
+
);
|
|
21352
21551
|
}
|
|
21353
21552
|
/**
|
|
21354
21553
|
* Delete an API Gateway Authorizer
|
|
@@ -21580,20 +21779,20 @@ var ApiGatewayProvider = class _ApiGatewayProvider {
|
|
|
21580
21779
|
}
|
|
21581
21780
|
}
|
|
21582
21781
|
/**
|
|
21583
|
-
* Update an API Gateway Deployment
|
|
21782
|
+
* Update an API Gateway Deployment.
|
|
21584
21783
|
*
|
|
21585
|
-
* Deployments are immutable
|
|
21586
|
-
*
|
|
21784
|
+
* Deployments are immutable — every property change requires a fresh
|
|
21785
|
+
* Deployment. `cdkd drift --revert` therefore throws
|
|
21786
|
+
* `ResourceUpdateNotSupportedError` instead of silently no-op'ing.
|
|
21587
21787
|
*/
|
|
21588
|
-
updateDeployment(logicalId,
|
|
21589
|
-
|
|
21590
|
-
|
|
21591
|
-
|
|
21592
|
-
|
|
21593
|
-
|
|
21594
|
-
|
|
21595
|
-
|
|
21596
|
-
});
|
|
21788
|
+
updateDeployment(logicalId, _physicalId, _resourceType) {
|
|
21789
|
+
return Promise.reject(
|
|
21790
|
+
new ResourceUpdateNotSupportedError(
|
|
21791
|
+
"AWS::ApiGateway::Deployment",
|
|
21792
|
+
logicalId,
|
|
21793
|
+
"API Gateway Deployment is immutable; re-deploy with cdkd deploy --replace, or change the resource definition to create a new Deployment"
|
|
21794
|
+
)
|
|
21795
|
+
);
|
|
21597
21796
|
}
|
|
21598
21797
|
/**
|
|
21599
21798
|
* Delete an API Gateway Deployment
|
|
@@ -21894,17 +22093,22 @@ var ApiGatewayProvider = class _ApiGatewayProvider {
|
|
|
21894
22093
|
}
|
|
21895
22094
|
}
|
|
21896
22095
|
/**
|
|
21897
|
-
* Update an API Gateway Method
|
|
22096
|
+
* Update an API Gateway Method.
|
|
21898
22097
|
*
|
|
21899
|
-
*
|
|
22098
|
+
* AWS exposes `UpdateMethod` (PATCH) but cdkd does not yet plumb the
|
|
22099
|
+
* patch-operations builder through. Methods are recreated by the deploy
|
|
22100
|
+
* engine's immutable-property replacement path. `cdkd drift --revert`
|
|
22101
|
+
* surfaces a clear "use --replace or re-deploy" message instead of
|
|
22102
|
+
* silently no-op'ing the revert.
|
|
21900
22103
|
*/
|
|
21901
|
-
updateMethod(logicalId,
|
|
21902
|
-
|
|
21903
|
-
|
|
21904
|
-
|
|
21905
|
-
|
|
21906
|
-
|
|
21907
|
-
|
|
22104
|
+
updateMethod(logicalId, _physicalId) {
|
|
22105
|
+
return Promise.reject(
|
|
22106
|
+
new ResourceUpdateNotSupportedError(
|
|
22107
|
+
"AWS::ApiGateway::Method",
|
|
22108
|
+
logicalId,
|
|
22109
|
+
"API Gateway Method updates are not yet implemented in cdkd; re-deploy with cdkd deploy --replace, or destroy + redeploy the stack"
|
|
22110
|
+
)
|
|
22111
|
+
);
|
|
21908
22112
|
}
|
|
21909
22113
|
/**
|
|
21910
22114
|
* Delete an API Gateway Method
|
|
@@ -22282,13 +22486,23 @@ var ApiGatewayV2Provider = class {
|
|
|
22282
22486
|
);
|
|
22283
22487
|
}
|
|
22284
22488
|
}
|
|
22285
|
-
|
|
22286
|
-
|
|
22287
|
-
|
|
22288
|
-
|
|
22289
|
-
|
|
22290
|
-
|
|
22291
|
-
|
|
22489
|
+
/**
|
|
22490
|
+
* HTTP API resources are treated as immutable by cdkd: the deploy engine
|
|
22491
|
+
* recreates them on property changes via the immutable-property
|
|
22492
|
+
* replacement path. AWS does expose `UpdateApi` / `UpdateRoute` /
|
|
22493
|
+
* `UpdateIntegration` / `UpdateStage` / `UpdateAuthorizer`, but cdkd
|
|
22494
|
+
* does not yet plumb them through. `cdkd drift --revert` surfaces a
|
|
22495
|
+
* clear "use --replace or re-deploy" message instead of silently
|
|
22496
|
+
* no-op'ing the revert.
|
|
22497
|
+
*/
|
|
22498
|
+
update(logicalId, _physicalId, resourceType, _properties, _previousProperties) {
|
|
22499
|
+
return Promise.reject(
|
|
22500
|
+
new ResourceUpdateNotSupportedError(
|
|
22501
|
+
resourceType,
|
|
22502
|
+
logicalId,
|
|
22503
|
+
"API Gateway V2 (HTTP API) resources are recreated on property changes; re-deploy with cdkd deploy --replace, or destroy + redeploy the stack"
|
|
22504
|
+
)
|
|
22505
|
+
);
|
|
22292
22506
|
}
|
|
22293
22507
|
async delete(logicalId, physicalId, resourceType, properties, context) {
|
|
22294
22508
|
switch (resourceType) {
|
|
@@ -22785,6 +22999,9 @@ var ApiGatewayV2Provider = class {
|
|
|
22785
22999
|
}
|
|
22786
23000
|
if (resp.CorsConfiguration)
|
|
22787
23001
|
result["CorsConfiguration"] = resp.CorsConfiguration;
|
|
23002
|
+
const tags = normalizeAwsTagsToCfn(resp.Tags);
|
|
23003
|
+
if (tags.length > 0)
|
|
23004
|
+
result["Tags"] = tags;
|
|
22788
23005
|
return result;
|
|
22789
23006
|
} catch (err) {
|
|
22790
23007
|
if (err instanceof NotFoundException4)
|
|
@@ -22964,6 +23181,7 @@ import {
|
|
|
22964
23181
|
CreateCloudFrontOriginAccessIdentityCommand,
|
|
22965
23182
|
DeleteCloudFrontOriginAccessIdentityCommand,
|
|
22966
23183
|
GetCloudFrontOriginAccessIdentityCommand as GetCloudFrontOriginAccessIdentityCommand2,
|
|
23184
|
+
UpdateCloudFrontOriginAccessIdentityCommand,
|
|
22967
23185
|
NoSuchCloudFrontOriginAccessIdentity
|
|
22968
23186
|
} from "@aws-sdk/client-cloudfront";
|
|
22969
23187
|
init_aws_clients();
|
|
@@ -23019,17 +23237,61 @@ var CloudFrontOAIProvider = class {
|
|
|
23019
23237
|
}
|
|
23020
23238
|
}
|
|
23021
23239
|
/**
|
|
23022
|
-
* Update a CloudFront Origin Access Identity
|
|
23240
|
+
* Update a CloudFront Origin Access Identity.
|
|
23241
|
+
*
|
|
23242
|
+
* Only the `Comment` field is mutable on an OAI; `CallerReference` is set
|
|
23243
|
+
* by cdkd at create time and cannot be changed. AWS exposes a single
|
|
23244
|
+
* `UpdateCloudFrontOriginAccessIdentity` call that requires the current
|
|
23245
|
+
* `ETag` (fetched via `GetCloudFrontOriginAccessIdentity`) and overwrites
|
|
23246
|
+
* the entire `CloudFrontOriginAccessIdentityConfig`.
|
|
23023
23247
|
*
|
|
23024
|
-
*
|
|
23025
|
-
*
|
|
23248
|
+
* Used by `cdkd drift --revert` to push the cdkd-state Comment back into
|
|
23249
|
+
* AWS; on the normal deploy path this is also exercised when a user
|
|
23250
|
+
* tweaks the Comment in their CDK code.
|
|
23026
23251
|
*/
|
|
23027
|
-
update(logicalId, physicalId,
|
|
23028
|
-
this.logger.debug(`
|
|
23029
|
-
|
|
23030
|
-
|
|
23031
|
-
|
|
23032
|
-
|
|
23252
|
+
async update(logicalId, physicalId, resourceType, properties, _previousProperties) {
|
|
23253
|
+
this.logger.debug(`Updating CloudFront OAI ${logicalId}: ${physicalId}`);
|
|
23254
|
+
const config = properties["CloudFrontOriginAccessIdentityConfig"];
|
|
23255
|
+
const comment = config?.["Comment"] ?? "";
|
|
23256
|
+
try {
|
|
23257
|
+
const getResponse = await this.cloudFrontClient.send(
|
|
23258
|
+
new GetCloudFrontOriginAccessIdentityCommand2({ Id: physicalId })
|
|
23259
|
+
);
|
|
23260
|
+
const etag = getResponse.ETag;
|
|
23261
|
+
if (!etag) {
|
|
23262
|
+
throw new Error("GetCloudFrontOriginAccessIdentity did not return ETag");
|
|
23263
|
+
}
|
|
23264
|
+
await this.cloudFrontClient.send(
|
|
23265
|
+
new UpdateCloudFrontOriginAccessIdentityCommand({
|
|
23266
|
+
Id: physicalId,
|
|
23267
|
+
IfMatch: etag,
|
|
23268
|
+
CloudFrontOriginAccessIdentityConfig: {
|
|
23269
|
+
// CallerReference is immutable; preserve whatever the OAI was
|
|
23270
|
+
// created with so AWS does not reject the update.
|
|
23271
|
+
CallerReference: getResponse.CloudFrontOriginAccessIdentity?.CloudFrontOriginAccessIdentityConfig?.CallerReference ?? logicalId,
|
|
23272
|
+
Comment: comment
|
|
23273
|
+
}
|
|
23274
|
+
})
|
|
23275
|
+
);
|
|
23276
|
+
this.logger.debug(`Successfully updated CloudFront OAI ${logicalId}`);
|
|
23277
|
+
return {
|
|
23278
|
+
physicalId,
|
|
23279
|
+
wasReplaced: false,
|
|
23280
|
+
attributes: {
|
|
23281
|
+
Id: physicalId,
|
|
23282
|
+
S3CanonicalUserId: getResponse.CloudFrontOriginAccessIdentity?.S3CanonicalUserId
|
|
23283
|
+
}
|
|
23284
|
+
};
|
|
23285
|
+
} catch (error) {
|
|
23286
|
+
const cause = error instanceof Error ? error : void 0;
|
|
23287
|
+
throw new ProvisioningError(
|
|
23288
|
+
`Failed to update CloudFront OAI ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
23289
|
+
resourceType,
|
|
23290
|
+
logicalId,
|
|
23291
|
+
physicalId,
|
|
23292
|
+
cause
|
|
23293
|
+
);
|
|
23294
|
+
}
|
|
23033
23295
|
}
|
|
23034
23296
|
/**
|
|
23035
23297
|
* Delete a CloudFront Origin Access Identity
|
|
@@ -24190,8 +24452,9 @@ var StepFunctionsProvider = class {
|
|
|
24190
24452
|
* time and not surfaced by `DescribeStateMachine` (the response carries
|
|
24191
24453
|
* the already-substituted definition).
|
|
24192
24454
|
*
|
|
24193
|
-
* `Tags` is
|
|
24194
|
-
* `aws
|
|
24455
|
+
* `Tags` is surfaced via a follow-up `ListTagsForResource(arn)` call.
|
|
24456
|
+
* CDK's `aws:*` auto-tags are filtered out; the result key is omitted
|
|
24457
|
+
* entirely when AWS reports no user tags.
|
|
24195
24458
|
*
|
|
24196
24459
|
* Returns `undefined` when the state machine is gone (`StateMachineDoesNotExist`).
|
|
24197
24460
|
*/
|
|
@@ -24259,6 +24522,17 @@ var StepFunctionsProvider = class {
|
|
|
24259
24522
|
if (Object.keys(ec).length > 0)
|
|
24260
24523
|
result["EncryptionConfiguration"] = ec;
|
|
24261
24524
|
}
|
|
24525
|
+
try {
|
|
24526
|
+
const tagsResp = await this.getClient().send(
|
|
24527
|
+
new ListTagsForResourceCommand8({ resourceArn: physicalId })
|
|
24528
|
+
);
|
|
24529
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.tags);
|
|
24530
|
+
if (tags.length > 0)
|
|
24531
|
+
result["Tags"] = tags;
|
|
24532
|
+
} catch (err) {
|
|
24533
|
+
if (!(err instanceof StateMachineDoesNotExist))
|
|
24534
|
+
throw err;
|
|
24535
|
+
}
|
|
24262
24536
|
return result;
|
|
24263
24537
|
}
|
|
24264
24538
|
/**
|
|
@@ -25100,8 +25374,11 @@ var ECSProvider = class {
|
|
|
25100
25374
|
* - `AWS::ECS::TaskDefinition` → `DescribeTaskDefinition`
|
|
25101
25375
|
*
|
|
25102
25376
|
* Each branch surfaces only the keys cdkd's `create()` accepts, mapping
|
|
25103
|
-
* the SDK's camelCase to CFn PascalCase. Tags are
|
|
25104
|
-
* (
|
|
25377
|
+
* the SDK's camelCase to CFn PascalCase. Tags are surfaced via
|
|
25378
|
+
* `DescribeClusters/Services(include=[TAGS])` for cluster / service, and
|
|
25379
|
+
* via `DescribeTaskDefinition(include=[TAGS])` for task definitions —
|
|
25380
|
+
* with CDK's `aws:*` auto-tags filtered out. Tag-result keys are omitted
|
|
25381
|
+
* when AWS reports no user tags.
|
|
25105
25382
|
*/
|
|
25106
25383
|
async readCurrentState(physicalId, _logicalId, resourceType) {
|
|
25107
25384
|
switch (resourceType) {
|
|
@@ -25119,7 +25396,7 @@ var ECSProvider = class {
|
|
|
25119
25396
|
let resp;
|
|
25120
25397
|
try {
|
|
25121
25398
|
resp = await this.getClient().send(
|
|
25122
|
-
new DescribeClustersCommand({ clusters: [physicalId] })
|
|
25399
|
+
new DescribeClustersCommand({ clusters: [physicalId], include: ["TAGS"] })
|
|
25123
25400
|
);
|
|
25124
25401
|
} catch {
|
|
25125
25402
|
return void 0;
|
|
@@ -25142,6 +25419,9 @@ var ECSProvider = class {
|
|
|
25142
25419
|
Value: s.value
|
|
25143
25420
|
}));
|
|
25144
25421
|
}
|
|
25422
|
+
const tags = normalizeAwsTagsToCfn(c.tags);
|
|
25423
|
+
if (tags.length > 0)
|
|
25424
|
+
result["Tags"] = tags;
|
|
25145
25425
|
return result;
|
|
25146
25426
|
}
|
|
25147
25427
|
async readCurrentStateService(physicalId) {
|
|
@@ -25153,7 +25433,11 @@ var ECSProvider = class {
|
|
|
25153
25433
|
let resp;
|
|
25154
25434
|
try {
|
|
25155
25435
|
resp = await this.getClient().send(
|
|
25156
|
-
new DescribeServicesCommand({
|
|
25436
|
+
new DescribeServicesCommand({
|
|
25437
|
+
cluster: clusterArn,
|
|
25438
|
+
services: [serviceName],
|
|
25439
|
+
include: ["TAGS"]
|
|
25440
|
+
})
|
|
25157
25441
|
);
|
|
25158
25442
|
} catch {
|
|
25159
25443
|
return void 0;
|
|
@@ -25206,13 +25490,16 @@ var ECSProvider = class {
|
|
|
25206
25490
|
if (s.serviceRegistries && s.serviceRegistries.length > 0) {
|
|
25207
25491
|
result["ServiceRegistries"] = s.serviceRegistries;
|
|
25208
25492
|
}
|
|
25493
|
+
const tags = normalizeAwsTagsToCfn(s.tags);
|
|
25494
|
+
if (tags.length > 0)
|
|
25495
|
+
result["Tags"] = tags;
|
|
25209
25496
|
return result;
|
|
25210
25497
|
}
|
|
25211
25498
|
async readCurrentStateTaskDefinition(physicalId) {
|
|
25212
25499
|
let resp;
|
|
25213
25500
|
try {
|
|
25214
25501
|
resp = await this.getClient().send(
|
|
25215
|
-
new DescribeTaskDefinitionCommand({ taskDefinition: physicalId })
|
|
25502
|
+
new DescribeTaskDefinitionCommand({ taskDefinition: physicalId, include: ["TAGS"] })
|
|
25216
25503
|
);
|
|
25217
25504
|
} catch {
|
|
25218
25505
|
return void 0;
|
|
@@ -25255,6 +25542,9 @@ var ECSProvider = class {
|
|
|
25255
25542
|
if (td.containerDefinitions && td.containerDefinitions.length > 0) {
|
|
25256
25543
|
result["ContainerDefinitions"] = td.containerDefinitions;
|
|
25257
25544
|
}
|
|
25545
|
+
const tags = normalizeAwsTagsToCfn(resp.tags);
|
|
25546
|
+
if (tags.length > 0)
|
|
25547
|
+
result["Tags"] = tags;
|
|
25258
25548
|
return result;
|
|
25259
25549
|
}
|
|
25260
25550
|
/**
|
|
@@ -25570,34 +25860,14 @@ var ELBv2Provider = class {
|
|
|
25570
25860
|
);
|
|
25571
25861
|
}
|
|
25572
25862
|
}
|
|
25573
|
-
|
|
25574
|
-
|
|
25575
|
-
|
|
25576
|
-
|
|
25577
|
-
new DescribeLoadBalancersCommand2({ LoadBalancerArns: [physicalId] })
|
|
25578
|
-
);
|
|
25579
|
-
const lb = describeResponse.LoadBalancers?.[0];
|
|
25580
|
-
return {
|
|
25581
|
-
physicalId,
|
|
25582
|
-
wasReplaced: false,
|
|
25583
|
-
attributes: {
|
|
25584
|
-
DNSName: lb?.DNSName,
|
|
25585
|
-
CanonicalHostedZoneID: lb?.CanonicalHostedZoneId,
|
|
25586
|
-
LoadBalancerArn: physicalId,
|
|
25587
|
-
LoadBalancerFullName: physicalId.split("/").slice(1).join("/"),
|
|
25588
|
-
LoadBalancerName: lb?.LoadBalancerName
|
|
25589
|
-
}
|
|
25590
|
-
};
|
|
25591
|
-
} catch (error) {
|
|
25592
|
-
const cause = error instanceof Error ? error : void 0;
|
|
25593
|
-
throw new ProvisioningError(
|
|
25594
|
-
`Failed to update LoadBalancer ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
|
|
25595
|
-
resourceType,
|
|
25863
|
+
updateLoadBalancer(logicalId, _physicalId, _resourceType, _properties) {
|
|
25864
|
+
return Promise.reject(
|
|
25865
|
+
new ResourceUpdateNotSupportedError(
|
|
25866
|
+
"AWS::ElasticLoadBalancingV2::LoadBalancer",
|
|
25596
25867
|
logicalId,
|
|
25597
|
-
|
|
25598
|
-
|
|
25599
|
-
|
|
25600
|
-
}
|
|
25868
|
+
"ELBv2 LoadBalancer in-place updates are not yet implemented in cdkd; re-deploy with cdkd deploy --replace, or destroy + redeploy the stack"
|
|
25869
|
+
)
|
|
25870
|
+
);
|
|
25601
25871
|
}
|
|
25602
25872
|
async deleteLoadBalancer(logicalId, physicalId, resourceType, context) {
|
|
25603
25873
|
this.logger.debug(`Deleting LoadBalancer ${logicalId}: ${physicalId}`);
|
|
@@ -25903,8 +26173,11 @@ var ELBv2Provider = class {
|
|
|
25903
26173
|
* - `Listener` → `DescribeListeners` (LoadBalancerArn, Certificates,
|
|
25904
26174
|
* DefaultActions, Port, Protocol, SslPolicy).
|
|
25905
26175
|
*
|
|
25906
|
-
* Tags are
|
|
25907
|
-
*
|
|
26176
|
+
* Tags are surfaced via a follow-up `DescribeTags(ResourceArns=[arn])`
|
|
26177
|
+
* for all three types (the `physicalId` cdkd state holds is the ARN).
|
|
26178
|
+
* CDK's `aws:*` auto-tags are filtered out and the result key is omitted
|
|
26179
|
+
* when AWS reports no user tags. Returns `undefined` when the resource
|
|
26180
|
+
* is gone (`*NotFoundException`).
|
|
25908
26181
|
*/
|
|
25909
26182
|
async readCurrentState(physicalId, _logicalId, resourceType) {
|
|
25910
26183
|
switch (resourceType) {
|
|
@@ -25951,6 +26224,7 @@ var ELBv2Provider = class {
|
|
|
25951
26224
|
result["Type"] = lb.Type;
|
|
25952
26225
|
if (lb.IpAddressType !== void 0)
|
|
25953
26226
|
result["IpAddressType"] = lb.IpAddressType;
|
|
26227
|
+
await this.attachTags(result, physicalId);
|
|
25954
26228
|
return result;
|
|
25955
26229
|
}
|
|
25956
26230
|
async readTargetGroup(physicalId) {
|
|
@@ -26009,6 +26283,7 @@ var ELBv2Provider = class {
|
|
|
26009
26283
|
if (Object.keys(matcher).length > 0)
|
|
26010
26284
|
result["Matcher"] = matcher;
|
|
26011
26285
|
}
|
|
26286
|
+
await this.attachTags(result, physicalId);
|
|
26012
26287
|
return result;
|
|
26013
26288
|
}
|
|
26014
26289
|
async readListener(physicalId) {
|
|
@@ -26050,8 +26325,23 @@ var ELBv2Provider = class {
|
|
|
26050
26325
|
(a) => a
|
|
26051
26326
|
);
|
|
26052
26327
|
}
|
|
26328
|
+
await this.attachTags(result, physicalId);
|
|
26053
26329
|
return result;
|
|
26054
26330
|
}
|
|
26331
|
+
/** Best-effort tag fetch via `DescribeTags(ResourceArns=[arn])`. */
|
|
26332
|
+
async attachTags(result, arn) {
|
|
26333
|
+
try {
|
|
26334
|
+
const resp = await this.getClient().send(new DescribeTagsCommand({ ResourceArns: [arn] }));
|
|
26335
|
+
const tagDesc = resp.TagDescriptions?.[0];
|
|
26336
|
+
const tags = normalizeAwsTagsToCfn(tagDesc?.Tags);
|
|
26337
|
+
if (tags.length > 0)
|
|
26338
|
+
result["Tags"] = tags;
|
|
26339
|
+
} catch (err) {
|
|
26340
|
+
this.logger.debug(
|
|
26341
|
+
`ELBv2 DescribeTags(${arn}) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
26342
|
+
);
|
|
26343
|
+
}
|
|
26344
|
+
}
|
|
26055
26345
|
/**
|
|
26056
26346
|
* Adopt an existing ELBv2 LoadBalancer or TargetGroup into cdkd state.
|
|
26057
26347
|
*
|
|
@@ -26806,8 +27096,10 @@ var RDSProvider = class {
|
|
|
26806
27096
|
*
|
|
26807
27097
|
* Each branch surfaces only the keys cdkd's `create()` accepts. Sensitive
|
|
26808
27098
|
* fields like `MasterUserPassword` are NEVER surfaced (RDS does not return
|
|
26809
|
-
* them in the Describe responses). `Tags` are
|
|
26810
|
-
* (
|
|
27099
|
+
* them in the Describe responses). `Tags` are surfaced via a follow-up
|
|
27100
|
+
* `ListTagsForResource(ResourceName=arn)` call (RDS uses `[{Key, Value}]`
|
|
27101
|
+
* shape). CDK's `aws:*` auto-tags are filtered out; the result key is
|
|
27102
|
+
* omitted entirely when AWS reports no user tags.
|
|
26811
27103
|
*
|
|
26812
27104
|
* Returns `undefined` when the resource is gone (`*NotFoundFault`).
|
|
26813
27105
|
*/
|
|
@@ -26851,6 +27143,8 @@ var RDSProvider = class {
|
|
|
26851
27143
|
if (inst.PubliclyAccessible !== void 0) {
|
|
26852
27144
|
result["PubliclyAccessible"] = inst.PubliclyAccessible;
|
|
26853
27145
|
}
|
|
27146
|
+
if (inst.DBInstanceArn)
|
|
27147
|
+
await this.attachTags(result, inst.DBInstanceArn);
|
|
26854
27148
|
return result;
|
|
26855
27149
|
}
|
|
26856
27150
|
async readCurrentStateDBCluster(physicalId) {
|
|
@@ -26907,6 +27201,8 @@ var RDSProvider = class {
|
|
|
26907
27201
|
if (Object.keys(sc).length > 0)
|
|
26908
27202
|
result["ServerlessV2ScalingConfiguration"] = sc;
|
|
26909
27203
|
}
|
|
27204
|
+
if (cluster.DBClusterArn)
|
|
27205
|
+
await this.attachTags(result, cluster.DBClusterArn);
|
|
26910
27206
|
return result;
|
|
26911
27207
|
}
|
|
26912
27208
|
async readCurrentStateDBSubnetGroup(physicalId) {
|
|
@@ -26934,8 +27230,31 @@ var RDSProvider = class {
|
|
|
26934
27230
|
(id) => !!id
|
|
26935
27231
|
);
|
|
26936
27232
|
}
|
|
27233
|
+
if (sg.DBSubnetGroupArn)
|
|
27234
|
+
await this.attachTags(result, sg.DBSubnetGroupArn);
|
|
26937
27235
|
return result;
|
|
26938
27236
|
}
|
|
27237
|
+
/**
|
|
27238
|
+
* Fetch tags via `ListTagsForResource(ResourceName=arn)` and merge them
|
|
27239
|
+
* into the result under `Tags` (CFn shape, `aws:*` filtered out, omitted
|
|
27240
|
+
* when empty). Best-effort: tag-fetch failures are logged at debug and
|
|
27241
|
+
* the key is simply left out — drift detection on configuration is more
|
|
27242
|
+
* important than fail-closing on a missing tag permission.
|
|
27243
|
+
*/
|
|
27244
|
+
async attachTags(result, arn) {
|
|
27245
|
+
try {
|
|
27246
|
+
const tagsResp = await this.getClient().send(
|
|
27247
|
+
new ListTagsForResourceCommand10({ ResourceName: arn })
|
|
27248
|
+
);
|
|
27249
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.TagList);
|
|
27250
|
+
if (tags.length > 0)
|
|
27251
|
+
result["Tags"] = tags;
|
|
27252
|
+
} catch (err) {
|
|
27253
|
+
this.logger.debug(
|
|
27254
|
+
`RDS ListTagsForResource(${arn}) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
27255
|
+
);
|
|
27256
|
+
}
|
|
27257
|
+
}
|
|
26939
27258
|
async importDBInstance(input) {
|
|
26940
27259
|
const explicit = resolveExplicitPhysicalId(input, "DBInstanceIdentifier");
|
|
26941
27260
|
if (explicit) {
|
|
@@ -27712,10 +28031,11 @@ var Route53Provider = class {
|
|
|
27712
28031
|
*
|
|
27713
28032
|
* Dispatch per resource type:
|
|
27714
28033
|
* - `HostedZone` → `GetHostedZone` (Name, HostedZoneConfig{Comment,
|
|
27715
|
-
* PrivateZone}, VPCs from `VPCs[]
|
|
27716
|
-
*
|
|
27717
|
-
*
|
|
27718
|
-
*
|
|
28034
|
+
* PrivateZone}, VPCs from `VPCs[]`, HostedZoneTags via
|
|
28035
|
+
* `ListTagsForResource(ResourceType=hostedzone, ResourceId=<idTail>)`
|
|
28036
|
+
* with `aws:*` filtered out and the key omitted when empty).
|
|
28037
|
+
* QueryLoggingConfig is skipped because it's a separate
|
|
28038
|
+
* `ListQueryLoggingConfigs` call and the v1 surface does not surface it.
|
|
27719
28039
|
* - `RecordSet` → `ListResourceRecordSets` filtered to the exact
|
|
27720
28040
|
* `(name, type)` pair from the composite physicalId
|
|
27721
28041
|
* (`{zoneId}|{name}|{type}`). Surfaces TTL, ResourceRecords (with
|
|
@@ -27770,6 +28090,19 @@ var Route53Provider = class {
|
|
|
27770
28090
|
return out;
|
|
27771
28091
|
});
|
|
27772
28092
|
}
|
|
28093
|
+
const idTail = physicalId.replace(/^\/hostedzone\//, "");
|
|
28094
|
+
try {
|
|
28095
|
+
const tagsResp = await this.getClient().send(
|
|
28096
|
+
new ListTagsForResourceCommand11({ ResourceType: "hostedzone", ResourceId: idTail })
|
|
28097
|
+
);
|
|
28098
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.ResourceTagSet?.Tags);
|
|
28099
|
+
if (tags.length > 0)
|
|
28100
|
+
result["HostedZoneTags"] = tags;
|
|
28101
|
+
} catch (err) {
|
|
28102
|
+
this.logger.debug(
|
|
28103
|
+
`Route53 ListTagsForResource(${idTail}) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
28104
|
+
);
|
|
28105
|
+
}
|
|
27773
28106
|
return result;
|
|
27774
28107
|
}
|
|
27775
28108
|
async readRecordSet(physicalId) {
|
|
@@ -28149,7 +28482,9 @@ var WAFv2WebACLProvider = class {
|
|
|
28149
28482
|
* and AssociationConfig — every key cdkd state declares as
|
|
28150
28483
|
* `handledProperties`. `Scope` is recovered from the ARN parse.
|
|
28151
28484
|
*
|
|
28152
|
-
* Tags are
|
|
28485
|
+
* Tags are surfaced via a follow-up `ListTagsForResource(ResourceARN)`
|
|
28486
|
+
* call. CDK's `aws:*` auto-tags are filtered out and the result key is
|
|
28487
|
+
* omitted when AWS reports no user tags. Returns `undefined`
|
|
28153
28488
|
* when the ARN can't be parsed or the WebACL is gone
|
|
28154
28489
|
* (`WAFNonexistentItemException`).
|
|
28155
28490
|
*/
|
|
@@ -28206,6 +28541,18 @@ var WAFv2WebACLProvider = class {
|
|
|
28206
28541
|
if (webACL.AssociationConfig) {
|
|
28207
28542
|
result["AssociationConfig"] = webACL.AssociationConfig;
|
|
28208
28543
|
}
|
|
28544
|
+
try {
|
|
28545
|
+
const tagsResp = await this.getClient().send(
|
|
28546
|
+
new ListTagsForResourceCommand12({ ResourceARN: physicalId })
|
|
28547
|
+
);
|
|
28548
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.TagInfoForResource?.TagList);
|
|
28549
|
+
if (tags.length > 0)
|
|
28550
|
+
result["Tags"] = tags;
|
|
28551
|
+
} catch (err) {
|
|
28552
|
+
this.logger.debug(
|
|
28553
|
+
`WAFv2 ListTagsForResource(${physicalId}) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
28554
|
+
);
|
|
28555
|
+
}
|
|
28209
28556
|
return result;
|
|
28210
28557
|
}
|
|
28211
28558
|
/**
|
|
@@ -28613,9 +28960,10 @@ var CognitoUserPoolProvider = class {
|
|
|
28613
28960
|
* `UserPoolClient`, `UserPoolGroup`, and other Cognito sub-resources go
|
|
28614
28961
|
* through the CC API fallback (which has its own `readCurrentState`).
|
|
28615
28962
|
*
|
|
28616
|
-
* `UserPoolTags` is
|
|
28617
|
-
*
|
|
28618
|
-
*
|
|
28963
|
+
* `UserPoolTags` is surfaced from the same `DescribeUserPool` response —
|
|
28964
|
+
* Cognito's CFn property is a tag-name → value map (NOT an array of
|
|
28965
|
+
* `{Key, Value}`), so we keep the map shape and just filter out CDK's
|
|
28966
|
+
* `aws:*` auto-tags. The result key is omitted when no user tags remain.
|
|
28619
28967
|
*
|
|
28620
28968
|
* Returns `undefined` when the pool is gone (`ResourceNotFoundException`).
|
|
28621
28969
|
*/
|
|
@@ -28692,6 +29040,15 @@ var CognitoUserPoolProvider = class {
|
|
|
28692
29040
|
if (pool.SmsVerificationMessage !== void 0) {
|
|
28693
29041
|
result["SmsVerificationMessage"] = pool.SmsVerificationMessage;
|
|
28694
29042
|
}
|
|
29043
|
+
if (pool.UserPoolTags) {
|
|
29044
|
+
const userTags = {};
|
|
29045
|
+
for (const [k, v] of Object.entries(pool.UserPoolTags)) {
|
|
29046
|
+
if (!k.startsWith("aws:"))
|
|
29047
|
+
userTags[k] = v;
|
|
29048
|
+
}
|
|
29049
|
+
if (Object.keys(userTags).length > 0)
|
|
29050
|
+
result["UserPoolTags"] = userTags;
|
|
29051
|
+
}
|
|
28695
29052
|
return result;
|
|
28696
29053
|
}
|
|
28697
29054
|
/**
|
|
@@ -29196,8 +29553,11 @@ var ElastiCacheProvider = class {
|
|
|
29196
29553
|
* surfacing `CacheSubnetGroupName`, `CacheSubnetGroupDescription`,
|
|
29197
29554
|
* and `SubnetIds` derived from `Subnets[].SubnetIdentifier`.
|
|
29198
29555
|
*
|
|
29199
|
-
* Tags are
|
|
29200
|
-
*
|
|
29556
|
+
* Tags are surfaced via a follow-up `ListTagsForResource(ResourceName=arn)`
|
|
29557
|
+
* for both types (ARN derived from `cluster.ARN` / `group.ARN`). CDK's
|
|
29558
|
+
* `aws:*` auto-tags are filtered out and the result key is omitted when
|
|
29559
|
+
* AWS reports no user tags. Returns `undefined` when the resource is gone
|
|
29560
|
+
* (`*NotFoundFault`).
|
|
29201
29561
|
*/
|
|
29202
29562
|
async readCurrentState(physicalId, _logicalId, resourceType) {
|
|
29203
29563
|
switch (resourceType) {
|
|
@@ -29277,6 +29637,8 @@ var ElastiCacheProvider = class {
|
|
|
29277
29637
|
if (ids.length > 0)
|
|
29278
29638
|
result["VpcSecurityGroupIds"] = ids;
|
|
29279
29639
|
}
|
|
29640
|
+
if (cluster.ARN)
|
|
29641
|
+
await this.attachTags(result, cluster.ARN);
|
|
29280
29642
|
return result;
|
|
29281
29643
|
}
|
|
29282
29644
|
async readSubnetGroup(physicalId) {
|
|
@@ -29305,8 +29667,25 @@ var ElastiCacheProvider = class {
|
|
|
29305
29667
|
if (ids.length > 0)
|
|
29306
29668
|
result["SubnetIds"] = ids;
|
|
29307
29669
|
}
|
|
29670
|
+
if (group.ARN)
|
|
29671
|
+
await this.attachTags(result, group.ARN);
|
|
29308
29672
|
return result;
|
|
29309
29673
|
}
|
|
29674
|
+
/** Best-effort tag fetch — failures omit the key without breaking the read. */
|
|
29675
|
+
async attachTags(result, arn) {
|
|
29676
|
+
try {
|
|
29677
|
+
const tagsResp = await this.getClient().send(
|
|
29678
|
+
new ListTagsForResourceCommand14({ ResourceName: arn })
|
|
29679
|
+
);
|
|
29680
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.TagList);
|
|
29681
|
+
if (tags.length > 0)
|
|
29682
|
+
result["Tags"] = tags;
|
|
29683
|
+
} catch (err) {
|
|
29684
|
+
this.logger.debug(
|
|
29685
|
+
`ElastiCache ListTagsForResource(${arn}) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
29686
|
+
);
|
|
29687
|
+
}
|
|
29688
|
+
}
|
|
29310
29689
|
/**
|
|
29311
29690
|
* Adopt an existing ElastiCache resource into cdkd state.
|
|
29312
29691
|
*
|
|
@@ -29590,15 +29969,14 @@ var ServiceDiscoveryProvider = class {
|
|
|
29590
29969
|
);
|
|
29591
29970
|
}
|
|
29592
29971
|
}
|
|
29593
|
-
updateNamespace(logicalId,
|
|
29594
|
-
|
|
29595
|
-
|
|
29596
|
-
|
|
29597
|
-
|
|
29598
|
-
|
|
29599
|
-
|
|
29600
|
-
|
|
29601
|
-
});
|
|
29972
|
+
updateNamespace(logicalId, _physicalId) {
|
|
29973
|
+
return Promise.reject(
|
|
29974
|
+
new ResourceUpdateNotSupportedError(
|
|
29975
|
+
"AWS::ServiceDiscovery::PrivateDnsNamespace",
|
|
29976
|
+
logicalId,
|
|
29977
|
+
"PrivateDnsNamespace updates are not yet implemented in cdkd; re-deploy with cdkd deploy --replace, or destroy + redeploy the stack"
|
|
29978
|
+
)
|
|
29979
|
+
);
|
|
29602
29980
|
}
|
|
29603
29981
|
async deleteNamespace(logicalId, physicalId, resourceType, context) {
|
|
29604
29982
|
this.logger.debug(`Deleting private DNS namespace ${logicalId}: ${physicalId}`);
|
|
@@ -29693,15 +30071,14 @@ var ServiceDiscoveryProvider = class {
|
|
|
29693
30071
|
);
|
|
29694
30072
|
}
|
|
29695
30073
|
}
|
|
29696
|
-
updateService(logicalId,
|
|
29697
|
-
|
|
29698
|
-
|
|
29699
|
-
|
|
29700
|
-
|
|
29701
|
-
|
|
29702
|
-
|
|
29703
|
-
|
|
29704
|
-
});
|
|
30074
|
+
updateService(logicalId, _physicalId) {
|
|
30075
|
+
return Promise.reject(
|
|
30076
|
+
new ResourceUpdateNotSupportedError(
|
|
30077
|
+
"AWS::ServiceDiscovery::Service",
|
|
30078
|
+
logicalId,
|
|
30079
|
+
"ServiceDiscovery Service updates are not yet implemented in cdkd; re-deploy with cdkd deploy --replace, or destroy + redeploy the stack"
|
|
30080
|
+
)
|
|
30081
|
+
);
|
|
29705
30082
|
}
|
|
29706
30083
|
async deleteService(logicalId, physicalId, resourceType, context) {
|
|
29707
30084
|
this.logger.debug(`Deleting service discovery service ${logicalId}: ${physicalId}`);
|
|
@@ -29794,8 +30171,12 @@ var ServiceDiscoveryProvider = class {
|
|
|
29794
30171
|
* - `Service` → `GetService` (Name, NamespaceId, Description, Type,
|
|
29795
30172
|
* DnsConfig, HealthCheckConfig, HealthCheckCustomConfig).
|
|
29796
30173
|
*
|
|
29797
|
-
* Tags are
|
|
29798
|
-
*
|
|
30174
|
+
* Tags are surfaced via a follow-up `ListTagsForResource(ResourceARN)`
|
|
30175
|
+
* call (using the resource ARN from `GetNamespace.Arn` or
|
|
30176
|
+
* `GetService.Arn`). CDK's `aws:*` auto-tags are filtered out and the
|
|
30177
|
+
* result key is omitted when AWS reports no user tags. Returns
|
|
30178
|
+
* `undefined` when the resource is gone (`NamespaceNotFound` /
|
|
30179
|
+
* `ServiceNotFound`).
|
|
29799
30180
|
*/
|
|
29800
30181
|
async readCurrentState(physicalId, _logicalId, resourceType) {
|
|
29801
30182
|
switch (resourceType) {
|
|
@@ -29825,6 +30206,8 @@ var ServiceDiscoveryProvider = class {
|
|
|
29825
30206
|
if (ns.Description !== void 0 && ns.Description !== "") {
|
|
29826
30207
|
result["Description"] = ns.Description;
|
|
29827
30208
|
}
|
|
30209
|
+
if (ns.Arn)
|
|
30210
|
+
await this.attachTags(result, ns.Arn);
|
|
29828
30211
|
return result;
|
|
29829
30212
|
}
|
|
29830
30213
|
async readService(physicalId) {
|
|
@@ -29858,8 +30241,25 @@ var ServiceDiscoveryProvider = class {
|
|
|
29858
30241
|
if (svc.HealthCheckCustomConfig) {
|
|
29859
30242
|
result["HealthCheckCustomConfig"] = svc.HealthCheckCustomConfig;
|
|
29860
30243
|
}
|
|
30244
|
+
if (svc.Arn)
|
|
30245
|
+
await this.attachTags(result, svc.Arn);
|
|
29861
30246
|
return result;
|
|
29862
30247
|
}
|
|
30248
|
+
/** Best-effort tag fetch via `ListTagsForResource(ResourceARN)`. */
|
|
30249
|
+
async attachTags(result, arn) {
|
|
30250
|
+
try {
|
|
30251
|
+
const tagsResp = await this.getClient().send(
|
|
30252
|
+
new ListTagsForResourceCommand15({ ResourceARN: arn })
|
|
30253
|
+
);
|
|
30254
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.Tags);
|
|
30255
|
+
if (tags.length > 0)
|
|
30256
|
+
result["Tags"] = tags;
|
|
30257
|
+
} catch (err) {
|
|
30258
|
+
this.logger.debug(
|
|
30259
|
+
`ServiceDiscovery ListTagsForResource(${arn}) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
30260
|
+
);
|
|
30261
|
+
}
|
|
30262
|
+
}
|
|
29863
30263
|
async import(input) {
|
|
29864
30264
|
switch (input.resourceType) {
|
|
29865
30265
|
case "AWS::ServiceDiscovery::PrivateDnsNamespace":
|
|
@@ -30049,9 +30449,22 @@ var AppSyncProvider = class {
|
|
|
30049
30449
|
);
|
|
30050
30450
|
}
|
|
30051
30451
|
}
|
|
30052
|
-
|
|
30053
|
-
|
|
30054
|
-
|
|
30452
|
+
/**
|
|
30453
|
+
* AppSync resources are treated as immutable by cdkd: every supported
|
|
30454
|
+
* type (`GraphQLApi`, `GraphQLSchema`, `DataSource`, `Resolver`,
|
|
30455
|
+
* `ApiKey`) is recreated on property changes via the deploy engine's
|
|
30456
|
+
* immutable-property replacement path. There is no in-place update,
|
|
30457
|
+
* so `cdkd drift --revert` surfaces a clear "use --replace or
|
|
30458
|
+
* re-deploy" message instead of silently no-op'ing the revert.
|
|
30459
|
+
*/
|
|
30460
|
+
update(logicalId, _physicalId, resourceType, _properties, _previousProperties) {
|
|
30461
|
+
return Promise.reject(
|
|
30462
|
+
new ResourceUpdateNotSupportedError(
|
|
30463
|
+
resourceType,
|
|
30464
|
+
logicalId,
|
|
30465
|
+
"AppSync resources are recreated on property changes; re-deploy with cdkd deploy --replace, or destroy + redeploy the stack"
|
|
30466
|
+
)
|
|
30467
|
+
);
|
|
30055
30468
|
}
|
|
30056
30469
|
async delete(logicalId, physicalId, resourceType, _properties, context) {
|
|
30057
30470
|
switch (resourceType) {
|
|
@@ -30493,7 +30906,9 @@ var AppSyncProvider = class {
|
|
|
30493
30906
|
*
|
|
30494
30907
|
* Dispatches per resource type:
|
|
30495
30908
|
* - `GraphQLApi` → `GetGraphqlApi` (Name, AuthenticationType, XrayEnabled,
|
|
30496
|
-
* LogConfig). Tags
|
|
30909
|
+
* LogConfig, Tags). Tags come from the same response (`tags` map);
|
|
30910
|
+
* CDK's `aws:*` auto-tags are filtered out and the result key is
|
|
30911
|
+
* omitted when no user tags remain.
|
|
30497
30912
|
* - `DataSource` → `GetDataSource` (Name, Type, Description,
|
|
30498
30913
|
* ServiceRoleArn, DynamoDBConfig, LambdaConfig, HttpConfig). The
|
|
30499
30914
|
* `ApiId` cdkd holds is recovered from the `apiId|name` physicalId.
|
|
@@ -30561,6 +30976,9 @@ var AppSyncProvider = class {
|
|
|
30561
30976
|
if (Object.keys(log).length > 0)
|
|
30562
30977
|
result["LogConfig"] = log;
|
|
30563
30978
|
}
|
|
30979
|
+
const tags = normalizeAwsTagsToCfn(api.tags);
|
|
30980
|
+
if (tags.length > 0)
|
|
30981
|
+
result["Tags"] = tags;
|
|
30564
30982
|
return result;
|
|
30565
30983
|
}
|
|
30566
30984
|
async readDataSource(physicalId) {
|
|
@@ -30788,10 +31206,11 @@ var GlueProvider = class {
|
|
|
30788
31206
|
async update(logicalId, physicalId, resourceType, properties, _previousProperties) {
|
|
30789
31207
|
switch (resourceType) {
|
|
30790
31208
|
case "AWS::Glue::Database":
|
|
30791
|
-
|
|
30792
|
-
|
|
31209
|
+
throw new ResourceUpdateNotSupportedError(
|
|
31210
|
+
resourceType,
|
|
31211
|
+
logicalId,
|
|
31212
|
+
"Glue Database updates are not yet implemented in cdkd; re-deploy with cdkd deploy --replace, or destroy + redeploy the stack"
|
|
30793
31213
|
);
|
|
30794
|
-
return { physicalId, wasReplaced: false };
|
|
30795
31214
|
case "AWS::Glue::Table":
|
|
30796
31215
|
return this.updateTable(logicalId, physicalId, resourceType, properties);
|
|
30797
31216
|
default:
|
|
@@ -31805,9 +32224,11 @@ var KMSProvider = class {
|
|
|
31805
32224
|
* Surfaces `AliasName`, `TargetKeyId`. `ListAliases` is paginated
|
|
31806
32225
|
* since there's no direct "describe one alias" API.
|
|
31807
32226
|
*
|
|
31808
|
-
* `Tags` is
|
|
31809
|
-
*
|
|
31810
|
-
*
|
|
32227
|
+
* `Tags` is surfaced for `AWS::KMS::Key` via a follow-up
|
|
32228
|
+
* `ListResourceTags(KeyId)` call (KMS uses `[{TagKey, TagValue}]` shape).
|
|
32229
|
+
* CDK's `aws:*` auto-tags are filtered out; the result key is omitted
|
|
32230
|
+
* entirely when AWS reports no user tags. `AWS::KMS::Alias` does not
|
|
32231
|
+
* support tags. `BypassPolicyLockoutSafetyCheck` and `PendingWindowInDays`
|
|
31811
32232
|
* are not part of the persisted AWS state visible via `DescribeKey`.
|
|
31812
32233
|
*
|
|
31813
32234
|
* Returns `undefined` when the resource is gone (`NotFoundException`).
|
|
@@ -31850,6 +32271,19 @@ var KMSProvider = class {
|
|
|
31850
32271
|
result["MultiRegion"] = md.MultiRegion;
|
|
31851
32272
|
if (md.Origin !== void 0)
|
|
31852
32273
|
result["Origin"] = md.Origin;
|
|
32274
|
+
if (md.KeyId) {
|
|
32275
|
+
try {
|
|
32276
|
+
const tagsResp = await this.getClient().send(
|
|
32277
|
+
new ListResourceTagsCommand({ KeyId: md.KeyId })
|
|
32278
|
+
);
|
|
32279
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.Tags);
|
|
32280
|
+
if (tags.length > 0)
|
|
32281
|
+
result["Tags"] = tags;
|
|
32282
|
+
} catch (err) {
|
|
32283
|
+
if (err instanceof NotFoundException5)
|
|
32284
|
+
return void 0;
|
|
32285
|
+
}
|
|
32286
|
+
}
|
|
31853
32287
|
return result;
|
|
31854
32288
|
}
|
|
31855
32289
|
async readCurrentStateAlias(physicalId) {
|
|
@@ -32233,7 +32667,8 @@ var KinesisStreamProvider = class {
|
|
|
32233
32667
|
*
|
|
32234
32668
|
* Issues `DescribeStream` and surfaces the keys cdkd's `create()`
|
|
32235
32669
|
* accepts: `Name`, `StreamModeDetails`, `ShardCount`, `RetentionPeriodHours`,
|
|
32236
|
-
* and `StreamEncryption`. Tags are
|
|
32670
|
+
* and `StreamEncryption`. Tags are surfaced via a follow-up
|
|
32671
|
+
* `ListTagsForStream` with `aws:*` filtered out.
|
|
32237
32672
|
*
|
|
32238
32673
|
* `ShardCount` is reported as the count of `Shards[]` in the stream
|
|
32239
32674
|
* description (only present for PROVISIONED-mode streams; ON_DEMAND
|
|
@@ -32282,6 +32717,20 @@ var KinesisStreamProvider = class {
|
|
|
32282
32717
|
encryption["KeyId"] = stream.KeyId;
|
|
32283
32718
|
result["StreamEncryption"] = encryption;
|
|
32284
32719
|
}
|
|
32720
|
+
try {
|
|
32721
|
+
const tagsResp = await this.getClient().send(
|
|
32722
|
+
new ListTagsForStreamCommand({ StreamName: physicalId })
|
|
32723
|
+
);
|
|
32724
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.Tags);
|
|
32725
|
+
if (tags.length > 0)
|
|
32726
|
+
result["Tags"] = tags;
|
|
32727
|
+
} catch (err) {
|
|
32728
|
+
if (err instanceof ResourceNotFoundException13)
|
|
32729
|
+
return void 0;
|
|
32730
|
+
this.logger.debug(
|
|
32731
|
+
`Kinesis ListTagsForStream(${physicalId}) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
32732
|
+
);
|
|
32733
|
+
}
|
|
32285
32734
|
return result;
|
|
32286
32735
|
}
|
|
32287
32736
|
async import(input) {
|
|
@@ -32414,8 +32863,15 @@ var EFSProvider = class {
|
|
|
32414
32863
|
);
|
|
32415
32864
|
}
|
|
32416
32865
|
}
|
|
32866
|
+
/**
|
|
32867
|
+
* EFS resources are treated as immutable by cdkd's `update()`. The deploy
|
|
32868
|
+
* engine recreates them on property changes via immutable-property
|
|
32869
|
+
* detection. (AWS does expose `UpdateFileSystem` for ThroughputMode and
|
|
32870
|
+
* `ModifyMountTargetSecurityGroups` for mount-target SGs — those are
|
|
32871
|
+
* deferred to a follow-up PR.) `cdkd drift --revert` surfaces a clear
|
|
32872
|
+
* "use --replace or re-deploy" message instead of silently no-op'ing.
|
|
32873
|
+
*/
|
|
32417
32874
|
update(logicalId, physicalId, resourceType, _properties, _previousProperties) {
|
|
32418
|
-
this.logger.debug(`Update for ${resourceType} ${logicalId} (${physicalId}) - no-op, immutable`);
|
|
32419
32875
|
if (resourceType !== "AWS::EFS::FileSystem" && resourceType !== "AWS::EFS::MountTarget" && resourceType !== "AWS::EFS::AccessPoint") {
|
|
32420
32876
|
throw new ProvisioningError(
|
|
32421
32877
|
`Unsupported resource type: ${resourceType}`,
|
|
@@ -32424,7 +32880,13 @@ var EFSProvider = class {
|
|
|
32424
32880
|
physicalId
|
|
32425
32881
|
);
|
|
32426
32882
|
}
|
|
32427
|
-
return Promise.
|
|
32883
|
+
return Promise.reject(
|
|
32884
|
+
new ResourceUpdateNotSupportedError(
|
|
32885
|
+
resourceType,
|
|
32886
|
+
logicalId,
|
|
32887
|
+
"EFS resources are recreated on property changes; re-deploy with cdkd deploy --replace, or destroy + redeploy the stack"
|
|
32888
|
+
)
|
|
32889
|
+
);
|
|
32428
32890
|
}
|
|
32429
32891
|
async delete(logicalId, physicalId, resourceType, _properties, context) {
|
|
32430
32892
|
switch (resourceType) {
|
|
@@ -32781,7 +33243,12 @@ var EFSProvider = class {
|
|
|
32781
33243
|
* - `MountTarget` → `DescribeMountTargets` (FileSystemId, SubnetId).
|
|
32782
33244
|
* SecurityGroups requires a separate call and is omitted for v1.
|
|
32783
33245
|
*
|
|
32784
|
-
*
|
|
33246
|
+
* `FileSystemTags` (the CFn property name on `AWS::EFS::FileSystem`) is
|
|
33247
|
+
* surfaced from the same `DescribeFileSystems` response — `aws:*`
|
|
33248
|
+
* auto-tags filtered, key omitted when empty. `AccessPoint` and
|
|
33249
|
+
* `MountTarget` are not surfaced for tags here (`AccessPointTags` would
|
|
33250
|
+
* mirror this approach but the test scope below covers `FileSystem`
|
|
33251
|
+
* only; further coverage can land in a follow-up).
|
|
32785
33252
|
* Returns `undefined` when the resource is gone (`*NotFound`).
|
|
32786
33253
|
*/
|
|
32787
33254
|
async readCurrentState(physicalId, _logicalId, resourceType) {
|
|
@@ -32858,6 +33325,9 @@ var EFSProvider = class {
|
|
|
32858
33325
|
if (err instanceof FileSystemNotFound)
|
|
32859
33326
|
return void 0;
|
|
32860
33327
|
}
|
|
33328
|
+
const tags = normalizeAwsTagsToCfn(fs.Tags);
|
|
33329
|
+
if (tags.length > 0)
|
|
33330
|
+
result["FileSystemTags"] = tags;
|
|
32861
33331
|
return result;
|
|
32862
33332
|
}
|
|
32863
33333
|
async readAccessPoint(physicalId) {
|
|
@@ -33241,15 +33711,21 @@ var FirehoseProvider = class {
|
|
|
33241
33711
|
}
|
|
33242
33712
|
}
|
|
33243
33713
|
/**
|
|
33244
|
-
*
|
|
33245
|
-
*
|
|
33246
|
-
*
|
|
33714
|
+
* Firehose delivery streams are treated as immutable by cdkd. Most
|
|
33715
|
+
* destination-config changes require replacement, and AWS's
|
|
33716
|
+
* `UpdateDestination` API surface is deep enough that the deploy engine's
|
|
33717
|
+
* immutable-property replacement path covers the common cases more
|
|
33718
|
+
* reliably. `cdkd drift --revert` therefore surfaces a clear "use
|
|
33719
|
+
* --replace or re-deploy" message instead of silently no-op'ing.
|
|
33247
33720
|
*/
|
|
33248
|
-
update(logicalId,
|
|
33249
|
-
|
|
33250
|
-
|
|
33721
|
+
update(logicalId, _physicalId, resourceType, _properties, _previousProperties) {
|
|
33722
|
+
return Promise.reject(
|
|
33723
|
+
new ResourceUpdateNotSupportedError(
|
|
33724
|
+
resourceType,
|
|
33725
|
+
logicalId,
|
|
33726
|
+
"Firehose delivery streams are recreated on property changes; re-deploy with cdkd deploy --replace, or destroy + redeploy the stack"
|
|
33727
|
+
)
|
|
33251
33728
|
);
|
|
33252
|
-
return Promise.resolve({ physicalId, wasReplaced: false });
|
|
33253
33729
|
}
|
|
33254
33730
|
/**
|
|
33255
33731
|
* Delete a Firehose delivery stream
|
|
@@ -33403,8 +33879,10 @@ var FirehoseProvider = class {
|
|
|
33403
33879
|
* fields. Drift on destination contents is best chased manually via
|
|
33404
33880
|
* `aws firehose describe-delivery-stream` for now.
|
|
33405
33881
|
*
|
|
33406
|
-
* Tags
|
|
33407
|
-
*
|
|
33882
|
+
* Tags are surfaced via a follow-up `ListTagsForDeliveryStream` call
|
|
33883
|
+
* with `aws:*` filtered out and the result key omitted when empty.
|
|
33884
|
+
* `DeliveryStreamEncryptionConfigurationInput` is still skipped (shape
|
|
33885
|
+
* decision deferred).
|
|
33408
33886
|
*
|
|
33409
33887
|
* Returns `undefined` when the stream is gone (`ResourceNotFoundException`).
|
|
33410
33888
|
*/
|
|
@@ -33440,6 +33918,20 @@ var FirehoseProvider = class {
|
|
|
33440
33918
|
result["KinesisStreamSourceConfiguration"] = srcOut;
|
|
33441
33919
|
}
|
|
33442
33920
|
}
|
|
33921
|
+
try {
|
|
33922
|
+
const tagsResp = await this.getClient().send(
|
|
33923
|
+
new ListTagsForDeliveryStreamCommand({ DeliveryStreamName: physicalId })
|
|
33924
|
+
);
|
|
33925
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.Tags);
|
|
33926
|
+
if (tags.length > 0)
|
|
33927
|
+
result["Tags"] = tags;
|
|
33928
|
+
} catch (err) {
|
|
33929
|
+
if (err instanceof ResourceNotFoundException14)
|
|
33930
|
+
return void 0;
|
|
33931
|
+
this.logger.debug(
|
|
33932
|
+
`Firehose ListTagsForDeliveryStream(${physicalId}) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
33933
|
+
);
|
|
33934
|
+
}
|
|
33443
33935
|
return result;
|
|
33444
33936
|
}
|
|
33445
33937
|
async import(input) {
|
|
@@ -33775,8 +34267,13 @@ var CloudTrailProvider = class {
|
|
|
33775
34267
|
* derived field; the cdkd state property is `SnsTopicName` so we
|
|
33776
34268
|
* surface `SnsTopicName` directly from `GetTrail.SnsTopicName`.
|
|
33777
34269
|
*
|
|
33778
|
-
* Tags
|
|
33779
|
-
*
|
|
34270
|
+
* Tags are surfaced via a follow-up `ListTags(ResourceIdList=[arn])` call
|
|
34271
|
+
* (using the trail ARN from the same `GetTrail` response). CDK's `aws:*`
|
|
34272
|
+
* auto-tags are filtered out and the result key is omitted when AWS
|
|
34273
|
+
* reports no user tags.
|
|
34274
|
+
*
|
|
34275
|
+
* `InsightSelectors` is skipped for v1 (separate call + shape mapping
|
|
34276
|
+
* still TBD).
|
|
33780
34277
|
*
|
|
33781
34278
|
* Returns `undefined` when the trail is gone (`TrailNotFoundException`).
|
|
33782
34279
|
*/
|
|
@@ -33838,6 +34335,20 @@ var CloudTrailProvider = class {
|
|
|
33838
34335
|
}
|
|
33839
34336
|
} catch {
|
|
33840
34337
|
}
|
|
34338
|
+
if (trail.TrailARN) {
|
|
34339
|
+
try {
|
|
34340
|
+
const tagsResp = await this.getClient().send(
|
|
34341
|
+
new ListTagsCommand3({ ResourceIdList: [trail.TrailARN] })
|
|
34342
|
+
);
|
|
34343
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.ResourceTagList?.[0]?.TagsList);
|
|
34344
|
+
if (tags.length > 0)
|
|
34345
|
+
result["Tags"] = tags;
|
|
34346
|
+
} catch (err) {
|
|
34347
|
+
this.logger.debug(
|
|
34348
|
+
`CloudTrail ListTags(${trail.TrailARN}) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
34349
|
+
);
|
|
34350
|
+
}
|
|
34351
|
+
}
|
|
33841
34352
|
return result;
|
|
33842
34353
|
}
|
|
33843
34354
|
async import(input) {
|
|
@@ -34170,8 +34681,12 @@ var CodeBuildProvider = class {
|
|
|
34170
34681
|
* is left to a follow-up — surfacing them with a partial shape would
|
|
34171
34682
|
* fire false drift on every project that uses them.
|
|
34172
34683
|
*
|
|
34173
|
-
* Tags are
|
|
34174
|
-
*
|
|
34684
|
+
* Tags are surfaced from the same `BatchGetProjects` response (CodeBuild
|
|
34685
|
+
* uses lower-case `key`/`value` shape; `normalizeAwsTagsToCfn` re-shapes
|
|
34686
|
+
* to CFn `[{Key, Value}]`). CDK's `aws:*` auto-tags are filtered out
|
|
34687
|
+
* and the result key is omitted when AWS reports no user tags. Returns
|
|
34688
|
+
* `undefined` when the project is gone (`projects` array empty /
|
|
34689
|
+
* `projectsNotFound` set).
|
|
34175
34690
|
*/
|
|
34176
34691
|
async readCurrentState(physicalId, _logicalId, _resourceType) {
|
|
34177
34692
|
let project;
|
|
@@ -34290,6 +34805,9 @@ var CodeBuildProvider = class {
|
|
|
34290
34805
|
if (Object.keys(env).length > 0)
|
|
34291
34806
|
result["Environment"] = env;
|
|
34292
34807
|
}
|
|
34808
|
+
const tags = normalizeAwsTagsToCfn(project.tags);
|
|
34809
|
+
if (tags.length > 0)
|
|
34810
|
+
result["Tags"] = tags;
|
|
34293
34811
|
return result;
|
|
34294
34812
|
}
|
|
34295
34813
|
async import(input) {
|
|
@@ -35818,11 +36336,14 @@ var ECRProvider = class {
|
|
|
35818
36336
|
* round-trip; cdkd state holds the policy as either a string or an
|
|
35819
36337
|
* object (depending on user input), and the comparator round-trip
|
|
35820
36338
|
* is not yet handled here.
|
|
35821
|
-
* - `Tags`: requires `ListTagsForResource`; auto-injected
|
|
35822
|
-
* `aws:cdk:path` tag-shape question is out of scope.
|
|
35823
36339
|
* - `EmptyOnDelete` / `ImageTagMutabilityExclusionFilters`: not part
|
|
35824
36340
|
* of the persisted AWS state visible via standard Describe.
|
|
35825
36341
|
*
|
|
36342
|
+
* `Tags` is surfaced via a follow-up `ListTagsForResource(arn)` call
|
|
36343
|
+
* (using the repository ARN that `DescribeRepositories` returns). CDK's
|
|
36344
|
+
* `aws:*` auto-tags are filtered out; the result key is omitted entirely
|
|
36345
|
+
* when AWS reports no user tags.
|
|
36346
|
+
*
|
|
35826
36347
|
* Returns `undefined` when the repository is gone (`RepositoryNotFoundException`).
|
|
35827
36348
|
*/
|
|
35828
36349
|
async readCurrentState(physicalId, _logicalId, _resourceType) {
|
|
@@ -35875,6 +36396,19 @@ var ECRProvider = class {
|
|
|
35875
36396
|
throw err;
|
|
35876
36397
|
}
|
|
35877
36398
|
}
|
|
36399
|
+
if (r.repositoryArn) {
|
|
36400
|
+
try {
|
|
36401
|
+
const tagsResp = await this.getClient().send(
|
|
36402
|
+
new ListTagsForResourceCommand18({ resourceArn: r.repositoryArn })
|
|
36403
|
+
);
|
|
36404
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.tags);
|
|
36405
|
+
if (tags.length > 0)
|
|
36406
|
+
result["Tags"] = tags;
|
|
36407
|
+
} catch (err) {
|
|
36408
|
+
if (!(err instanceof RepositoryNotFoundException))
|
|
36409
|
+
throw err;
|
|
36410
|
+
}
|
|
36411
|
+
}
|
|
35878
36412
|
return result;
|
|
35879
36413
|
}
|
|
35880
36414
|
/**
|
|
@@ -38492,6 +39026,7 @@ async function runRevert(reports, providerRegistry, stateConfig, awsClients, opt
|
|
|
38492
39026
|
const owner = `${process.env["USER"] || "unknown"}@${process.env["HOSTNAME"] || "host"}:${process.pid}`;
|
|
38493
39027
|
const concurrency = Math.max(1, options.concurrency ?? 4);
|
|
38494
39028
|
let totalFailed = 0;
|
|
39029
|
+
let totalUnsupported = 0;
|
|
38495
39030
|
let totalSucceeded = 0;
|
|
38496
39031
|
for (const report of reports) {
|
|
38497
39032
|
const driftedOutcomes = report.outcomes.filter(
|
|
@@ -38529,10 +39064,17 @@ async function runRevert(reports, providerRegistry, stateConfig, awsClients, opt
|
|
|
38529
39064
|
` \u2713 ${report.stackName}/${outcome.logicalId} (${outcome.resourceType}): reverted.`
|
|
38530
39065
|
);
|
|
38531
39066
|
} catch (err) {
|
|
39067
|
+
if (err instanceof ResourceUpdateNotSupportedError) {
|
|
39068
|
+
totalUnsupported++;
|
|
39069
|
+
logger.warn(
|
|
39070
|
+
` \u2298 ${report.stackName}/${outcome.logicalId} (${outcome.resourceType}): could not revert \u2014 ${err.message}`
|
|
39071
|
+
);
|
|
39072
|
+
return;
|
|
39073
|
+
}
|
|
38532
39074
|
totalFailed++;
|
|
38533
39075
|
const msg = err instanceof Error ? err.message : String(err);
|
|
38534
39076
|
logger.error(
|
|
38535
|
-
` \u2717 ${report.stackName}/${outcome.logicalId} (${outcome.resourceType}): ${msg}`
|
|
39077
|
+
` \u2717 ${report.stackName}/${outcome.logicalId} (${outcome.resourceType}): AWS update failed \u2014 ${msg}`
|
|
38536
39078
|
);
|
|
38537
39079
|
}
|
|
38538
39080
|
});
|
|
@@ -38545,11 +39087,21 @@ async function runRevert(reports, providerRegistry, stateConfig, awsClients, opt
|
|
|
38545
39087
|
});
|
|
38546
39088
|
}
|
|
38547
39089
|
}
|
|
39090
|
+
const summaryParts = [`${totalSucceeded} reverted`];
|
|
39091
|
+
if (totalUnsupported > 0)
|
|
39092
|
+
summaryParts.push(`${totalUnsupported} update-not-supported`);
|
|
39093
|
+
if (totalFailed > 0)
|
|
39094
|
+
summaryParts.push(`${totalFailed} failed`);
|
|
38548
39095
|
logger.info(`
|
|
38549
|
-
Revert summary: ${
|
|
38550
|
-
if (
|
|
39096
|
+
Revert summary: ${summaryParts.join(", ")}.`);
|
|
39097
|
+
if (totalUnsupported > 0) {
|
|
39098
|
+
logger.warn(
|
|
39099
|
+
`${totalUnsupported} resource(s) cannot be reverted in place \u2014 re-deploy the stack with cdkd deploy --replace, or destroy + redeploy to push the cdkd-state values back into AWS.`
|
|
39100
|
+
);
|
|
39101
|
+
}
|
|
39102
|
+
if (totalFailed > 0 || totalUnsupported > 0) {
|
|
38551
39103
|
throw new PartialFailureError(
|
|
38552
|
-
`Revert completed with ${totalFailed} resource error(s). Re-run 'cdkd drift <stack>' to see the remaining drift, then 'cdkd drift <stack> --revert' to retry.`
|
|
39104
|
+
`Revert completed with ${totalFailed + totalUnsupported} resource error(s) (${totalFailed} AWS update failure(s), ${totalUnsupported} update-not-supported). Re-run 'cdkd drift <stack>' to see the remaining drift, then 'cdkd drift <stack> --revert' to retry.`
|
|
38553
39105
|
);
|
|
38554
39106
|
}
|
|
38555
39107
|
}
|
|
@@ -41896,7 +42448,7 @@ function reorderArgs(argv) {
|
|
|
41896
42448
|
}
|
|
41897
42449
|
async function main() {
|
|
41898
42450
|
const program = new Command14();
|
|
41899
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.
|
|
42451
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.46.0");
|
|
41900
42452
|
program.addCommand(createBootstrapCommand());
|
|
41901
42453
|
program.addCommand(createSynthCommand());
|
|
41902
42454
|
program.addCommand(createListCommand());
|