@go-to-k/cdkd 0.45.0 → 0.46.1
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 +618 -90
- package/dist/cli.js.map +3 -3
- package/dist/go-to-k-cdkd-0.46.1.tgz +0 -0
- package/dist/index.js +67 -3
- package/dist/index.js.map +2 -2
- package/package.json +1 -1
- package/dist/go-to-k-cdkd-0.45.0.tgz +0 -0
package/dist/cli.js
CHANGED
|
@@ -8510,6 +8510,31 @@ function matchesCdkPath(tags, cdkPath) {
|
|
|
8510
8510
|
}
|
|
8511
8511
|
return false;
|
|
8512
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
|
+
}
|
|
8513
8538
|
|
|
8514
8539
|
// src/provisioning/providers/iam-role-provider.ts
|
|
8515
8540
|
var IAMRoleProvider = class {
|
|
@@ -9069,9 +9094,10 @@ var IAMRoleProvider = class {
|
|
|
9069
9094
|
* costs one extra `GetRolePolicy` per inline policy. Out of scope for
|
|
9070
9095
|
* v1 — drift detection on inline IAM policy bodies can ship in a
|
|
9071
9096
|
* follow-up.
|
|
9072
|
-
* - `Tags` is
|
|
9073
|
-
*
|
|
9074
|
-
*
|
|
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).
|
|
9075
9101
|
*
|
|
9076
9102
|
* Returns `undefined` when the role is gone (`NoSuchEntityException`).
|
|
9077
9103
|
*/
|
|
@@ -9121,8 +9147,46 @@ var IAMRoleProvider = class {
|
|
|
9121
9147
|
if (!(err instanceof NoSuchEntityException))
|
|
9122
9148
|
throw err;
|
|
9123
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
|
+
}
|
|
9124
9176
|
return result;
|
|
9125
9177
|
}
|
|
9178
|
+
/**
|
|
9179
|
+
* `Policies` (inline policy bodies) are intentionally omitted from
|
|
9180
|
+
* `readCurrentState`: surfacing the names without bodies would
|
|
9181
|
+
* guarantee a `PolicyDocument`-shaped drift on every role, and
|
|
9182
|
+
* fetching every body costs one extra `GetRolePolicy` per inline
|
|
9183
|
+
* policy. Tell the drift comparator to skip the whole subtree until a
|
|
9184
|
+
* dedicated PR adds proper inline-policy drift via per-name
|
|
9185
|
+
* `GetRolePolicy`.
|
|
9186
|
+
*/
|
|
9187
|
+
getDriftUnknownPaths() {
|
|
9188
|
+
return ["Policies"];
|
|
9189
|
+
}
|
|
9126
9190
|
/**
|
|
9127
9191
|
* Adopt an existing IAM role into cdkd state.
|
|
9128
9192
|
*
|
|
@@ -12126,14 +12190,9 @@ var S3BucketProvider = class {
|
|
|
12126
12190
|
}
|
|
12127
12191
|
try {
|
|
12128
12192
|
const resp = await this.s3Client.send(new GetBucketTaggingCommand({ Bucket: physicalId }));
|
|
12129
|
-
|
|
12130
|
-
|
|
12131
|
-
|
|
12132
|
-
Value: t.Value
|
|
12133
|
-
}));
|
|
12134
|
-
if (tags.length > 0)
|
|
12135
|
-
result["Tags"] = tags;
|
|
12136
|
-
}
|
|
12193
|
+
const tags = normalizeAwsTagsToCfn(resp.TagSet);
|
|
12194
|
+
if (tags.length > 0)
|
|
12195
|
+
result["Tags"] = tags;
|
|
12137
12196
|
} catch (err) {
|
|
12138
12197
|
const e = err;
|
|
12139
12198
|
if (e.name !== "NoSuchTagSet") {
|
|
@@ -12742,9 +12801,11 @@ var SQSQueueProvider = class {
|
|
|
12742
12801
|
* `QueueName` is derived from the URL tail (the `physicalId` is the
|
|
12743
12802
|
* queue URL), not surfaced by `GetQueueAttributes`.
|
|
12744
12803
|
*
|
|
12745
|
-
* `Tags` is
|
|
12746
|
-
*
|
|
12747
|
-
*
|
|
12804
|
+
* `Tags` is surfaced via `ListQueueTags` (returns a tag-name → value map).
|
|
12805
|
+
* CDK's `aws:*` auto-tags are filtered out by `normalizeAwsTagsToCfn`; the
|
|
12806
|
+
* result key is omitted entirely when AWS reports no user tags (matches
|
|
12807
|
+
* `create()`'s behavior of only sending Tags when the template carries
|
|
12808
|
+
* them).
|
|
12748
12809
|
*
|
|
12749
12810
|
* Returns `undefined` when the queue is gone (`QueueDoesNotExist`).
|
|
12750
12811
|
*/
|
|
@@ -12812,6 +12873,18 @@ var SQSQueueProvider = class {
|
|
|
12812
12873
|
result["RedrivePolicy"] = attributes["RedrivePolicy"];
|
|
12813
12874
|
}
|
|
12814
12875
|
}
|
|
12876
|
+
try {
|
|
12877
|
+
const tagsResp = await this.sqsClient.send(
|
|
12878
|
+
new ListQueueTagsCommand({ QueueUrl: physicalId })
|
|
12879
|
+
);
|
|
12880
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.Tags);
|
|
12881
|
+
if (tags.length > 0)
|
|
12882
|
+
result["Tags"] = tags;
|
|
12883
|
+
} catch (err) {
|
|
12884
|
+
if (err instanceof QueueDoesNotExist)
|
|
12885
|
+
return void 0;
|
|
12886
|
+
throw err;
|
|
12887
|
+
}
|
|
12815
12888
|
return result;
|
|
12816
12889
|
}
|
|
12817
12890
|
/**
|
|
@@ -13431,11 +13504,16 @@ var SNSTopicProvider = class {
|
|
|
13431
13504
|
* `TopicName` is derived from the ARN tail (the `physicalId` is the
|
|
13432
13505
|
* topic ARN).
|
|
13433
13506
|
*
|
|
13434
|
-
* `Tags`
|
|
13435
|
-
* `
|
|
13436
|
-
*
|
|
13437
|
-
*
|
|
13438
|
-
*
|
|
13507
|
+
* `Tags` is surfaced via a follow-up `ListTagsForResource` call. CDK's
|
|
13508
|
+
* `aws:*` auto-tags are filtered out by `normalizeAwsTagsToCfn`; the
|
|
13509
|
+
* result key is omitted entirely when AWS reports no user tags (matches
|
|
13510
|
+
* `create()`'s behavior of only sending Tags when the template carries
|
|
13511
|
+
* them).
|
|
13512
|
+
*
|
|
13513
|
+
* `DeliveryStatusLogging` is intentionally omitted: it fans out into
|
|
13514
|
+
* per-protocol attributes (`{Protocol}SuccessFeedbackRoleArn`, etc.) whose
|
|
13515
|
+
* round-trip back to the CFn array shape needs more thought than fits in
|
|
13516
|
+
* this PR.
|
|
13439
13517
|
*
|
|
13440
13518
|
* `Subscription` is omitted because CDK manages it via separate
|
|
13441
13519
|
* `AWS::SNS::Subscription` resources, not as a Topic property.
|
|
@@ -13488,8 +13566,32 @@ var SNSTopicProvider = class {
|
|
|
13488
13566
|
}
|
|
13489
13567
|
}
|
|
13490
13568
|
}
|
|
13569
|
+
try {
|
|
13570
|
+
const tagsResp = await this.snsClient.send(
|
|
13571
|
+
new ListTagsForResourceCommand({ ResourceArn: physicalId })
|
|
13572
|
+
);
|
|
13573
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.Tags);
|
|
13574
|
+
if (tags.length > 0)
|
|
13575
|
+
result["Tags"] = tags;
|
|
13576
|
+
} catch (err) {
|
|
13577
|
+
if (err instanceof NotFoundException)
|
|
13578
|
+
return void 0;
|
|
13579
|
+
throw err;
|
|
13580
|
+
}
|
|
13491
13581
|
return result;
|
|
13492
13582
|
}
|
|
13583
|
+
/**
|
|
13584
|
+
* `DeliveryStatusLogging` fans out to per-protocol attributes
|
|
13585
|
+
* (`{Protocol}SuccessFeedbackRoleArn` etc.) whose round-trip back to the
|
|
13586
|
+
* CFn array shape is not yet implemented; `Subscription` is managed via
|
|
13587
|
+
* separate `AWS::SNS::Subscription` resources rather than the Topic
|
|
13588
|
+
* itself. Both are absent from `readCurrentState`, so tell the drift
|
|
13589
|
+
* comparator to skip them and avoid the guaranteed false-positive that
|
|
13590
|
+
* would fire on every clean run when the user did template either.
|
|
13591
|
+
*/
|
|
13592
|
+
getDriftUnknownPaths() {
|
|
13593
|
+
return ["DeliveryStatusLogging", "Subscription"];
|
|
13594
|
+
}
|
|
13493
13595
|
/**
|
|
13494
13596
|
* Adopt an existing SNS topic into cdkd state.
|
|
13495
13597
|
*
|
|
@@ -14691,11 +14793,13 @@ var LambdaFunctionProvider = class {
|
|
|
14691
14793
|
* function's `CodeSha256` does live in `GetFunction` but is not what
|
|
14692
14794
|
* cdkd's `Code: { S3Bucket, S3Key }` state property carries).
|
|
14693
14795
|
*
|
|
14694
|
-
* `Tags` is
|
|
14695
|
-
*
|
|
14696
|
-
*
|
|
14697
|
-
*
|
|
14698
|
-
*
|
|
14796
|
+
* `Tags` is surfaced from the `Tags` map on the same `GetFunction`
|
|
14797
|
+
* response. CDK's auto-injected `aws:cdk:*` tags (which AWS happily
|
|
14798
|
+
* returns) are filtered out by `normalizeAwsTagsToCfn` so they don't
|
|
14799
|
+
* fire false-positive drift against state. The result key is omitted
|
|
14800
|
+
* entirely when AWS reports no user tags, matching `create()`'s
|
|
14801
|
+
* behavior of only sending `Tags` when the user explicitly passes
|
|
14802
|
+
* them.
|
|
14699
14803
|
*
|
|
14700
14804
|
* Returns `undefined` when the function is gone (`ResourceNotFoundException`).
|
|
14701
14805
|
*/
|
|
@@ -14753,6 +14857,9 @@ var LambdaFunctionProvider = class {
|
|
|
14753
14857
|
if (Object.keys(vpc).length > 0)
|
|
14754
14858
|
result["VpcConfig"] = vpc;
|
|
14755
14859
|
}
|
|
14860
|
+
const tags = normalizeAwsTagsToCfn(resp.Tags);
|
|
14861
|
+
if (tags.length > 0)
|
|
14862
|
+
result["Tags"] = tags;
|
|
14756
14863
|
return result;
|
|
14757
14864
|
} catch (err) {
|
|
14758
14865
|
if (err instanceof ResourceNotFoundException)
|
|
@@ -14760,6 +14867,17 @@ var LambdaFunctionProvider = class {
|
|
|
14760
14867
|
throw err;
|
|
14761
14868
|
}
|
|
14762
14869
|
}
|
|
14870
|
+
/**
|
|
14871
|
+
* `Code: { S3Bucket, S3Key }` is set on create / update but `GetFunction`
|
|
14872
|
+
* only returns a pre-signed URL for the deployed code, never the original
|
|
14873
|
+
* asset key — so a state-recorded `Code` value can never match an
|
|
14874
|
+
* AWS-current snapshot. Tell the drift comparator to skip the whole
|
|
14875
|
+
* `Code` subtree to avoid the guaranteed false-positive that would fire
|
|
14876
|
+
* on every clean run.
|
|
14877
|
+
*/
|
|
14878
|
+
getDriftUnknownPaths() {
|
|
14879
|
+
return ["Code"];
|
|
14880
|
+
}
|
|
14763
14881
|
/**
|
|
14764
14882
|
* Adopt an existing Lambda function into cdkd state.
|
|
14765
14883
|
*
|
|
@@ -15903,6 +16021,16 @@ var LambdaLayerVersionProvider = class {
|
|
|
15903
16021
|
}
|
|
15904
16022
|
return result;
|
|
15905
16023
|
}
|
|
16024
|
+
/**
|
|
16025
|
+
* `Content: { S3Bucket, S3Key }` is set on create but
|
|
16026
|
+
* `GetLayerVersionByArn` only returns a pre-signed URL for the deployed
|
|
16027
|
+
* content — the original asset key is unrecoverable. Tell the drift
|
|
16028
|
+
* comparator to skip the whole `Content` subtree to avoid the guaranteed
|
|
16029
|
+
* false-positive that would fire on every clean run.
|
|
16030
|
+
*/
|
|
16031
|
+
getDriftUnknownPaths() {
|
|
16032
|
+
return ["Content"];
|
|
16033
|
+
}
|
|
15906
16034
|
/**
|
|
15907
16035
|
* Adopt an existing Lambda layer version into cdkd state.
|
|
15908
16036
|
*
|
|
@@ -16235,10 +16363,12 @@ var DynamoDBTableProvider = class {
|
|
|
16235
16363
|
*
|
|
16236
16364
|
* Returns `undefined` when the table is gone (`ResourceNotFoundException`).
|
|
16237
16365
|
*
|
|
16238
|
-
* Tags are
|
|
16239
|
-
*
|
|
16240
|
-
*
|
|
16241
|
-
*
|
|
16366
|
+
* Tags are surfaced via a follow-up `ListTagsOfResource` call (DynamoDB
|
|
16367
|
+
* doesn't include tags in `DescribeTable`). CDK's `aws:*` auto-tags are
|
|
16368
|
+
* filtered out by `normalizeAwsTagsToCfn` so they don't fire false-positive
|
|
16369
|
+
* drift, and the result key is omitted entirely when AWS reports no user
|
|
16370
|
+
* tags (matches `create()`'s behavior of only sending Tags when the
|
|
16371
|
+
* template carries them).
|
|
16242
16372
|
*/
|
|
16243
16373
|
async readCurrentState(physicalId, _logicalId, _resourceType) {
|
|
16244
16374
|
try {
|
|
@@ -16295,6 +16425,20 @@ var DynamoDBTableProvider = class {
|
|
|
16295
16425
|
if (table.TableClassSummary?.TableClass) {
|
|
16296
16426
|
result["TableClass"] = table.TableClassSummary.TableClass;
|
|
16297
16427
|
}
|
|
16428
|
+
if (table.TableArn) {
|
|
16429
|
+
try {
|
|
16430
|
+
const tagsResp = await this.dynamoDBClient.send(
|
|
16431
|
+
new ListTagsOfResourceCommand({ ResourceArn: table.TableArn })
|
|
16432
|
+
);
|
|
16433
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.Tags);
|
|
16434
|
+
if (tags.length > 0)
|
|
16435
|
+
result["Tags"] = tags;
|
|
16436
|
+
} catch (err) {
|
|
16437
|
+
if (err instanceof ResourceNotFoundException6)
|
|
16438
|
+
return void 0;
|
|
16439
|
+
throw err;
|
|
16440
|
+
}
|
|
16441
|
+
}
|
|
16298
16442
|
return result;
|
|
16299
16443
|
} catch (err) {
|
|
16300
16444
|
if (err instanceof ResourceNotFoundException6)
|
|
@@ -16616,11 +16760,16 @@ var LogsLogGroupProvider = class {
|
|
|
16616
16760
|
* `RetentionInDays`).
|
|
16617
16761
|
*
|
|
16618
16762
|
* Coverage: `LogGroupName`, `KmsKeyId`, `RetentionInDays`,
|
|
16619
|
-
* `LogGroupClass`. Other handledProperties (`DataProtectionPolicy`,
|
|
16620
|
-
* `
|
|
16763
|
+
* `LogGroupClass`, `Tags`. Other handledProperties (`DataProtectionPolicy`,
|
|
16764
|
+
* `FieldIndexPolicies`, `ResourcePolicyDocument`,
|
|
16621
16765
|
* `DeletionProtectionEnabled`, `BearerTokenAuthenticationEnabled`) need
|
|
16622
16766
|
* their own per-property API call and are out of scope for v1.
|
|
16623
16767
|
*
|
|
16768
|
+
* Tags are read via `ListTagsForResource` (using the log-group ARN from
|
|
16769
|
+
* the same `DescribeLogGroups` response). CDK's `aws:*` auto-tags are
|
|
16770
|
+
* filtered out so they don't fire false-positive drift; the result key is
|
|
16771
|
+
* omitted entirely when AWS reports no user tags.
|
|
16772
|
+
*
|
|
16624
16773
|
* Returns `undefined` when the log group is gone.
|
|
16625
16774
|
*/
|
|
16626
16775
|
async readCurrentState(physicalId, _logicalId, _resourceType) {
|
|
@@ -16641,6 +16790,21 @@ var LogsLogGroupProvider = class {
|
|
|
16641
16790
|
}
|
|
16642
16791
|
if (found.logGroupClass !== void 0)
|
|
16643
16792
|
result["LogGroupClass"] = found.logGroupClass;
|
|
16793
|
+
if (found.arn) {
|
|
16794
|
+
const arnForTags = found.arn.replace(/:\*$/, "");
|
|
16795
|
+
try {
|
|
16796
|
+
const tagsResp = await this.logsClient.send(
|
|
16797
|
+
new ListTagsForResourceCommand2({ resourceArn: arnForTags })
|
|
16798
|
+
);
|
|
16799
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.tags);
|
|
16800
|
+
if (tags.length > 0)
|
|
16801
|
+
result["Tags"] = tags;
|
|
16802
|
+
} catch (err) {
|
|
16803
|
+
if (err instanceof ResourceNotFoundException7)
|
|
16804
|
+
return void 0;
|
|
16805
|
+
throw err;
|
|
16806
|
+
}
|
|
16807
|
+
}
|
|
16644
16808
|
return result;
|
|
16645
16809
|
} catch (err) {
|
|
16646
16810
|
if (err instanceof ResourceNotFoundException7)
|
|
@@ -17010,6 +17174,20 @@ var CloudWatchAlarmProvider = class {
|
|
|
17010
17174
|
if (alarm.Metrics && alarm.Metrics.length > 0) {
|
|
17011
17175
|
result["Metrics"] = alarm.Metrics.map((m) => m);
|
|
17012
17176
|
}
|
|
17177
|
+
if (alarm.AlarmArn) {
|
|
17178
|
+
try {
|
|
17179
|
+
const tagsResp = await this.cloudWatchClient.send(
|
|
17180
|
+
new ListTagsForResourceCommand3({ ResourceARN: alarm.AlarmArn })
|
|
17181
|
+
);
|
|
17182
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.Tags);
|
|
17183
|
+
if (tags.length > 0)
|
|
17184
|
+
result["Tags"] = tags;
|
|
17185
|
+
} catch (err) {
|
|
17186
|
+
this.logger.debug(
|
|
17187
|
+
`CloudWatch ListTagsForResource(${alarm.AlarmArn}) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
17188
|
+
);
|
|
17189
|
+
}
|
|
17190
|
+
}
|
|
17013
17191
|
return result;
|
|
17014
17192
|
}
|
|
17015
17193
|
async import(input) {
|
|
@@ -17348,8 +17526,10 @@ var SecretsManagerSecretProvider = class {
|
|
|
17348
17526
|
* call to avoid surfacing plaintext through drift). Cdkd state holds
|
|
17349
17527
|
* the user-supplied string verbatim; comparing against AWS would
|
|
17350
17528
|
* require pulling the value, so this is deliberately deferred.
|
|
17351
|
-
*
|
|
17352
|
-
*
|
|
17529
|
+
*
|
|
17530
|
+
* `Tags` is surfaced from the same `DescribeSecret` response (no extra
|
|
17531
|
+
* round-trip). CDK's `aws:*` auto-tags are filtered out; the result key
|
|
17532
|
+
* is omitted entirely when AWS reports no user tags.
|
|
17353
17533
|
*
|
|
17354
17534
|
* Returns `undefined` when the secret is gone (`ResourceNotFoundException`).
|
|
17355
17535
|
*/
|
|
@@ -17374,6 +17554,9 @@ var SecretsManagerSecretProvider = class {
|
|
|
17374
17554
|
return out;
|
|
17375
17555
|
});
|
|
17376
17556
|
}
|
|
17557
|
+
const tags = normalizeAwsTagsToCfn(resp.Tags);
|
|
17558
|
+
if (tags.length > 0)
|
|
17559
|
+
result["Tags"] = tags;
|
|
17377
17560
|
return result;
|
|
17378
17561
|
} catch (err) {
|
|
17379
17562
|
if (err instanceof ResourceNotFoundException8)
|
|
@@ -17381,6 +17564,16 @@ var SecretsManagerSecretProvider = class {
|
|
|
17381
17564
|
throw err;
|
|
17382
17565
|
}
|
|
17383
17566
|
}
|
|
17567
|
+
/**
|
|
17568
|
+
* `SecretString` and `GenerateSecretString` are set on create but
|
|
17569
|
+
* `DescribeSecret` does not return the secret value (that lives behind
|
|
17570
|
+
* `GetSecretValue`, which we deliberately never call to avoid surfacing
|
|
17571
|
+
* plaintext through drift). Tell the drift comparator to skip both keys
|
|
17572
|
+
* so they don't fire guaranteed false-positive drift on every clean run.
|
|
17573
|
+
*/
|
|
17574
|
+
getDriftUnknownPaths() {
|
|
17575
|
+
return ["SecretString", "GenerateSecretString"];
|
|
17576
|
+
}
|
|
17384
17577
|
/**
|
|
17385
17578
|
* Adopt an existing Secrets Manager secret into cdkd state.
|
|
17386
17579
|
*
|
|
@@ -17660,12 +17853,12 @@ var SSMParameterProvider = class {
|
|
|
17660
17853
|
* metadata (`Description`, `AllowedPattern`, `Tier`) that `GetParameter`
|
|
17661
17854
|
* does not return.
|
|
17662
17855
|
*
|
|
17663
|
-
* `Name` is set to the physical id. `Tags`
|
|
17664
|
-
*
|
|
17665
|
-
*
|
|
17666
|
-
* `Policies`
|
|
17667
|
-
*
|
|
17668
|
-
*
|
|
17856
|
+
* `Name` is set to the physical id. `Tags` is surfaced via a follow-up
|
|
17857
|
+
* `ListTagsForResource(ResourceType=Parameter)` call, with CDK's `aws:*`
|
|
17858
|
+
* auto-tags filtered out. `Policies` is intentionally out of scope:
|
|
17859
|
+
* `DescribeParameters.Policies` returns a structured array but cdkd state
|
|
17860
|
+
* holds the raw JSON string the user typed — comparing the two accurately
|
|
17861
|
+
* needs more work.
|
|
17669
17862
|
*
|
|
17670
17863
|
* **Note**: For `SecureString` parameters, AWS returns the encrypted
|
|
17671
17864
|
* blob in `Value` (we pass `WithDecryption: false`). cdkd state usually
|
|
@@ -17717,6 +17910,18 @@ var SSMParameterProvider = class {
|
|
|
17717
17910
|
}
|
|
17718
17911
|
} catch {
|
|
17719
17912
|
}
|
|
17913
|
+
try {
|
|
17914
|
+
const tagsResp = await this.ssmClient.send(
|
|
17915
|
+
new ListTagsForResourceCommand4({
|
|
17916
|
+
ResourceType: "Parameter",
|
|
17917
|
+
ResourceId: physicalId
|
|
17918
|
+
})
|
|
17919
|
+
);
|
|
17920
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.TagList);
|
|
17921
|
+
if (tags.length > 0)
|
|
17922
|
+
result["Tags"] = tags;
|
|
17923
|
+
} catch {
|
|
17924
|
+
}
|
|
17720
17925
|
return result;
|
|
17721
17926
|
}
|
|
17722
17927
|
/**
|
|
@@ -18060,8 +18265,10 @@ var EventBridgeRuleProvider = class {
|
|
|
18060
18265
|
* it as the user typed it, typically an object), `ScheduleExpression`,
|
|
18061
18266
|
* `State`, `RoleArn`, `Targets` (CFn shape `[{Id, Arn, ...}]`).
|
|
18062
18267
|
*
|
|
18063
|
-
* `Tags` is
|
|
18064
|
-
*
|
|
18268
|
+
* `Tags` is surfaced via a follow-up `ListTagsForResource` call (using the
|
|
18269
|
+
* rule ARN — the same `physicalId` cdkd state holds). CDK's `aws:*`
|
|
18270
|
+
* auto-tags are filtered out; the result key is omitted entirely when AWS
|
|
18271
|
+
* reports no user tags.
|
|
18065
18272
|
*
|
|
18066
18273
|
* Returns `undefined` when the rule is gone (`ResourceNotFoundException`).
|
|
18067
18274
|
*/
|
|
@@ -18119,6 +18326,18 @@ var EventBridgeRuleProvider = class {
|
|
|
18119
18326
|
throw err;
|
|
18120
18327
|
}
|
|
18121
18328
|
}
|
|
18329
|
+
try {
|
|
18330
|
+
const tagsResp = await this.eventBridgeClient.send(
|
|
18331
|
+
new ListTagsForResourceCommand5({ ResourceARN: physicalId })
|
|
18332
|
+
);
|
|
18333
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.Tags);
|
|
18334
|
+
if (tags.length > 0)
|
|
18335
|
+
result["Tags"] = tags;
|
|
18336
|
+
} catch (err) {
|
|
18337
|
+
if (!(err instanceof ResourceNotFoundException9)) {
|
|
18338
|
+
throw err;
|
|
18339
|
+
}
|
|
18340
|
+
}
|
|
18122
18341
|
return result;
|
|
18123
18342
|
}
|
|
18124
18343
|
/**
|
|
@@ -18489,10 +18708,13 @@ var EventBridgeBusProvider = class {
|
|
|
18489
18708
|
* the user typed it, which may be either an object or a string — the
|
|
18490
18709
|
* comparator handles either side).
|
|
18491
18710
|
*
|
|
18492
|
-
* `Tags`
|
|
18493
|
-
*
|
|
18494
|
-
*
|
|
18495
|
-
*
|
|
18711
|
+
* `Tags` is surfaced via a follow-up `ListTagsForResource` call (using the
|
|
18712
|
+
* bus ARN from the same `DescribeEventBus` response). CDK's `aws:*`
|
|
18713
|
+
* auto-tags are filtered out; the result key is omitted when AWS reports
|
|
18714
|
+
* no user tags.
|
|
18715
|
+
*
|
|
18716
|
+
* `EventSourceName` is intentionally omitted: it is set at create time
|
|
18717
|
+
* only and not surfaced by `DescribeEventBus`.
|
|
18496
18718
|
*
|
|
18497
18719
|
* Returns `undefined` when the bus is gone (`ResourceNotFoundException`).
|
|
18498
18720
|
*/
|
|
@@ -18520,6 +18742,20 @@ var EventBridgeBusProvider = class {
|
|
|
18520
18742
|
result["Policy"] = resp.Policy;
|
|
18521
18743
|
}
|
|
18522
18744
|
}
|
|
18745
|
+
if (resp.Arn) {
|
|
18746
|
+
try {
|
|
18747
|
+
const tagsResp = await this.eventBridgeClient.send(
|
|
18748
|
+
new ListTagsForResourceCommand6({ ResourceARN: resp.Arn })
|
|
18749
|
+
);
|
|
18750
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.Tags);
|
|
18751
|
+
if (tags.length > 0)
|
|
18752
|
+
result["Tags"] = tags;
|
|
18753
|
+
} catch (err) {
|
|
18754
|
+
if (err instanceof ResourceNotFoundException10)
|
|
18755
|
+
return void 0;
|
|
18756
|
+
throw err;
|
|
18757
|
+
}
|
|
18758
|
+
}
|
|
18523
18759
|
return result;
|
|
18524
18760
|
} catch (err) {
|
|
18525
18761
|
if (err instanceof ResourceNotFoundException10)
|
|
@@ -22818,6 +23054,9 @@ var ApiGatewayV2Provider = class {
|
|
|
22818
23054
|
}
|
|
22819
23055
|
if (resp.CorsConfiguration)
|
|
22820
23056
|
result["CorsConfiguration"] = resp.CorsConfiguration;
|
|
23057
|
+
const tags = normalizeAwsTagsToCfn(resp.Tags);
|
|
23058
|
+
if (tags.length > 0)
|
|
23059
|
+
result["Tags"] = tags;
|
|
22821
23060
|
return result;
|
|
22822
23061
|
} catch (err) {
|
|
22823
23062
|
if (err instanceof NotFoundException4)
|
|
@@ -24268,8 +24507,9 @@ var StepFunctionsProvider = class {
|
|
|
24268
24507
|
* time and not surfaced by `DescribeStateMachine` (the response carries
|
|
24269
24508
|
* the already-substituted definition).
|
|
24270
24509
|
*
|
|
24271
|
-
* `Tags` is
|
|
24272
|
-
* `aws
|
|
24510
|
+
* `Tags` is surfaced via a follow-up `ListTagsForResource(arn)` call.
|
|
24511
|
+
* CDK's `aws:*` auto-tags are filtered out; the result key is omitted
|
|
24512
|
+
* entirely when AWS reports no user tags.
|
|
24273
24513
|
*
|
|
24274
24514
|
* Returns `undefined` when the state machine is gone (`StateMachineDoesNotExist`).
|
|
24275
24515
|
*/
|
|
@@ -24337,6 +24577,17 @@ var StepFunctionsProvider = class {
|
|
|
24337
24577
|
if (Object.keys(ec).length > 0)
|
|
24338
24578
|
result["EncryptionConfiguration"] = ec;
|
|
24339
24579
|
}
|
|
24580
|
+
try {
|
|
24581
|
+
const tagsResp = await this.getClient().send(
|
|
24582
|
+
new ListTagsForResourceCommand8({ resourceArn: physicalId })
|
|
24583
|
+
);
|
|
24584
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.tags);
|
|
24585
|
+
if (tags.length > 0)
|
|
24586
|
+
result["Tags"] = tags;
|
|
24587
|
+
} catch (err) {
|
|
24588
|
+
if (!(err instanceof StateMachineDoesNotExist))
|
|
24589
|
+
throw err;
|
|
24590
|
+
}
|
|
24340
24591
|
return result;
|
|
24341
24592
|
}
|
|
24342
24593
|
/**
|
|
@@ -25178,8 +25429,11 @@ var ECSProvider = class {
|
|
|
25178
25429
|
* - `AWS::ECS::TaskDefinition` → `DescribeTaskDefinition`
|
|
25179
25430
|
*
|
|
25180
25431
|
* Each branch surfaces only the keys cdkd's `create()` accepts, mapping
|
|
25181
|
-
* the SDK's camelCase to CFn PascalCase. Tags are
|
|
25182
|
-
* (
|
|
25432
|
+
* the SDK's camelCase to CFn PascalCase. Tags are surfaced via
|
|
25433
|
+
* `DescribeClusters/Services(include=[TAGS])` for cluster / service, and
|
|
25434
|
+
* via `DescribeTaskDefinition(include=[TAGS])` for task definitions —
|
|
25435
|
+
* with CDK's `aws:*` auto-tags filtered out. Tag-result keys are omitted
|
|
25436
|
+
* when AWS reports no user tags.
|
|
25183
25437
|
*/
|
|
25184
25438
|
async readCurrentState(physicalId, _logicalId, resourceType) {
|
|
25185
25439
|
switch (resourceType) {
|
|
@@ -25197,7 +25451,7 @@ var ECSProvider = class {
|
|
|
25197
25451
|
let resp;
|
|
25198
25452
|
try {
|
|
25199
25453
|
resp = await this.getClient().send(
|
|
25200
|
-
new DescribeClustersCommand({ clusters: [physicalId] })
|
|
25454
|
+
new DescribeClustersCommand({ clusters: [physicalId], include: ["TAGS"] })
|
|
25201
25455
|
);
|
|
25202
25456
|
} catch {
|
|
25203
25457
|
return void 0;
|
|
@@ -25220,6 +25474,9 @@ var ECSProvider = class {
|
|
|
25220
25474
|
Value: s.value
|
|
25221
25475
|
}));
|
|
25222
25476
|
}
|
|
25477
|
+
const tags = normalizeAwsTagsToCfn(c.tags);
|
|
25478
|
+
if (tags.length > 0)
|
|
25479
|
+
result["Tags"] = tags;
|
|
25223
25480
|
return result;
|
|
25224
25481
|
}
|
|
25225
25482
|
async readCurrentStateService(physicalId) {
|
|
@@ -25231,7 +25488,11 @@ var ECSProvider = class {
|
|
|
25231
25488
|
let resp;
|
|
25232
25489
|
try {
|
|
25233
25490
|
resp = await this.getClient().send(
|
|
25234
|
-
new DescribeServicesCommand({
|
|
25491
|
+
new DescribeServicesCommand({
|
|
25492
|
+
cluster: clusterArn,
|
|
25493
|
+
services: [serviceName],
|
|
25494
|
+
include: ["TAGS"]
|
|
25495
|
+
})
|
|
25235
25496
|
);
|
|
25236
25497
|
} catch {
|
|
25237
25498
|
return void 0;
|
|
@@ -25284,13 +25545,16 @@ var ECSProvider = class {
|
|
|
25284
25545
|
if (s.serviceRegistries && s.serviceRegistries.length > 0) {
|
|
25285
25546
|
result["ServiceRegistries"] = s.serviceRegistries;
|
|
25286
25547
|
}
|
|
25548
|
+
const tags = normalizeAwsTagsToCfn(s.tags);
|
|
25549
|
+
if (tags.length > 0)
|
|
25550
|
+
result["Tags"] = tags;
|
|
25287
25551
|
return result;
|
|
25288
25552
|
}
|
|
25289
25553
|
async readCurrentStateTaskDefinition(physicalId) {
|
|
25290
25554
|
let resp;
|
|
25291
25555
|
try {
|
|
25292
25556
|
resp = await this.getClient().send(
|
|
25293
|
-
new DescribeTaskDefinitionCommand({ taskDefinition: physicalId })
|
|
25557
|
+
new DescribeTaskDefinitionCommand({ taskDefinition: physicalId, include: ["TAGS"] })
|
|
25294
25558
|
);
|
|
25295
25559
|
} catch {
|
|
25296
25560
|
return void 0;
|
|
@@ -25333,6 +25597,9 @@ var ECSProvider = class {
|
|
|
25333
25597
|
if (td.containerDefinitions && td.containerDefinitions.length > 0) {
|
|
25334
25598
|
result["ContainerDefinitions"] = td.containerDefinitions;
|
|
25335
25599
|
}
|
|
25600
|
+
const tags = normalizeAwsTagsToCfn(resp.tags);
|
|
25601
|
+
if (tags.length > 0)
|
|
25602
|
+
result["Tags"] = tags;
|
|
25336
25603
|
return result;
|
|
25337
25604
|
}
|
|
25338
25605
|
/**
|
|
@@ -25961,8 +26228,11 @@ var ELBv2Provider = class {
|
|
|
25961
26228
|
* - `Listener` → `DescribeListeners` (LoadBalancerArn, Certificates,
|
|
25962
26229
|
* DefaultActions, Port, Protocol, SslPolicy).
|
|
25963
26230
|
*
|
|
25964
|
-
* Tags are
|
|
25965
|
-
*
|
|
26231
|
+
* Tags are surfaced via a follow-up `DescribeTags(ResourceArns=[arn])`
|
|
26232
|
+
* for all three types (the `physicalId` cdkd state holds is the ARN).
|
|
26233
|
+
* CDK's `aws:*` auto-tags are filtered out and the result key is omitted
|
|
26234
|
+
* when AWS reports no user tags. Returns `undefined` when the resource
|
|
26235
|
+
* is gone (`*NotFoundException`).
|
|
25966
26236
|
*/
|
|
25967
26237
|
async readCurrentState(physicalId, _logicalId, resourceType) {
|
|
25968
26238
|
switch (resourceType) {
|
|
@@ -26009,6 +26279,7 @@ var ELBv2Provider = class {
|
|
|
26009
26279
|
result["Type"] = lb.Type;
|
|
26010
26280
|
if (lb.IpAddressType !== void 0)
|
|
26011
26281
|
result["IpAddressType"] = lb.IpAddressType;
|
|
26282
|
+
await this.attachTags(result, physicalId);
|
|
26012
26283
|
return result;
|
|
26013
26284
|
}
|
|
26014
26285
|
async readTargetGroup(physicalId) {
|
|
@@ -26067,6 +26338,7 @@ var ELBv2Provider = class {
|
|
|
26067
26338
|
if (Object.keys(matcher).length > 0)
|
|
26068
26339
|
result["Matcher"] = matcher;
|
|
26069
26340
|
}
|
|
26341
|
+
await this.attachTags(result, physicalId);
|
|
26070
26342
|
return result;
|
|
26071
26343
|
}
|
|
26072
26344
|
async readListener(physicalId) {
|
|
@@ -26108,8 +26380,23 @@ var ELBv2Provider = class {
|
|
|
26108
26380
|
(a) => a
|
|
26109
26381
|
);
|
|
26110
26382
|
}
|
|
26383
|
+
await this.attachTags(result, physicalId);
|
|
26111
26384
|
return result;
|
|
26112
26385
|
}
|
|
26386
|
+
/** Best-effort tag fetch via `DescribeTags(ResourceArns=[arn])`. */
|
|
26387
|
+
async attachTags(result, arn) {
|
|
26388
|
+
try {
|
|
26389
|
+
const resp = await this.getClient().send(new DescribeTagsCommand({ ResourceArns: [arn] }));
|
|
26390
|
+
const tagDesc = resp.TagDescriptions?.[0];
|
|
26391
|
+
const tags = normalizeAwsTagsToCfn(tagDesc?.Tags);
|
|
26392
|
+
if (tags.length > 0)
|
|
26393
|
+
result["Tags"] = tags;
|
|
26394
|
+
} catch (err) {
|
|
26395
|
+
this.logger.debug(
|
|
26396
|
+
`ELBv2 DescribeTags(${arn}) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
26397
|
+
);
|
|
26398
|
+
}
|
|
26399
|
+
}
|
|
26113
26400
|
/**
|
|
26114
26401
|
* Adopt an existing ELBv2 LoadBalancer or TargetGroup into cdkd state.
|
|
26115
26402
|
*
|
|
@@ -26864,8 +27151,10 @@ var RDSProvider = class {
|
|
|
26864
27151
|
*
|
|
26865
27152
|
* Each branch surfaces only the keys cdkd's `create()` accepts. Sensitive
|
|
26866
27153
|
* fields like `MasterUserPassword` are NEVER surfaced (RDS does not return
|
|
26867
|
-
* them in the Describe responses). `Tags` are
|
|
26868
|
-
* (
|
|
27154
|
+
* them in the Describe responses). `Tags` are surfaced via a follow-up
|
|
27155
|
+
* `ListTagsForResource(ResourceName=arn)` call (RDS uses `[{Key, Value}]`
|
|
27156
|
+
* shape). CDK's `aws:*` auto-tags are filtered out; the result key is
|
|
27157
|
+
* omitted entirely when AWS reports no user tags.
|
|
26869
27158
|
*
|
|
26870
27159
|
* Returns `undefined` when the resource is gone (`*NotFoundFault`).
|
|
26871
27160
|
*/
|
|
@@ -26909,6 +27198,8 @@ var RDSProvider = class {
|
|
|
26909
27198
|
if (inst.PubliclyAccessible !== void 0) {
|
|
26910
27199
|
result["PubliclyAccessible"] = inst.PubliclyAccessible;
|
|
26911
27200
|
}
|
|
27201
|
+
if (inst.DBInstanceArn)
|
|
27202
|
+
await this.attachTags(result, inst.DBInstanceArn);
|
|
26912
27203
|
return result;
|
|
26913
27204
|
}
|
|
26914
27205
|
async readCurrentStateDBCluster(physicalId) {
|
|
@@ -26965,6 +27256,8 @@ var RDSProvider = class {
|
|
|
26965
27256
|
if (Object.keys(sc).length > 0)
|
|
26966
27257
|
result["ServerlessV2ScalingConfiguration"] = sc;
|
|
26967
27258
|
}
|
|
27259
|
+
if (cluster.DBClusterArn)
|
|
27260
|
+
await this.attachTags(result, cluster.DBClusterArn);
|
|
26968
27261
|
return result;
|
|
26969
27262
|
}
|
|
26970
27263
|
async readCurrentStateDBSubnetGroup(physicalId) {
|
|
@@ -26992,8 +27285,31 @@ var RDSProvider = class {
|
|
|
26992
27285
|
(id) => !!id
|
|
26993
27286
|
);
|
|
26994
27287
|
}
|
|
27288
|
+
if (sg.DBSubnetGroupArn)
|
|
27289
|
+
await this.attachTags(result, sg.DBSubnetGroupArn);
|
|
26995
27290
|
return result;
|
|
26996
27291
|
}
|
|
27292
|
+
/**
|
|
27293
|
+
* Fetch tags via `ListTagsForResource(ResourceName=arn)` and merge them
|
|
27294
|
+
* into the result under `Tags` (CFn shape, `aws:*` filtered out, omitted
|
|
27295
|
+
* when empty). Best-effort: tag-fetch failures are logged at debug and
|
|
27296
|
+
* the key is simply left out — drift detection on configuration is more
|
|
27297
|
+
* important than fail-closing on a missing tag permission.
|
|
27298
|
+
*/
|
|
27299
|
+
async attachTags(result, arn) {
|
|
27300
|
+
try {
|
|
27301
|
+
const tagsResp = await this.getClient().send(
|
|
27302
|
+
new ListTagsForResourceCommand10({ ResourceName: arn })
|
|
27303
|
+
);
|
|
27304
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.TagList);
|
|
27305
|
+
if (tags.length > 0)
|
|
27306
|
+
result["Tags"] = tags;
|
|
27307
|
+
} catch (err) {
|
|
27308
|
+
this.logger.debug(
|
|
27309
|
+
`RDS ListTagsForResource(${arn}) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
27310
|
+
);
|
|
27311
|
+
}
|
|
27312
|
+
}
|
|
26997
27313
|
async importDBInstance(input) {
|
|
26998
27314
|
const explicit = resolveExplicitPhysicalId(input, "DBInstanceIdentifier");
|
|
26999
27315
|
if (explicit) {
|
|
@@ -27770,10 +28086,11 @@ var Route53Provider = class {
|
|
|
27770
28086
|
*
|
|
27771
28087
|
* Dispatch per resource type:
|
|
27772
28088
|
* - `HostedZone` → `GetHostedZone` (Name, HostedZoneConfig{Comment,
|
|
27773
|
-
* PrivateZone}, VPCs from `VPCs[]
|
|
27774
|
-
*
|
|
27775
|
-
*
|
|
27776
|
-
*
|
|
28089
|
+
* PrivateZone}, VPCs from `VPCs[]`, HostedZoneTags via
|
|
28090
|
+
* `ListTagsForResource(ResourceType=hostedzone, ResourceId=<idTail>)`
|
|
28091
|
+
* with `aws:*` filtered out and the key omitted when empty).
|
|
28092
|
+
* QueryLoggingConfig is skipped because it's a separate
|
|
28093
|
+
* `ListQueryLoggingConfigs` call and the v1 surface does not surface it.
|
|
27777
28094
|
* - `RecordSet` → `ListResourceRecordSets` filtered to the exact
|
|
27778
28095
|
* `(name, type)` pair from the composite physicalId
|
|
27779
28096
|
* (`{zoneId}|{name}|{type}`). Surfaces TTL, ResourceRecords (with
|
|
@@ -27828,6 +28145,19 @@ var Route53Provider = class {
|
|
|
27828
28145
|
return out;
|
|
27829
28146
|
});
|
|
27830
28147
|
}
|
|
28148
|
+
const idTail = physicalId.replace(/^\/hostedzone\//, "");
|
|
28149
|
+
try {
|
|
28150
|
+
const tagsResp = await this.getClient().send(
|
|
28151
|
+
new ListTagsForResourceCommand11({ ResourceType: "hostedzone", ResourceId: idTail })
|
|
28152
|
+
);
|
|
28153
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.ResourceTagSet?.Tags);
|
|
28154
|
+
if (tags.length > 0)
|
|
28155
|
+
result["HostedZoneTags"] = tags;
|
|
28156
|
+
} catch (err) {
|
|
28157
|
+
this.logger.debug(
|
|
28158
|
+
`Route53 ListTagsForResource(${idTail}) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
28159
|
+
);
|
|
28160
|
+
}
|
|
27831
28161
|
return result;
|
|
27832
28162
|
}
|
|
27833
28163
|
async readRecordSet(physicalId) {
|
|
@@ -28207,7 +28537,9 @@ var WAFv2WebACLProvider = class {
|
|
|
28207
28537
|
* and AssociationConfig — every key cdkd state declares as
|
|
28208
28538
|
* `handledProperties`. `Scope` is recovered from the ARN parse.
|
|
28209
28539
|
*
|
|
28210
|
-
* Tags are
|
|
28540
|
+
* Tags are surfaced via a follow-up `ListTagsForResource(ResourceARN)`
|
|
28541
|
+
* call. CDK's `aws:*` auto-tags are filtered out and the result key is
|
|
28542
|
+
* omitted when AWS reports no user tags. Returns `undefined`
|
|
28211
28543
|
* when the ARN can't be parsed or the WebACL is gone
|
|
28212
28544
|
* (`WAFNonexistentItemException`).
|
|
28213
28545
|
*/
|
|
@@ -28264,6 +28596,18 @@ var WAFv2WebACLProvider = class {
|
|
|
28264
28596
|
if (webACL.AssociationConfig) {
|
|
28265
28597
|
result["AssociationConfig"] = webACL.AssociationConfig;
|
|
28266
28598
|
}
|
|
28599
|
+
try {
|
|
28600
|
+
const tagsResp = await this.getClient().send(
|
|
28601
|
+
new ListTagsForResourceCommand12({ ResourceARN: physicalId })
|
|
28602
|
+
);
|
|
28603
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.TagInfoForResource?.TagList);
|
|
28604
|
+
if (tags.length > 0)
|
|
28605
|
+
result["Tags"] = tags;
|
|
28606
|
+
} catch (err) {
|
|
28607
|
+
this.logger.debug(
|
|
28608
|
+
`WAFv2 ListTagsForResource(${physicalId}) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
28609
|
+
);
|
|
28610
|
+
}
|
|
28267
28611
|
return result;
|
|
28268
28612
|
}
|
|
28269
28613
|
/**
|
|
@@ -28671,9 +29015,10 @@ var CognitoUserPoolProvider = class {
|
|
|
28671
29015
|
* `UserPoolClient`, `UserPoolGroup`, and other Cognito sub-resources go
|
|
28672
29016
|
* through the CC API fallback (which has its own `readCurrentState`).
|
|
28673
29017
|
*
|
|
28674
|
-
* `UserPoolTags` is
|
|
28675
|
-
*
|
|
28676
|
-
*
|
|
29018
|
+
* `UserPoolTags` is surfaced from the same `DescribeUserPool` response —
|
|
29019
|
+
* Cognito's CFn property is a tag-name → value map (NOT an array of
|
|
29020
|
+
* `{Key, Value}`), so we keep the map shape and just filter out CDK's
|
|
29021
|
+
* `aws:*` auto-tags. The result key is omitted when no user tags remain.
|
|
28677
29022
|
*
|
|
28678
29023
|
* Returns `undefined` when the pool is gone (`ResourceNotFoundException`).
|
|
28679
29024
|
*/
|
|
@@ -28750,6 +29095,15 @@ var CognitoUserPoolProvider = class {
|
|
|
28750
29095
|
if (pool.SmsVerificationMessage !== void 0) {
|
|
28751
29096
|
result["SmsVerificationMessage"] = pool.SmsVerificationMessage;
|
|
28752
29097
|
}
|
|
29098
|
+
if (pool.UserPoolTags) {
|
|
29099
|
+
const userTags = {};
|
|
29100
|
+
for (const [k, v] of Object.entries(pool.UserPoolTags)) {
|
|
29101
|
+
if (!k.startsWith("aws:"))
|
|
29102
|
+
userTags[k] = v;
|
|
29103
|
+
}
|
|
29104
|
+
if (Object.keys(userTags).length > 0)
|
|
29105
|
+
result["UserPoolTags"] = userTags;
|
|
29106
|
+
}
|
|
28753
29107
|
return result;
|
|
28754
29108
|
}
|
|
28755
29109
|
/**
|
|
@@ -29254,8 +29608,11 @@ var ElastiCacheProvider = class {
|
|
|
29254
29608
|
* surfacing `CacheSubnetGroupName`, `CacheSubnetGroupDescription`,
|
|
29255
29609
|
* and `SubnetIds` derived from `Subnets[].SubnetIdentifier`.
|
|
29256
29610
|
*
|
|
29257
|
-
* Tags are
|
|
29258
|
-
*
|
|
29611
|
+
* Tags are surfaced via a follow-up `ListTagsForResource(ResourceName=arn)`
|
|
29612
|
+
* for both types (ARN derived from `cluster.ARN` / `group.ARN`). CDK's
|
|
29613
|
+
* `aws:*` auto-tags are filtered out and the result key is omitted when
|
|
29614
|
+
* AWS reports no user tags. Returns `undefined` when the resource is gone
|
|
29615
|
+
* (`*NotFoundFault`).
|
|
29259
29616
|
*/
|
|
29260
29617
|
async readCurrentState(physicalId, _logicalId, resourceType) {
|
|
29261
29618
|
switch (resourceType) {
|
|
@@ -29335,6 +29692,8 @@ var ElastiCacheProvider = class {
|
|
|
29335
29692
|
if (ids.length > 0)
|
|
29336
29693
|
result["VpcSecurityGroupIds"] = ids;
|
|
29337
29694
|
}
|
|
29695
|
+
if (cluster.ARN)
|
|
29696
|
+
await this.attachTags(result, cluster.ARN);
|
|
29338
29697
|
return result;
|
|
29339
29698
|
}
|
|
29340
29699
|
async readSubnetGroup(physicalId) {
|
|
@@ -29363,8 +29722,25 @@ var ElastiCacheProvider = class {
|
|
|
29363
29722
|
if (ids.length > 0)
|
|
29364
29723
|
result["SubnetIds"] = ids;
|
|
29365
29724
|
}
|
|
29725
|
+
if (group.ARN)
|
|
29726
|
+
await this.attachTags(result, group.ARN);
|
|
29366
29727
|
return result;
|
|
29367
29728
|
}
|
|
29729
|
+
/** Best-effort tag fetch — failures omit the key without breaking the read. */
|
|
29730
|
+
async attachTags(result, arn) {
|
|
29731
|
+
try {
|
|
29732
|
+
const tagsResp = await this.getClient().send(
|
|
29733
|
+
new ListTagsForResourceCommand14({ ResourceName: arn })
|
|
29734
|
+
);
|
|
29735
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.TagList);
|
|
29736
|
+
if (tags.length > 0)
|
|
29737
|
+
result["Tags"] = tags;
|
|
29738
|
+
} catch (err) {
|
|
29739
|
+
this.logger.debug(
|
|
29740
|
+
`ElastiCache ListTagsForResource(${arn}) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
29741
|
+
);
|
|
29742
|
+
}
|
|
29743
|
+
}
|
|
29368
29744
|
/**
|
|
29369
29745
|
* Adopt an existing ElastiCache resource into cdkd state.
|
|
29370
29746
|
*
|
|
@@ -29850,8 +30226,12 @@ var ServiceDiscoveryProvider = class {
|
|
|
29850
30226
|
* - `Service` → `GetService` (Name, NamespaceId, Description, Type,
|
|
29851
30227
|
* DnsConfig, HealthCheckConfig, HealthCheckCustomConfig).
|
|
29852
30228
|
*
|
|
29853
|
-
* Tags are
|
|
29854
|
-
*
|
|
30229
|
+
* Tags are surfaced via a follow-up `ListTagsForResource(ResourceARN)`
|
|
30230
|
+
* call (using the resource ARN from `GetNamespace.Arn` or
|
|
30231
|
+
* `GetService.Arn`). CDK's `aws:*` auto-tags are filtered out and the
|
|
30232
|
+
* result key is omitted when AWS reports no user tags. Returns
|
|
30233
|
+
* `undefined` when the resource is gone (`NamespaceNotFound` /
|
|
30234
|
+
* `ServiceNotFound`).
|
|
29855
30235
|
*/
|
|
29856
30236
|
async readCurrentState(physicalId, _logicalId, resourceType) {
|
|
29857
30237
|
switch (resourceType) {
|
|
@@ -29881,6 +30261,8 @@ var ServiceDiscoveryProvider = class {
|
|
|
29881
30261
|
if (ns.Description !== void 0 && ns.Description !== "") {
|
|
29882
30262
|
result["Description"] = ns.Description;
|
|
29883
30263
|
}
|
|
30264
|
+
if (ns.Arn)
|
|
30265
|
+
await this.attachTags(result, ns.Arn);
|
|
29884
30266
|
return result;
|
|
29885
30267
|
}
|
|
29886
30268
|
async readService(physicalId) {
|
|
@@ -29914,8 +30296,25 @@ var ServiceDiscoveryProvider = class {
|
|
|
29914
30296
|
if (svc.HealthCheckCustomConfig) {
|
|
29915
30297
|
result["HealthCheckCustomConfig"] = svc.HealthCheckCustomConfig;
|
|
29916
30298
|
}
|
|
30299
|
+
if (svc.Arn)
|
|
30300
|
+
await this.attachTags(result, svc.Arn);
|
|
29917
30301
|
return result;
|
|
29918
30302
|
}
|
|
30303
|
+
/** Best-effort tag fetch via `ListTagsForResource(ResourceARN)`. */
|
|
30304
|
+
async attachTags(result, arn) {
|
|
30305
|
+
try {
|
|
30306
|
+
const tagsResp = await this.getClient().send(
|
|
30307
|
+
new ListTagsForResourceCommand15({ ResourceARN: arn })
|
|
30308
|
+
);
|
|
30309
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.Tags);
|
|
30310
|
+
if (tags.length > 0)
|
|
30311
|
+
result["Tags"] = tags;
|
|
30312
|
+
} catch (err) {
|
|
30313
|
+
this.logger.debug(
|
|
30314
|
+
`ServiceDiscovery ListTagsForResource(${arn}) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
30315
|
+
);
|
|
30316
|
+
}
|
|
30317
|
+
}
|
|
29919
30318
|
async import(input) {
|
|
29920
30319
|
switch (input.resourceType) {
|
|
29921
30320
|
case "AWS::ServiceDiscovery::PrivateDnsNamespace":
|
|
@@ -30562,7 +30961,9 @@ var AppSyncProvider = class {
|
|
|
30562
30961
|
*
|
|
30563
30962
|
* Dispatches per resource type:
|
|
30564
30963
|
* - `GraphQLApi` → `GetGraphqlApi` (Name, AuthenticationType, XrayEnabled,
|
|
30565
|
-
* LogConfig). Tags
|
|
30964
|
+
* LogConfig, Tags). Tags come from the same response (`tags` map);
|
|
30965
|
+
* CDK's `aws:*` auto-tags are filtered out and the result key is
|
|
30966
|
+
* omitted when no user tags remain.
|
|
30566
30967
|
* - `DataSource` → `GetDataSource` (Name, Type, Description,
|
|
30567
30968
|
* ServiceRoleArn, DynamoDBConfig, LambdaConfig, HttpConfig). The
|
|
30568
30969
|
* `ApiId` cdkd holds is recovered from the `apiId|name` physicalId.
|
|
@@ -30630,6 +31031,9 @@ var AppSyncProvider = class {
|
|
|
30630
31031
|
if (Object.keys(log).length > 0)
|
|
30631
31032
|
result["LogConfig"] = log;
|
|
30632
31033
|
}
|
|
31034
|
+
const tags = normalizeAwsTagsToCfn(api.tags);
|
|
31035
|
+
if (tags.length > 0)
|
|
31036
|
+
result["Tags"] = tags;
|
|
30633
31037
|
return result;
|
|
30634
31038
|
}
|
|
30635
31039
|
async readDataSource(physicalId) {
|
|
@@ -31875,9 +32279,11 @@ var KMSProvider = class {
|
|
|
31875
32279
|
* Surfaces `AliasName`, `TargetKeyId`. `ListAliases` is paginated
|
|
31876
32280
|
* since there's no direct "describe one alias" API.
|
|
31877
32281
|
*
|
|
31878
|
-
* `Tags` is
|
|
31879
|
-
*
|
|
31880
|
-
*
|
|
32282
|
+
* `Tags` is surfaced for `AWS::KMS::Key` via a follow-up
|
|
32283
|
+
* `ListResourceTags(KeyId)` call (KMS uses `[{TagKey, TagValue}]` shape).
|
|
32284
|
+
* CDK's `aws:*` auto-tags are filtered out; the result key is omitted
|
|
32285
|
+
* entirely when AWS reports no user tags. `AWS::KMS::Alias` does not
|
|
32286
|
+
* support tags. `BypassPolicyLockoutSafetyCheck` and `PendingWindowInDays`
|
|
31881
32287
|
* are not part of the persisted AWS state visible via `DescribeKey`.
|
|
31882
32288
|
*
|
|
31883
32289
|
* Returns `undefined` when the resource is gone (`NotFoundException`).
|
|
@@ -31920,6 +32326,19 @@ var KMSProvider = class {
|
|
|
31920
32326
|
result["MultiRegion"] = md.MultiRegion;
|
|
31921
32327
|
if (md.Origin !== void 0)
|
|
31922
32328
|
result["Origin"] = md.Origin;
|
|
32329
|
+
if (md.KeyId) {
|
|
32330
|
+
try {
|
|
32331
|
+
const tagsResp = await this.getClient().send(
|
|
32332
|
+
new ListResourceTagsCommand({ KeyId: md.KeyId })
|
|
32333
|
+
);
|
|
32334
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.Tags);
|
|
32335
|
+
if (tags.length > 0)
|
|
32336
|
+
result["Tags"] = tags;
|
|
32337
|
+
} catch (err) {
|
|
32338
|
+
if (err instanceof NotFoundException5)
|
|
32339
|
+
return void 0;
|
|
32340
|
+
}
|
|
32341
|
+
}
|
|
31923
32342
|
return result;
|
|
31924
32343
|
}
|
|
31925
32344
|
async readCurrentStateAlias(physicalId) {
|
|
@@ -32303,7 +32722,8 @@ var KinesisStreamProvider = class {
|
|
|
32303
32722
|
*
|
|
32304
32723
|
* Issues `DescribeStream` and surfaces the keys cdkd's `create()`
|
|
32305
32724
|
* accepts: `Name`, `StreamModeDetails`, `ShardCount`, `RetentionPeriodHours`,
|
|
32306
|
-
* and `StreamEncryption`. Tags are
|
|
32725
|
+
* and `StreamEncryption`. Tags are surfaced via a follow-up
|
|
32726
|
+
* `ListTagsForStream` with `aws:*` filtered out.
|
|
32307
32727
|
*
|
|
32308
32728
|
* `ShardCount` is reported as the count of `Shards[]` in the stream
|
|
32309
32729
|
* description (only present for PROVISIONED-mode streams; ON_DEMAND
|
|
@@ -32352,6 +32772,20 @@ var KinesisStreamProvider = class {
|
|
|
32352
32772
|
encryption["KeyId"] = stream.KeyId;
|
|
32353
32773
|
result["StreamEncryption"] = encryption;
|
|
32354
32774
|
}
|
|
32775
|
+
try {
|
|
32776
|
+
const tagsResp = await this.getClient().send(
|
|
32777
|
+
new ListTagsForStreamCommand({ StreamName: physicalId })
|
|
32778
|
+
);
|
|
32779
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.Tags);
|
|
32780
|
+
if (tags.length > 0)
|
|
32781
|
+
result["Tags"] = tags;
|
|
32782
|
+
} catch (err) {
|
|
32783
|
+
if (err instanceof ResourceNotFoundException13)
|
|
32784
|
+
return void 0;
|
|
32785
|
+
this.logger.debug(
|
|
32786
|
+
`Kinesis ListTagsForStream(${physicalId}) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
32787
|
+
);
|
|
32788
|
+
}
|
|
32355
32789
|
return result;
|
|
32356
32790
|
}
|
|
32357
32791
|
async import(input) {
|
|
@@ -32864,7 +33298,12 @@ var EFSProvider = class {
|
|
|
32864
33298
|
* - `MountTarget` → `DescribeMountTargets` (FileSystemId, SubnetId).
|
|
32865
33299
|
* SecurityGroups requires a separate call and is omitted for v1.
|
|
32866
33300
|
*
|
|
32867
|
-
*
|
|
33301
|
+
* `FileSystemTags` (the CFn property name on `AWS::EFS::FileSystem`) is
|
|
33302
|
+
* surfaced from the same `DescribeFileSystems` response — `aws:*`
|
|
33303
|
+
* auto-tags filtered, key omitted when empty. `AccessPoint` and
|
|
33304
|
+
* `MountTarget` are not surfaced for tags here (`AccessPointTags` would
|
|
33305
|
+
* mirror this approach but the test scope below covers `FileSystem`
|
|
33306
|
+
* only; further coverage can land in a follow-up).
|
|
32868
33307
|
* Returns `undefined` when the resource is gone (`*NotFound`).
|
|
32869
33308
|
*/
|
|
32870
33309
|
async readCurrentState(physicalId, _logicalId, resourceType) {
|
|
@@ -32941,6 +33380,9 @@ var EFSProvider = class {
|
|
|
32941
33380
|
if (err instanceof FileSystemNotFound)
|
|
32942
33381
|
return void 0;
|
|
32943
33382
|
}
|
|
33383
|
+
const tags = normalizeAwsTagsToCfn(fs.Tags);
|
|
33384
|
+
if (tags.length > 0)
|
|
33385
|
+
result["FileSystemTags"] = tags;
|
|
32944
33386
|
return result;
|
|
32945
33387
|
}
|
|
32946
33388
|
async readAccessPoint(physicalId) {
|
|
@@ -33492,8 +33934,10 @@ var FirehoseProvider = class {
|
|
|
33492
33934
|
* fields. Drift on destination contents is best chased manually via
|
|
33493
33935
|
* `aws firehose describe-delivery-stream` for now.
|
|
33494
33936
|
*
|
|
33495
|
-
* Tags
|
|
33496
|
-
*
|
|
33937
|
+
* Tags are surfaced via a follow-up `ListTagsForDeliveryStream` call
|
|
33938
|
+
* with `aws:*` filtered out and the result key omitted when empty.
|
|
33939
|
+
* `DeliveryStreamEncryptionConfigurationInput` is still skipped (shape
|
|
33940
|
+
* decision deferred).
|
|
33497
33941
|
*
|
|
33498
33942
|
* Returns `undefined` when the stream is gone (`ResourceNotFoundException`).
|
|
33499
33943
|
*/
|
|
@@ -33529,6 +33973,20 @@ var FirehoseProvider = class {
|
|
|
33529
33973
|
result["KinesisStreamSourceConfiguration"] = srcOut;
|
|
33530
33974
|
}
|
|
33531
33975
|
}
|
|
33976
|
+
try {
|
|
33977
|
+
const tagsResp = await this.getClient().send(
|
|
33978
|
+
new ListTagsForDeliveryStreamCommand({ DeliveryStreamName: physicalId })
|
|
33979
|
+
);
|
|
33980
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.Tags);
|
|
33981
|
+
if (tags.length > 0)
|
|
33982
|
+
result["Tags"] = tags;
|
|
33983
|
+
} catch (err) {
|
|
33984
|
+
if (err instanceof ResourceNotFoundException14)
|
|
33985
|
+
return void 0;
|
|
33986
|
+
this.logger.debug(
|
|
33987
|
+
`Firehose ListTagsForDeliveryStream(${physicalId}) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
33988
|
+
);
|
|
33989
|
+
}
|
|
33532
33990
|
return result;
|
|
33533
33991
|
}
|
|
33534
33992
|
async import(input) {
|
|
@@ -33864,8 +34322,13 @@ var CloudTrailProvider = class {
|
|
|
33864
34322
|
* derived field; the cdkd state property is `SnsTopicName` so we
|
|
33865
34323
|
* surface `SnsTopicName` directly from `GetTrail.SnsTopicName`.
|
|
33866
34324
|
*
|
|
33867
|
-
* Tags
|
|
33868
|
-
*
|
|
34325
|
+
* Tags are surfaced via a follow-up `ListTags(ResourceIdList=[arn])` call
|
|
34326
|
+
* (using the trail ARN from the same `GetTrail` response). CDK's `aws:*`
|
|
34327
|
+
* auto-tags are filtered out and the result key is omitted when AWS
|
|
34328
|
+
* reports no user tags.
|
|
34329
|
+
*
|
|
34330
|
+
* `InsightSelectors` is skipped for v1 (separate call + shape mapping
|
|
34331
|
+
* still TBD).
|
|
33869
34332
|
*
|
|
33870
34333
|
* Returns `undefined` when the trail is gone (`TrailNotFoundException`).
|
|
33871
34334
|
*/
|
|
@@ -33927,6 +34390,20 @@ var CloudTrailProvider = class {
|
|
|
33927
34390
|
}
|
|
33928
34391
|
} catch {
|
|
33929
34392
|
}
|
|
34393
|
+
if (trail.TrailARN) {
|
|
34394
|
+
try {
|
|
34395
|
+
const tagsResp = await this.getClient().send(
|
|
34396
|
+
new ListTagsCommand3({ ResourceIdList: [trail.TrailARN] })
|
|
34397
|
+
);
|
|
34398
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.ResourceTagList?.[0]?.TagsList);
|
|
34399
|
+
if (tags.length > 0)
|
|
34400
|
+
result["Tags"] = tags;
|
|
34401
|
+
} catch (err) {
|
|
34402
|
+
this.logger.debug(
|
|
34403
|
+
`CloudTrail ListTags(${trail.TrailARN}) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
34404
|
+
);
|
|
34405
|
+
}
|
|
34406
|
+
}
|
|
33930
34407
|
return result;
|
|
33931
34408
|
}
|
|
33932
34409
|
async import(input) {
|
|
@@ -34259,8 +34736,12 @@ var CodeBuildProvider = class {
|
|
|
34259
34736
|
* is left to a follow-up — surfacing them with a partial shape would
|
|
34260
34737
|
* fire false drift on every project that uses them.
|
|
34261
34738
|
*
|
|
34262
|
-
* Tags are
|
|
34263
|
-
*
|
|
34739
|
+
* Tags are surfaced from the same `BatchGetProjects` response (CodeBuild
|
|
34740
|
+
* uses lower-case `key`/`value` shape; `normalizeAwsTagsToCfn` re-shapes
|
|
34741
|
+
* to CFn `[{Key, Value}]`). CDK's `aws:*` auto-tags are filtered out
|
|
34742
|
+
* and the result key is omitted when AWS reports no user tags. Returns
|
|
34743
|
+
* `undefined` when the project is gone (`projects` array empty /
|
|
34744
|
+
* `projectsNotFound` set).
|
|
34264
34745
|
*/
|
|
34265
34746
|
async readCurrentState(physicalId, _logicalId, _resourceType) {
|
|
34266
34747
|
let project;
|
|
@@ -34379,6 +34860,9 @@ var CodeBuildProvider = class {
|
|
|
34379
34860
|
if (Object.keys(env).length > 0)
|
|
34380
34861
|
result["Environment"] = env;
|
|
34381
34862
|
}
|
|
34863
|
+
const tags = normalizeAwsTagsToCfn(project.tags);
|
|
34864
|
+
if (tags.length > 0)
|
|
34865
|
+
result["Tags"] = tags;
|
|
34382
34866
|
return result;
|
|
34383
34867
|
}
|
|
34384
34868
|
async import(input) {
|
|
@@ -35907,11 +36391,14 @@ var ECRProvider = class {
|
|
|
35907
36391
|
* round-trip; cdkd state holds the policy as either a string or an
|
|
35908
36392
|
* object (depending on user input), and the comparator round-trip
|
|
35909
36393
|
* is not yet handled here.
|
|
35910
|
-
* - `Tags`: requires `ListTagsForResource`; auto-injected
|
|
35911
|
-
* `aws:cdk:path` tag-shape question is out of scope.
|
|
35912
36394
|
* - `EmptyOnDelete` / `ImageTagMutabilityExclusionFilters`: not part
|
|
35913
36395
|
* of the persisted AWS state visible via standard Describe.
|
|
35914
36396
|
*
|
|
36397
|
+
* `Tags` is surfaced via a follow-up `ListTagsForResource(arn)` call
|
|
36398
|
+
* (using the repository ARN that `DescribeRepositories` returns). CDK's
|
|
36399
|
+
* `aws:*` auto-tags are filtered out; the result key is omitted entirely
|
|
36400
|
+
* when AWS reports no user tags.
|
|
36401
|
+
*
|
|
35915
36402
|
* Returns `undefined` when the repository is gone (`RepositoryNotFoundException`).
|
|
35916
36403
|
*/
|
|
35917
36404
|
async readCurrentState(physicalId, _logicalId, _resourceType) {
|
|
@@ -35964,6 +36451,19 @@ var ECRProvider = class {
|
|
|
35964
36451
|
throw err;
|
|
35965
36452
|
}
|
|
35966
36453
|
}
|
|
36454
|
+
if (r.repositoryArn) {
|
|
36455
|
+
try {
|
|
36456
|
+
const tagsResp = await this.getClient().send(
|
|
36457
|
+
new ListTagsForResourceCommand18({ resourceArn: r.repositoryArn })
|
|
36458
|
+
);
|
|
36459
|
+
const tags = normalizeAwsTagsToCfn(tagsResp.tags);
|
|
36460
|
+
if (tags.length > 0)
|
|
36461
|
+
result["Tags"] = tags;
|
|
36462
|
+
} catch (err) {
|
|
36463
|
+
if (!(err instanceof RepositoryNotFoundException))
|
|
36464
|
+
throw err;
|
|
36465
|
+
}
|
|
36466
|
+
}
|
|
35967
36467
|
return result;
|
|
35968
36468
|
}
|
|
35969
36469
|
/**
|
|
@@ -38086,19 +38586,34 @@ import { Command as Command6, Option as Option3 } from "commander";
|
|
|
38086
38586
|
init_aws_clients();
|
|
38087
38587
|
|
|
38088
38588
|
// src/analyzer/drift-calculator.ts
|
|
38089
|
-
function calculateResourceDrift(stateProperties, awsProperties) {
|
|
38589
|
+
function calculateResourceDrift(stateProperties, awsProperties, options) {
|
|
38090
38590
|
const drifts = [];
|
|
38591
|
+
const ignore = options?.ignorePaths ?? [];
|
|
38091
38592
|
for (const key of Object.keys(stateProperties)) {
|
|
38092
|
-
|
|
38593
|
+
if (isIgnoredPath(key, ignore))
|
|
38594
|
+
continue;
|
|
38595
|
+
diffAt(key, stateProperties[key], awsProperties[key], drifts, ignore);
|
|
38093
38596
|
}
|
|
38094
38597
|
return drifts;
|
|
38095
38598
|
}
|
|
38096
|
-
function
|
|
38599
|
+
function isIgnoredPath(path, ignorePaths) {
|
|
38600
|
+
for (const entry of ignorePaths) {
|
|
38601
|
+
if (path === entry)
|
|
38602
|
+
return true;
|
|
38603
|
+
if (path.startsWith(`${entry}.`))
|
|
38604
|
+
return true;
|
|
38605
|
+
}
|
|
38606
|
+
return false;
|
|
38607
|
+
}
|
|
38608
|
+
function diffAt(path, stateValue, awsValue, out, ignorePaths) {
|
|
38097
38609
|
if (deepEqual(stateValue, awsValue))
|
|
38098
38610
|
return;
|
|
38099
38611
|
if (isPlainObject(stateValue) && isPlainObject(awsValue) && !Array.isArray(stateValue) && !Array.isArray(awsValue)) {
|
|
38100
38612
|
for (const key of Object.keys(stateValue)) {
|
|
38101
|
-
|
|
38613
|
+
const childPath = `${path}.${key}`;
|
|
38614
|
+
if (isIgnoredPath(childPath, ignorePaths))
|
|
38615
|
+
continue;
|
|
38616
|
+
diffAt(childPath, stateValue[key], awsValue[key], out, ignorePaths);
|
|
38102
38617
|
}
|
|
38103
38618
|
return;
|
|
38104
38619
|
}
|
|
@@ -38276,9 +38791,6 @@ async function driftCommand(stacks, options) {
|
|
|
38276
38791
|
logger.setLevel("debug");
|
|
38277
38792
|
}
|
|
38278
38793
|
warnIfDeprecatedRegion(options);
|
|
38279
|
-
if (!options.all && stacks.length === 0) {
|
|
38280
|
-
throw new Error("Stack name is required. Usage: cdkd drift <stack> [<stack>...] | --all");
|
|
38281
|
-
}
|
|
38282
38794
|
if (options.accept && options.revert) {
|
|
38283
38795
|
throw new Error(
|
|
38284
38796
|
"--accept and --revert are mutually exclusive. Use --accept to update cdkd state from AWS, or --revert to push cdkd state values back into AWS."
|
|
@@ -38359,6 +38871,21 @@ function resolveTargetRefs(stacks, stateRefs, options) {
|
|
|
38359
38871
|
}
|
|
38360
38872
|
return stateRefs;
|
|
38361
38873
|
}
|
|
38874
|
+
if (stacks.length === 0) {
|
|
38875
|
+
const candidates = options.stackRegion ? stateRefs.filter((r) => r.region === options.stackRegion) : stateRefs;
|
|
38876
|
+
if (candidates.length === 0) {
|
|
38877
|
+
throw new Error(
|
|
38878
|
+
"No stacks found in state bucket. Run `cdkd deploy` first, or pass --all explicitly."
|
|
38879
|
+
);
|
|
38880
|
+
}
|
|
38881
|
+
if (candidates.length === 1) {
|
|
38882
|
+
return [candidates[0]];
|
|
38883
|
+
}
|
|
38884
|
+
const listing = candidates.map((r) => `${r.stackName}${r.region ? ` (${r.region})` : ""}`).join(", ");
|
|
38885
|
+
throw new Error(
|
|
38886
|
+
`Multiple stacks found in state: ${listing}. Specify stack name(s) or use --all.`
|
|
38887
|
+
);
|
|
38888
|
+
}
|
|
38362
38889
|
const out = [];
|
|
38363
38890
|
for (const stackName of stacks) {
|
|
38364
38891
|
const matches = stateRefs.filter((r) => r.stackName === stackName);
|
|
@@ -38456,7 +38983,8 @@ async function runDriftForStack(stackName, region, stateBackend, providerRegistr
|
|
|
38456
38983
|
});
|
|
38457
38984
|
continue;
|
|
38458
38985
|
}
|
|
38459
|
-
const
|
|
38986
|
+
const ignorePaths = provider.getDriftUnknownPaths ? provider.getDriftUnknownPaths(resource.resourceType) : [];
|
|
38987
|
+
const changes = calculateResourceDrift(resource.properties ?? {}, aws, { ignorePaths });
|
|
38460
38988
|
if (changes.length === 0) {
|
|
38461
38989
|
outcomes.push({ kind: "clean", logicalId, resourceType: resource.resourceType });
|
|
38462
38990
|
} else {
|
|
@@ -42003,7 +42531,7 @@ function reorderArgs(argv) {
|
|
|
42003
42531
|
}
|
|
42004
42532
|
async function main() {
|
|
42005
42533
|
const program = new Command14();
|
|
42006
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.
|
|
42534
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.46.1");
|
|
42007
42535
|
program.addCommand(createBootstrapCommand());
|
|
42008
42536
|
program.addCommand(createSynthCommand());
|
|
42009
42537
|
program.addCommand(createListCommand());
|