@go-to-k/cdkd 0.14.0 → 0.15.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/README.md +9 -0
- package/dist/cli.js +1004 -9
- package/dist/cli.js.map +4 -4
- package/dist/go-to-k-cdkd-0.15.0.tgz +0 -0
- package/dist/index.js +80 -0
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
- package/dist/go-to-k-cdkd-0.14.0.tgz +0 -0
package/dist/cli.js
CHANGED
|
@@ -447,7 +447,7 @@ var init_aws_clients = __esm({
|
|
|
447
447
|
});
|
|
448
448
|
|
|
449
449
|
// src/cli/index.ts
|
|
450
|
-
import { Command as
|
|
450
|
+
import { Command as Command12 } from "commander";
|
|
451
451
|
|
|
452
452
|
// src/cli/commands/bootstrap.ts
|
|
453
453
|
import { Command, Option as Option2 } from "commander";
|
|
@@ -1030,9 +1030,9 @@ async function resolveStateBucketWithDefaultAndSource(cliBucket, region) {
|
|
|
1030
1030
|
}
|
|
1031
1031
|
}
|
|
1032
1032
|
async function bucketExists(client, bucketName) {
|
|
1033
|
-
const { HeadBucketCommand:
|
|
1033
|
+
const { HeadBucketCommand: HeadBucketCommand5 } = await import("@aws-sdk/client-s3");
|
|
1034
1034
|
try {
|
|
1035
|
-
await client.send(new
|
|
1035
|
+
await client.send(new HeadBucketCommand5({ Bucket: bucketName }));
|
|
1036
1036
|
return true;
|
|
1037
1037
|
} catch (error) {
|
|
1038
1038
|
const err = error;
|
|
@@ -7674,6 +7674,8 @@ import {
|
|
|
7674
7674
|
UntagRoleCommand,
|
|
7675
7675
|
PutRolePermissionsBoundaryCommand,
|
|
7676
7676
|
DeleteRolePermissionsBoundaryCommand,
|
|
7677
|
+
ListRolesCommand,
|
|
7678
|
+
ListRoleTagsCommand,
|
|
7677
7679
|
NoSuchEntityException
|
|
7678
7680
|
} from "@aws-sdk/client-iam";
|
|
7679
7681
|
init_aws_clients();
|
|
@@ -7782,6 +7784,32 @@ function applyDefaultNameForFallback(logicalId, resourceType, properties) {
|
|
|
7782
7784
|
};
|
|
7783
7785
|
}
|
|
7784
7786
|
|
|
7787
|
+
// src/provisioning/import-helpers.ts
|
|
7788
|
+
function readNameProperty(input, propertyName) {
|
|
7789
|
+
const value = input.properties?.[propertyName];
|
|
7790
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
7791
|
+
}
|
|
7792
|
+
function resolveExplicitPhysicalId(input, nameProperty) {
|
|
7793
|
+
if (input.knownPhysicalId)
|
|
7794
|
+
return input.knownPhysicalId;
|
|
7795
|
+
if (nameProperty) {
|
|
7796
|
+
const name = readNameProperty(input, nameProperty);
|
|
7797
|
+
if (name)
|
|
7798
|
+
return name;
|
|
7799
|
+
}
|
|
7800
|
+
return void 0;
|
|
7801
|
+
}
|
|
7802
|
+
var CDK_PATH_TAG = "aws:cdk:path";
|
|
7803
|
+
function matchesCdkPath(tags, cdkPath) {
|
|
7804
|
+
if (!tags || !cdkPath)
|
|
7805
|
+
return false;
|
|
7806
|
+
for (const t of tags) {
|
|
7807
|
+
if (t.Key === CDK_PATH_TAG && t.Value === cdkPath)
|
|
7808
|
+
return true;
|
|
7809
|
+
}
|
|
7810
|
+
return false;
|
|
7811
|
+
}
|
|
7812
|
+
|
|
7785
7813
|
// src/provisioning/providers/iam-role-provider.ts
|
|
7786
7814
|
var IAMRoleProvider = class {
|
|
7787
7815
|
iamClient;
|
|
@@ -8288,6 +8316,58 @@ var IAMRoleProvider = class {
|
|
|
8288
8316
|
this.logger.debug(`Added/updated ${tagsToAdd.length} tags on role ${roleName}`);
|
|
8289
8317
|
}
|
|
8290
8318
|
}
|
|
8319
|
+
/**
|
|
8320
|
+
* Adopt an existing IAM role into cdkd state.
|
|
8321
|
+
*
|
|
8322
|
+
* Lookup order:
|
|
8323
|
+
* 1. `--resource` override or `Properties.RoleName` → use directly,
|
|
8324
|
+
* verify via `GetRole`.
|
|
8325
|
+
* 2. `ListRoles` + `ListRoleTags`, match `aws:cdk:path` tag.
|
|
8326
|
+
*
|
|
8327
|
+
* `ListRoles` is paginated and IAM is global (no region scoping), so this
|
|
8328
|
+
* walks every role in the account once. Acceptable for the cardinalities
|
|
8329
|
+
* we expect (typically <100 roles per account); larger accounts may want
|
|
8330
|
+
* to provide `--resource` overrides instead.
|
|
8331
|
+
*/
|
|
8332
|
+
async import(input) {
|
|
8333
|
+
const explicit = resolveExplicitPhysicalId(input, "RoleName");
|
|
8334
|
+
if (explicit) {
|
|
8335
|
+
try {
|
|
8336
|
+
await this.iamClient.send(new GetRoleCommand({ RoleName: explicit }));
|
|
8337
|
+
return { physicalId: explicit, attributes: {} };
|
|
8338
|
+
} catch (err) {
|
|
8339
|
+
if (err instanceof NoSuchEntityException)
|
|
8340
|
+
return null;
|
|
8341
|
+
throw err;
|
|
8342
|
+
}
|
|
8343
|
+
}
|
|
8344
|
+
if (!input.cdkPath)
|
|
8345
|
+
return null;
|
|
8346
|
+
let marker;
|
|
8347
|
+
do {
|
|
8348
|
+
const list = await this.iamClient.send(
|
|
8349
|
+
new ListRolesCommand({ ...marker && { Marker: marker } })
|
|
8350
|
+
);
|
|
8351
|
+
for (const role of list.Roles ?? []) {
|
|
8352
|
+
if (!role.RoleName)
|
|
8353
|
+
continue;
|
|
8354
|
+
try {
|
|
8355
|
+
const tags = await this.iamClient.send(
|
|
8356
|
+
new ListRoleTagsCommand({ RoleName: role.RoleName })
|
|
8357
|
+
);
|
|
8358
|
+
if (matchesCdkPath(tags.Tags, input.cdkPath)) {
|
|
8359
|
+
return { physicalId: role.RoleName, attributes: {} };
|
|
8360
|
+
}
|
|
8361
|
+
} catch (err) {
|
|
8362
|
+
if (err instanceof NoSuchEntityException)
|
|
8363
|
+
continue;
|
|
8364
|
+
throw err;
|
|
8365
|
+
}
|
|
8366
|
+
}
|
|
8367
|
+
marker = list.IsTruncated ? list.Marker : void 0;
|
|
8368
|
+
} while (marker);
|
|
8369
|
+
return null;
|
|
8370
|
+
}
|
|
8291
8371
|
};
|
|
8292
8372
|
|
|
8293
8373
|
// src/provisioning/providers/iam-policy-provider.ts
|
|
@@ -9868,6 +9948,8 @@ var IAMUserGroupProvider = class {
|
|
|
9868
9948
|
import {
|
|
9869
9949
|
CreateBucketCommand as CreateBucketCommand2,
|
|
9870
9950
|
DeleteBucketCommand,
|
|
9951
|
+
HeadBucketCommand as HeadBucketCommand3,
|
|
9952
|
+
ListBucketsCommand,
|
|
9871
9953
|
PutBucketVersioningCommand as PutBucketVersioningCommand2,
|
|
9872
9954
|
PutBucketTaggingCommand,
|
|
9873
9955
|
PutBucketOwnershipControlsCommand,
|
|
@@ -9885,6 +9967,7 @@ import {
|
|
|
9885
9967
|
PutBucketInventoryConfigurationCommand,
|
|
9886
9968
|
PutBucketReplicationCommand,
|
|
9887
9969
|
PutObjectLockConfigurationCommand,
|
|
9970
|
+
GetBucketTaggingCommand,
|
|
9888
9971
|
NoSuchBucket,
|
|
9889
9972
|
ListObjectVersionsCommand,
|
|
9890
9973
|
DeleteObjectsCommand
|
|
@@ -10723,6 +10806,53 @@ var S3BucketProvider = class {
|
|
|
10723
10806
|
);
|
|
10724
10807
|
}
|
|
10725
10808
|
}
|
|
10809
|
+
/**
|
|
10810
|
+
* Adopt an existing S3 bucket into cdkd state.
|
|
10811
|
+
*
|
|
10812
|
+
* Lookup order:
|
|
10813
|
+
* 1. `--resource <id>=<name>` override or `Properties.BucketName` → use directly,
|
|
10814
|
+
* verify with `HeadBucket`.
|
|
10815
|
+
* 2. `ListBuckets` + `GetBucketTagging`, match `aws:cdk:path` against the
|
|
10816
|
+
* CDK construct path.
|
|
10817
|
+
*
|
|
10818
|
+
* Returns `null` when nothing matches — caller treats this as
|
|
10819
|
+
* "not deployed yet" rather than a failure.
|
|
10820
|
+
*/
|
|
10821
|
+
async import(input) {
|
|
10822
|
+
const explicit = resolveExplicitPhysicalId(input, "BucketName");
|
|
10823
|
+
if (explicit) {
|
|
10824
|
+
try {
|
|
10825
|
+
await this.s3Client.send(new HeadBucketCommand3({ Bucket: explicit }));
|
|
10826
|
+
return { physicalId: explicit, attributes: {} };
|
|
10827
|
+
} catch (err) {
|
|
10828
|
+
const e = err;
|
|
10829
|
+
if (e.name === "NotFound" || e.name === "NoSuchBucket") {
|
|
10830
|
+
return null;
|
|
10831
|
+
}
|
|
10832
|
+
throw err;
|
|
10833
|
+
}
|
|
10834
|
+
}
|
|
10835
|
+
if (!input.cdkPath)
|
|
10836
|
+
return null;
|
|
10837
|
+
const list = await this.s3Client.send(new ListBucketsCommand({}));
|
|
10838
|
+
for (const b of list.Buckets ?? []) {
|
|
10839
|
+
if (!b.Name)
|
|
10840
|
+
continue;
|
|
10841
|
+
try {
|
|
10842
|
+
const tagging = await this.s3Client.send(new GetBucketTaggingCommand({ Bucket: b.Name }));
|
|
10843
|
+
if (matchesCdkPath(tagging.TagSet, input.cdkPath)) {
|
|
10844
|
+
return { physicalId: b.Name, attributes: {} };
|
|
10845
|
+
}
|
|
10846
|
+
} catch (err) {
|
|
10847
|
+
const e = err;
|
|
10848
|
+
if (e.name === "NoSuchTagSet" || e.name === "AccessDenied" || e.$metadata?.httpStatusCode === 301) {
|
|
10849
|
+
continue;
|
|
10850
|
+
}
|
|
10851
|
+
throw err;
|
|
10852
|
+
}
|
|
10853
|
+
}
|
|
10854
|
+
return null;
|
|
10855
|
+
}
|
|
10726
10856
|
/**
|
|
10727
10857
|
* Delete a bucket, emptying it first if not empty.
|
|
10728
10858
|
* Handles the race condition where objects (e.g., ALB logs) are written
|
|
@@ -10959,6 +11089,9 @@ import {
|
|
|
10959
11089
|
CreateQueueCommand,
|
|
10960
11090
|
DeleteQueueCommand,
|
|
10961
11091
|
GetQueueAttributesCommand,
|
|
11092
|
+
GetQueueUrlCommand,
|
|
11093
|
+
ListQueuesCommand,
|
|
11094
|
+
ListQueueTagsCommand,
|
|
10962
11095
|
SetQueueAttributesCommand,
|
|
10963
11096
|
QueueDoesNotExist
|
|
10964
11097
|
} from "@aws-sdk/client-sqs";
|
|
@@ -11167,6 +11300,68 @@ var SQSQueueProvider = class {
|
|
|
11167
11300
|
return `arn:aws:sqs:unknown:unknown:${queueName}`;
|
|
11168
11301
|
}
|
|
11169
11302
|
}
|
|
11303
|
+
/**
|
|
11304
|
+
* Adopt an existing SQS queue into cdkd state.
|
|
11305
|
+
*
|
|
11306
|
+
* SQS physical IDs are queue URLs (`https://sqs.us-east-1.amazonaws.com/<account>/<name>`).
|
|
11307
|
+
*
|
|
11308
|
+
* Lookup order:
|
|
11309
|
+
* 1. `--resource` override (URL) → verify via `GetQueueAttributes`.
|
|
11310
|
+
* 2. `Properties.QueueName` → `GetQueueUrl` for direct lookup.
|
|
11311
|
+
* 3. `aws:cdk:path` tag match via `ListQueues` + `ListQueueTags`.
|
|
11312
|
+
*/
|
|
11313
|
+
async import(input) {
|
|
11314
|
+
if (input.knownPhysicalId) {
|
|
11315
|
+
try {
|
|
11316
|
+
await this.sqsClient.send(
|
|
11317
|
+
new GetQueueAttributesCommand({
|
|
11318
|
+
QueueUrl: input.knownPhysicalId,
|
|
11319
|
+
AttributeNames: ["QueueArn"]
|
|
11320
|
+
})
|
|
11321
|
+
);
|
|
11322
|
+
return { physicalId: input.knownPhysicalId, attributes: {} };
|
|
11323
|
+
} catch (err) {
|
|
11324
|
+
if (err instanceof QueueDoesNotExist)
|
|
11325
|
+
return null;
|
|
11326
|
+
throw err;
|
|
11327
|
+
}
|
|
11328
|
+
}
|
|
11329
|
+
const explicitName = resolveExplicitPhysicalId(input, "QueueName");
|
|
11330
|
+
if (explicitName && !input.knownPhysicalId) {
|
|
11331
|
+
try {
|
|
11332
|
+
const resp = await this.sqsClient.send(new GetQueueUrlCommand({ QueueName: explicitName }));
|
|
11333
|
+
if (resp.QueueUrl)
|
|
11334
|
+
return { physicalId: resp.QueueUrl, attributes: {} };
|
|
11335
|
+
return null;
|
|
11336
|
+
} catch (err) {
|
|
11337
|
+
if (err instanceof QueueDoesNotExist)
|
|
11338
|
+
return null;
|
|
11339
|
+
throw err;
|
|
11340
|
+
}
|
|
11341
|
+
}
|
|
11342
|
+
if (!input.cdkPath)
|
|
11343
|
+
return null;
|
|
11344
|
+
let nextToken;
|
|
11345
|
+
do {
|
|
11346
|
+
const list = await this.sqsClient.send(
|
|
11347
|
+
new ListQueuesCommand({ ...nextToken && { NextToken: nextToken } })
|
|
11348
|
+
);
|
|
11349
|
+
for (const url of list.QueueUrls ?? []) {
|
|
11350
|
+
try {
|
|
11351
|
+
const tagsResp = await this.sqsClient.send(new ListQueueTagsCommand({ QueueUrl: url }));
|
|
11352
|
+
if (tagsResp.Tags?.[CDK_PATH_TAG] === input.cdkPath) {
|
|
11353
|
+
return { physicalId: url, attributes: {} };
|
|
11354
|
+
}
|
|
11355
|
+
} catch (err) {
|
|
11356
|
+
if (err instanceof QueueDoesNotExist)
|
|
11357
|
+
continue;
|
|
11358
|
+
throw err;
|
|
11359
|
+
}
|
|
11360
|
+
}
|
|
11361
|
+
nextToken = list.NextToken;
|
|
11362
|
+
} while (nextToken);
|
|
11363
|
+
return null;
|
|
11364
|
+
}
|
|
11170
11365
|
};
|
|
11171
11366
|
|
|
11172
11367
|
// src/provisioning/providers/sqs-queue-policy-provider.ts
|
|
@@ -11329,6 +11524,9 @@ var SQSQueuePolicyProvider = class {
|
|
|
11329
11524
|
import {
|
|
11330
11525
|
CreateTopicCommand,
|
|
11331
11526
|
DeleteTopicCommand,
|
|
11527
|
+
GetTopicAttributesCommand,
|
|
11528
|
+
ListTopicsCommand,
|
|
11529
|
+
ListTagsForResourceCommand,
|
|
11332
11530
|
SetTopicAttributesCommand,
|
|
11333
11531
|
TagResourceCommand,
|
|
11334
11532
|
UntagResourceCommand,
|
|
@@ -11618,6 +11816,63 @@ var SNSTopicProvider = class {
|
|
|
11618
11816
|
);
|
|
11619
11817
|
}
|
|
11620
11818
|
}
|
|
11819
|
+
/**
|
|
11820
|
+
* Adopt an existing SNS topic into cdkd state.
|
|
11821
|
+
*
|
|
11822
|
+
* SNS physical IDs are full ARNs (`arn:aws:sns:...:TopicName`). The
|
|
11823
|
+
* `--resource` override is expected to receive an ARN; bare topic names
|
|
11824
|
+
* trigger a `ListTopics` walk that resolves to the ARN.
|
|
11825
|
+
*
|
|
11826
|
+
* Lookup order:
|
|
11827
|
+
* 1. `--resource` override → trust as ARN, verify via `GetTopicAttributes`.
|
|
11828
|
+
* 2. `Properties.TopicName` → `ListTopics` to find matching ARN.
|
|
11829
|
+
* 3. `aws:cdk:path` tag match via `ListTopics` + `ListTagsForResource`.
|
|
11830
|
+
*/
|
|
11831
|
+
async import(input) {
|
|
11832
|
+
if (input.knownPhysicalId) {
|
|
11833
|
+
try {
|
|
11834
|
+
await this.snsClient.send(
|
|
11835
|
+
new GetTopicAttributesCommand({ TopicArn: input.knownPhysicalId })
|
|
11836
|
+
);
|
|
11837
|
+
return { physicalId: input.knownPhysicalId, attributes: {} };
|
|
11838
|
+
} catch (err) {
|
|
11839
|
+
if (err instanceof NotFoundException)
|
|
11840
|
+
return null;
|
|
11841
|
+
throw err;
|
|
11842
|
+
}
|
|
11843
|
+
}
|
|
11844
|
+
const desiredName = typeof input.properties?.["TopicName"] === "string" ? input.properties["TopicName"] : void 0;
|
|
11845
|
+
let nextToken;
|
|
11846
|
+
do {
|
|
11847
|
+
const list = await this.snsClient.send(
|
|
11848
|
+
new ListTopicsCommand({ ...nextToken && { NextToken: nextToken } })
|
|
11849
|
+
);
|
|
11850
|
+
for (const t of list.Topics ?? []) {
|
|
11851
|
+
if (!t.TopicArn)
|
|
11852
|
+
continue;
|
|
11853
|
+
const arnTail = t.TopicArn.substring(t.TopicArn.lastIndexOf(":") + 1);
|
|
11854
|
+
if (desiredName && arnTail === desiredName) {
|
|
11855
|
+
return { physicalId: t.TopicArn, attributes: {} };
|
|
11856
|
+
}
|
|
11857
|
+
if (input.cdkPath) {
|
|
11858
|
+
try {
|
|
11859
|
+
const tagsResp = await this.snsClient.send(
|
|
11860
|
+
new ListTagsForResourceCommand({ ResourceArn: t.TopicArn })
|
|
11861
|
+
);
|
|
11862
|
+
if (matchesCdkPath(tagsResp.Tags, input.cdkPath)) {
|
|
11863
|
+
return { physicalId: t.TopicArn, attributes: {} };
|
|
11864
|
+
}
|
|
11865
|
+
} catch (err) {
|
|
11866
|
+
if (err instanceof NotFoundException)
|
|
11867
|
+
continue;
|
|
11868
|
+
throw err;
|
|
11869
|
+
}
|
|
11870
|
+
}
|
|
11871
|
+
}
|
|
11872
|
+
nextToken = list.NextToken;
|
|
11873
|
+
} while (nextToken);
|
|
11874
|
+
return null;
|
|
11875
|
+
}
|
|
11621
11876
|
};
|
|
11622
11877
|
|
|
11623
11878
|
// src/provisioning/providers/sns-subscription-provider.ts
|
|
@@ -11917,6 +12172,8 @@ import {
|
|
|
11917
12172
|
UpdateFunctionCodeCommand,
|
|
11918
12173
|
DeleteFunctionCommand,
|
|
11919
12174
|
GetFunctionCommand,
|
|
12175
|
+
ListFunctionsCommand,
|
|
12176
|
+
ListTagsCommand,
|
|
11920
12177
|
ResourceNotFoundException
|
|
11921
12178
|
} from "@aws-sdk/client-lambda";
|
|
11922
12179
|
import {
|
|
@@ -12501,6 +12758,57 @@ var LambdaFunctionProvider = class {
|
|
|
12501
12758
|
}
|
|
12502
12759
|
return (crc ^ 4294967295) >>> 0;
|
|
12503
12760
|
}
|
|
12761
|
+
/**
|
|
12762
|
+
* Adopt an existing Lambda function into cdkd state.
|
|
12763
|
+
*
|
|
12764
|
+
* Lookup order:
|
|
12765
|
+
* 1. `--resource` override or `Properties.FunctionName` → use directly,
|
|
12766
|
+
* verify via `GetFunction`.
|
|
12767
|
+
* 2. `ListFunctions` + `ListTags`, match `aws:cdk:path` tag.
|
|
12768
|
+
*
|
|
12769
|
+
* Lambda's `ListTags` returns a `Tags` map keyed by tag name (unlike
|
|
12770
|
+
* EC2/S3 which return an array of `{Key, Value}`), so we read it directly
|
|
12771
|
+
* instead of going through the shared `matchesCdkPath` helper.
|
|
12772
|
+
*/
|
|
12773
|
+
async import(input) {
|
|
12774
|
+
const explicit = resolveExplicitPhysicalId(input, "FunctionName");
|
|
12775
|
+
if (explicit) {
|
|
12776
|
+
try {
|
|
12777
|
+
await this.lambdaClient.send(new GetFunctionCommand({ FunctionName: explicit }));
|
|
12778
|
+
return { physicalId: explicit, attributes: {} };
|
|
12779
|
+
} catch (err) {
|
|
12780
|
+
if (err instanceof ResourceNotFoundException)
|
|
12781
|
+
return null;
|
|
12782
|
+
throw err;
|
|
12783
|
+
}
|
|
12784
|
+
}
|
|
12785
|
+
if (!input.cdkPath)
|
|
12786
|
+
return null;
|
|
12787
|
+
let marker;
|
|
12788
|
+
do {
|
|
12789
|
+
const list = await this.lambdaClient.send(
|
|
12790
|
+
new ListFunctionsCommand({ ...marker && { Marker: marker } })
|
|
12791
|
+
);
|
|
12792
|
+
for (const fn of list.Functions ?? []) {
|
|
12793
|
+
if (!fn.FunctionArn || !fn.FunctionName)
|
|
12794
|
+
continue;
|
|
12795
|
+
try {
|
|
12796
|
+
const tagsResp = await this.lambdaClient.send(
|
|
12797
|
+
new ListTagsCommand({ Resource: fn.FunctionArn })
|
|
12798
|
+
);
|
|
12799
|
+
if (tagsResp.Tags?.[CDK_PATH_TAG] === input.cdkPath) {
|
|
12800
|
+
return { physicalId: fn.FunctionName, attributes: {} };
|
|
12801
|
+
}
|
|
12802
|
+
} catch (err) {
|
|
12803
|
+
if (err instanceof ResourceNotFoundException)
|
|
12804
|
+
continue;
|
|
12805
|
+
throw err;
|
|
12806
|
+
}
|
|
12807
|
+
}
|
|
12808
|
+
marker = list.NextMarker;
|
|
12809
|
+
} while (marker);
|
|
12810
|
+
return null;
|
|
12811
|
+
}
|
|
12504
12812
|
};
|
|
12505
12813
|
|
|
12506
12814
|
// src/provisioning/providers/lambda-permission-provider.ts
|
|
@@ -13222,6 +13530,8 @@ import {
|
|
|
13222
13530
|
CreateTableCommand,
|
|
13223
13531
|
DeleteTableCommand,
|
|
13224
13532
|
DescribeTableCommand as DescribeTableCommand2,
|
|
13533
|
+
ListTablesCommand,
|
|
13534
|
+
ListTagsOfResourceCommand,
|
|
13225
13535
|
ResourceNotFoundException as ResourceNotFoundException6
|
|
13226
13536
|
} from "@aws-sdk/client-dynamodb";
|
|
13227
13537
|
init_aws_clients();
|
|
@@ -13433,12 +13743,70 @@ var DynamoDBTableProvider = class {
|
|
|
13433
13743
|
}
|
|
13434
13744
|
throw new Error(`Table ${tableName} did not reach ACTIVE status within ${maxAttempts} seconds`);
|
|
13435
13745
|
}
|
|
13746
|
+
/**
|
|
13747
|
+
* Adopt an existing DynamoDB table into cdkd state.
|
|
13748
|
+
*
|
|
13749
|
+
* Lookup order:
|
|
13750
|
+
* 1. `--resource` override or `Properties.TableName` → verify via `DescribeTable`.
|
|
13751
|
+
* 2. `ListTables` + `ListTagsOfResource`, match `aws:cdk:path` tag.
|
|
13752
|
+
*
|
|
13753
|
+
* Tags require the table ARN, which `DescribeTable` provides; the loop
|
|
13754
|
+
* therefore costs one `DescribeTable` per table just to read the ARN.
|
|
13755
|
+
* Acceptable for typical DynamoDB cardinalities.
|
|
13756
|
+
*/
|
|
13757
|
+
async import(input) {
|
|
13758
|
+
const explicit = resolveExplicitPhysicalId(input, "TableName");
|
|
13759
|
+
if (explicit) {
|
|
13760
|
+
try {
|
|
13761
|
+
await this.dynamoDBClient.send(new DescribeTableCommand2({ TableName: explicit }));
|
|
13762
|
+
return { physicalId: explicit, attributes: {} };
|
|
13763
|
+
} catch (err) {
|
|
13764
|
+
if (err instanceof ResourceNotFoundException6)
|
|
13765
|
+
return null;
|
|
13766
|
+
throw err;
|
|
13767
|
+
}
|
|
13768
|
+
}
|
|
13769
|
+
if (!input.cdkPath)
|
|
13770
|
+
return null;
|
|
13771
|
+
let exclusiveStartTableName;
|
|
13772
|
+
do {
|
|
13773
|
+
const list = await this.dynamoDBClient.send(
|
|
13774
|
+
new ListTablesCommand({
|
|
13775
|
+
...exclusiveStartTableName && { ExclusiveStartTableName: exclusiveStartTableName }
|
|
13776
|
+
})
|
|
13777
|
+
);
|
|
13778
|
+
for (const name of list.TableNames ?? []) {
|
|
13779
|
+
try {
|
|
13780
|
+
const desc = await this.dynamoDBClient.send(
|
|
13781
|
+
new DescribeTableCommand2({ TableName: name })
|
|
13782
|
+
);
|
|
13783
|
+
const arn = desc.Table?.TableArn;
|
|
13784
|
+
if (!arn)
|
|
13785
|
+
continue;
|
|
13786
|
+
const tagsResp = await this.dynamoDBClient.send(
|
|
13787
|
+
new ListTagsOfResourceCommand({ ResourceArn: arn })
|
|
13788
|
+
);
|
|
13789
|
+
if (matchesCdkPath(tagsResp.Tags, input.cdkPath)) {
|
|
13790
|
+
return { physicalId: name, attributes: {} };
|
|
13791
|
+
}
|
|
13792
|
+
} catch (err) {
|
|
13793
|
+
if (err instanceof ResourceNotFoundException6)
|
|
13794
|
+
continue;
|
|
13795
|
+
throw err;
|
|
13796
|
+
}
|
|
13797
|
+
}
|
|
13798
|
+
exclusiveStartTableName = list.LastEvaluatedTableName;
|
|
13799
|
+
} while (exclusiveStartTableName);
|
|
13800
|
+
return null;
|
|
13801
|
+
}
|
|
13436
13802
|
};
|
|
13437
13803
|
|
|
13438
13804
|
// src/provisioning/providers/logs-loggroup-provider.ts
|
|
13439
13805
|
import {
|
|
13440
13806
|
CreateLogGroupCommand,
|
|
13441
13807
|
DeleteLogGroupCommand,
|
|
13808
|
+
DescribeLogGroupsCommand,
|
|
13809
|
+
ListTagsForResourceCommand as ListTagsForResourceCommand2,
|
|
13442
13810
|
PutRetentionPolicyCommand,
|
|
13443
13811
|
DeleteRetentionPolicyCommand,
|
|
13444
13812
|
TagResourceCommand as TagResourceCommand2,
|
|
@@ -13662,6 +14030,61 @@ var LogsLogGroupProvider = class {
|
|
|
13662
14030
|
return `arn:aws:logs:unknown:unknown:log-group:${logGroupName}:*`;
|
|
13663
14031
|
}
|
|
13664
14032
|
}
|
|
14033
|
+
/**
|
|
14034
|
+
* Adopt an existing CloudWatch Logs log group into cdkd state.
|
|
14035
|
+
*
|
|
14036
|
+
* Lookup order:
|
|
14037
|
+
* 1. `--resource` override or `Properties.LogGroupName` → verify via
|
|
14038
|
+
* `DescribeLogGroups` (filtered by name prefix).
|
|
14039
|
+
* 2. `aws:cdk:path` tag match via `DescribeLogGroups` + `ListTagsForResource`.
|
|
14040
|
+
*
|
|
14041
|
+
* `ListTagsForResource` for log groups uses the log-group ARN. The
|
|
14042
|
+
* `DescribeLogGroups` response includes the ARN, so no extra round-trip
|
|
14043
|
+
* is needed beyond the per-group tag lookup.
|
|
14044
|
+
*/
|
|
14045
|
+
async import(input) {
|
|
14046
|
+
const explicit = resolveExplicitPhysicalId(input, "LogGroupName");
|
|
14047
|
+
if (explicit) {
|
|
14048
|
+
try {
|
|
14049
|
+
const resp = await this.logsClient.send(
|
|
14050
|
+
new DescribeLogGroupsCommand({ logGroupNamePrefix: explicit })
|
|
14051
|
+
);
|
|
14052
|
+
const found = resp.logGroups?.find((g) => g.logGroupName === explicit);
|
|
14053
|
+
return found ? { physicalId: explicit, attributes: {} } : null;
|
|
14054
|
+
} catch (err) {
|
|
14055
|
+
if (err instanceof ResourceNotFoundException7)
|
|
14056
|
+
return null;
|
|
14057
|
+
throw err;
|
|
14058
|
+
}
|
|
14059
|
+
}
|
|
14060
|
+
if (!input.cdkPath)
|
|
14061
|
+
return null;
|
|
14062
|
+
let nextToken;
|
|
14063
|
+
do {
|
|
14064
|
+
const list = await this.logsClient.send(
|
|
14065
|
+
new DescribeLogGroupsCommand({ ...nextToken && { nextToken } })
|
|
14066
|
+
);
|
|
14067
|
+
for (const g of list.logGroups ?? []) {
|
|
14068
|
+
if (!g.logGroupName || !g.arn)
|
|
14069
|
+
continue;
|
|
14070
|
+
const arnForTags = g.arn.replace(/:\*$/, "");
|
|
14071
|
+
try {
|
|
14072
|
+
const tagsResp = await this.logsClient.send(
|
|
14073
|
+
new ListTagsForResourceCommand2({ resourceArn: arnForTags })
|
|
14074
|
+
);
|
|
14075
|
+
if (tagsResp.tags?.["aws:cdk:path"] === input.cdkPath) {
|
|
14076
|
+
return { physicalId: g.logGroupName, attributes: {} };
|
|
14077
|
+
}
|
|
14078
|
+
} catch (err) {
|
|
14079
|
+
if (err instanceof ResourceNotFoundException7)
|
|
14080
|
+
continue;
|
|
14081
|
+
throw err;
|
|
14082
|
+
}
|
|
14083
|
+
}
|
|
14084
|
+
nextToken = list.nextToken;
|
|
14085
|
+
} while (nextToken);
|
|
14086
|
+
return null;
|
|
14087
|
+
}
|
|
13665
14088
|
};
|
|
13666
14089
|
|
|
13667
14090
|
// src/provisioning/providers/cloudwatch-alarm-provider.ts
|
|
@@ -13892,6 +14315,8 @@ var CloudWatchAlarmProvider = class {
|
|
|
13892
14315
|
import {
|
|
13893
14316
|
CreateSecretCommand,
|
|
13894
14317
|
DeleteSecretCommand,
|
|
14318
|
+
DescribeSecretCommand,
|
|
14319
|
+
ListSecretsCommand,
|
|
13895
14320
|
UpdateSecretCommand,
|
|
13896
14321
|
TagResourceCommand as TagResourceCommand3,
|
|
13897
14322
|
UntagResourceCommand as UntagResourceCommand3,
|
|
@@ -14159,10 +14584,65 @@ var SecretsManagerSecretProvider = class {
|
|
|
14159
14584
|
}
|
|
14160
14585
|
return password;
|
|
14161
14586
|
}
|
|
14587
|
+
/**
|
|
14588
|
+
* Adopt an existing Secrets Manager secret into cdkd state.
|
|
14589
|
+
*
|
|
14590
|
+
* Secrets Manager physical IDs are full secret ARNs. The CDK template's
|
|
14591
|
+
* `Properties.Name` (secret name) is enough to fetch the ARN via
|
|
14592
|
+
* `DescribeSecret`.
|
|
14593
|
+
*
|
|
14594
|
+
* Lookup order:
|
|
14595
|
+
* 1. `--resource` override (ARN) → verify via `DescribeSecret`.
|
|
14596
|
+
* 2. `Properties.Name` → `DescribeSecret` (accepts name).
|
|
14597
|
+
* 3. `aws:cdk:path` tag match via `ListSecrets` (which already returns Tags).
|
|
14598
|
+
*/
|
|
14599
|
+
async import(input) {
|
|
14600
|
+
if (input.knownPhysicalId) {
|
|
14601
|
+
try {
|
|
14602
|
+
const resp = await this.smClient.send(
|
|
14603
|
+
new DescribeSecretCommand({ SecretId: input.knownPhysicalId })
|
|
14604
|
+
);
|
|
14605
|
+
return resp.ARN ? { physicalId: resp.ARN, attributes: {} } : null;
|
|
14606
|
+
} catch (err) {
|
|
14607
|
+
if (err instanceof ResourceNotFoundException8)
|
|
14608
|
+
return null;
|
|
14609
|
+
throw err;
|
|
14610
|
+
}
|
|
14611
|
+
}
|
|
14612
|
+
const name = typeof input.properties?.["Name"] === "string" ? input.properties["Name"] : void 0;
|
|
14613
|
+
if (name) {
|
|
14614
|
+
try {
|
|
14615
|
+
const resp = await this.smClient.send(new DescribeSecretCommand({ SecretId: name }));
|
|
14616
|
+
return resp.ARN ? { physicalId: resp.ARN, attributes: {} } : null;
|
|
14617
|
+
} catch (err) {
|
|
14618
|
+
if (err instanceof ResourceNotFoundException8)
|
|
14619
|
+
return null;
|
|
14620
|
+
throw err;
|
|
14621
|
+
}
|
|
14622
|
+
}
|
|
14623
|
+
if (!input.cdkPath)
|
|
14624
|
+
return null;
|
|
14625
|
+
let nextToken;
|
|
14626
|
+
do {
|
|
14627
|
+
const list = await this.smClient.send(
|
|
14628
|
+
new ListSecretsCommand({ ...nextToken && { NextToken: nextToken } })
|
|
14629
|
+
);
|
|
14630
|
+
for (const s of list.SecretList ?? []) {
|
|
14631
|
+
if (s.ARN && matchesCdkPath(s.Tags, input.cdkPath)) {
|
|
14632
|
+
return { physicalId: s.ARN, attributes: {} };
|
|
14633
|
+
}
|
|
14634
|
+
}
|
|
14635
|
+
nextToken = list.NextToken;
|
|
14636
|
+
} while (nextToken);
|
|
14637
|
+
return null;
|
|
14638
|
+
}
|
|
14162
14639
|
};
|
|
14163
14640
|
|
|
14164
14641
|
// src/provisioning/providers/ssm-parameter-provider.ts
|
|
14165
14642
|
import {
|
|
14643
|
+
DescribeParametersCommand,
|
|
14644
|
+
GetParameterCommand as GetParameterCommand3,
|
|
14645
|
+
ListTagsForResourceCommand as ListTagsForResourceCommand3,
|
|
14166
14646
|
PutParameterCommand,
|
|
14167
14647
|
DeleteParameterCommand,
|
|
14168
14648
|
AddTagsToResourceCommand,
|
|
@@ -14374,6 +14854,57 @@ var SSMParameterProvider = class {
|
|
|
14374
14854
|
);
|
|
14375
14855
|
}
|
|
14376
14856
|
}
|
|
14857
|
+
/**
|
|
14858
|
+
* Adopt an existing SSM parameter into cdkd state.
|
|
14859
|
+
*
|
|
14860
|
+
* SSM physical IDs ARE the parameter names (`/foo/bar`). The CDK template
|
|
14861
|
+
* usually carries `Properties.Name` explicitly, so the explicit-name path
|
|
14862
|
+
* covers most cases. The tag-based fallback is rarely needed.
|
|
14863
|
+
*
|
|
14864
|
+
* Lookup order:
|
|
14865
|
+
* 1. `--resource` override or `Properties.Name` → verify via `GetParameter`.
|
|
14866
|
+
* 2. `aws:cdk:path` tag match via `DescribeParameters` + `ListTagsForResource`
|
|
14867
|
+
* (`ResourceType: 'Parameter'`, `ResourceId: <name>`).
|
|
14868
|
+
*/
|
|
14869
|
+
async import(input) {
|
|
14870
|
+
const explicit = resolveExplicitPhysicalId(input, "Name");
|
|
14871
|
+
if (explicit) {
|
|
14872
|
+
try {
|
|
14873
|
+
await this.ssmClient.send(new GetParameterCommand3({ Name: explicit }));
|
|
14874
|
+
return { physicalId: explicit, attributes: {} };
|
|
14875
|
+
} catch (err) {
|
|
14876
|
+
if (err instanceof ParameterNotFound)
|
|
14877
|
+
return null;
|
|
14878
|
+
throw err;
|
|
14879
|
+
}
|
|
14880
|
+
}
|
|
14881
|
+
if (!input.cdkPath)
|
|
14882
|
+
return null;
|
|
14883
|
+
let nextToken;
|
|
14884
|
+
do {
|
|
14885
|
+
const list = await this.ssmClient.send(
|
|
14886
|
+
new DescribeParametersCommand({ ...nextToken && { NextToken: nextToken } })
|
|
14887
|
+
);
|
|
14888
|
+
for (const p of list.Parameters ?? []) {
|
|
14889
|
+
if (!p.Name)
|
|
14890
|
+
continue;
|
|
14891
|
+
try {
|
|
14892
|
+
const tagsResp = await this.ssmClient.send(
|
|
14893
|
+
new ListTagsForResourceCommand3({ ResourceType: "Parameter", ResourceId: p.Name })
|
|
14894
|
+
);
|
|
14895
|
+
if (matchesCdkPath(tagsResp.TagList, input.cdkPath)) {
|
|
14896
|
+
return { physicalId: p.Name, attributes: {} };
|
|
14897
|
+
}
|
|
14898
|
+
} catch (err) {
|
|
14899
|
+
if (err instanceof ParameterNotFound)
|
|
14900
|
+
continue;
|
|
14901
|
+
throw err;
|
|
14902
|
+
}
|
|
14903
|
+
}
|
|
14904
|
+
nextToken = list.NextToken;
|
|
14905
|
+
} while (nextToken);
|
|
14906
|
+
return null;
|
|
14907
|
+
}
|
|
14377
14908
|
};
|
|
14378
14909
|
|
|
14379
14910
|
// src/provisioning/providers/eventbridge-rule-provider.ts
|
|
@@ -14672,7 +15203,9 @@ import {
|
|
|
14672
15203
|
DeleteEventBusCommand,
|
|
14673
15204
|
UpdateEventBusCommand,
|
|
14674
15205
|
DescribeEventBusCommand,
|
|
15206
|
+
ListEventBusesCommand,
|
|
14675
15207
|
ListRulesCommand,
|
|
15208
|
+
ListTagsForResourceCommand as ListTagsForResourceCommand4,
|
|
14676
15209
|
RemoveTargetsCommand as RemoveTargetsCommand2,
|
|
14677
15210
|
DeleteRuleCommand as DeleteRuleCommand2,
|
|
14678
15211
|
ListTargetsByRuleCommand as ListTargetsByRuleCommand2,
|
|
@@ -14913,6 +15446,52 @@ var EventBridgeBusProvider = class {
|
|
|
14913
15446
|
);
|
|
14914
15447
|
}
|
|
14915
15448
|
}
|
|
15449
|
+
/**
|
|
15450
|
+
* Adopt an existing EventBridge event bus into cdkd state.
|
|
15451
|
+
*
|
|
15452
|
+
* Lookup order:
|
|
15453
|
+
* 1. `--resource` override or `Properties.Name` → verify via `DescribeEventBus`.
|
|
15454
|
+
* 2. `aws:cdk:path` tag match via `ListEventBuses` + `ListTagsForResource`.
|
|
15455
|
+
*/
|
|
15456
|
+
async import(input) {
|
|
15457
|
+
const explicit = resolveExplicitPhysicalId(input, "Name");
|
|
15458
|
+
if (explicit) {
|
|
15459
|
+
try {
|
|
15460
|
+
await this.eventBridgeClient.send(new DescribeEventBusCommand({ Name: explicit }));
|
|
15461
|
+
return { physicalId: explicit, attributes: {} };
|
|
15462
|
+
} catch (err) {
|
|
15463
|
+
if (err instanceof ResourceNotFoundException10)
|
|
15464
|
+
return null;
|
|
15465
|
+
throw err;
|
|
15466
|
+
}
|
|
15467
|
+
}
|
|
15468
|
+
if (!input.cdkPath)
|
|
15469
|
+
return null;
|
|
15470
|
+
let nextToken;
|
|
15471
|
+
do {
|
|
15472
|
+
const list = await this.eventBridgeClient.send(
|
|
15473
|
+
new ListEventBusesCommand({ ...nextToken && { NextToken: nextToken } })
|
|
15474
|
+
);
|
|
15475
|
+
for (const bus of list.EventBuses ?? []) {
|
|
15476
|
+
if (!bus.Name || !bus.Arn)
|
|
15477
|
+
continue;
|
|
15478
|
+
try {
|
|
15479
|
+
const tagsResp = await this.eventBridgeClient.send(
|
|
15480
|
+
new ListTagsForResourceCommand4({ ResourceARN: bus.Arn })
|
|
15481
|
+
);
|
|
15482
|
+
if (matchesCdkPath(tagsResp.Tags, input.cdkPath)) {
|
|
15483
|
+
return { physicalId: bus.Name, attributes: {} };
|
|
15484
|
+
}
|
|
15485
|
+
} catch (err) {
|
|
15486
|
+
if (err instanceof ResourceNotFoundException10)
|
|
15487
|
+
continue;
|
|
15488
|
+
throw err;
|
|
15489
|
+
}
|
|
15490
|
+
}
|
|
15491
|
+
nextToken = list.NextToken;
|
|
15492
|
+
} while (nextToken);
|
|
15493
|
+
return null;
|
|
15494
|
+
}
|
|
14916
15495
|
};
|
|
14917
15496
|
|
|
14918
15497
|
// src/provisioning/providers/ec2-provider.ts
|
|
@@ -24219,6 +24798,10 @@ var GlueProvider = class {
|
|
|
24219
24798
|
import {
|
|
24220
24799
|
KMSClient as KMSClient2,
|
|
24221
24800
|
CreateKeyCommand,
|
|
24801
|
+
DescribeKeyCommand,
|
|
24802
|
+
ListAliasesCommand as ListAliasesCommand2,
|
|
24803
|
+
ListKeysCommand,
|
|
24804
|
+
ListResourceTagsCommand,
|
|
24222
24805
|
ScheduleKeyDeletionCommand,
|
|
24223
24806
|
CreateAliasCommand,
|
|
24224
24807
|
DeleteAliasCommand,
|
|
@@ -24601,6 +25184,81 @@ var KMSProvider = class {
|
|
|
24601
25184
|
);
|
|
24602
25185
|
}
|
|
24603
25186
|
}
|
|
25187
|
+
/**
|
|
25188
|
+
* Adopt an existing KMS key or alias into cdkd state.
|
|
25189
|
+
*
|
|
25190
|
+
* KMS keys have no `Properties.KeyName` field — physical IDs are
|
|
25191
|
+
* AWS-generated UUIDs. So:
|
|
25192
|
+
* - For `AWS::KMS::Key`: `--resource MyKey=<keyId>` is the only explicit
|
|
25193
|
+
* path; auto-lookup walks `ListKeys` + `ListResourceTags` matching
|
|
25194
|
+
* `aws:cdk:path`.
|
|
25195
|
+
* - For `AWS::KMS::Alias`: `Properties.AliasName` is explicit and reliable.
|
|
25196
|
+
*/
|
|
25197
|
+
async import(input) {
|
|
25198
|
+
if (input.resourceType === "AWS::KMS::Alias") {
|
|
25199
|
+
const aliasName = input.knownPhysicalId ?? (typeof input.properties?.["AliasName"] === "string" ? input.properties["AliasName"] : void 0);
|
|
25200
|
+
if (!aliasName)
|
|
25201
|
+
return null;
|
|
25202
|
+
try {
|
|
25203
|
+
let marker2;
|
|
25204
|
+
do {
|
|
25205
|
+
const list = await this.getClient().send(
|
|
25206
|
+
new ListAliasesCommand2({ ...marker2 && { Marker: marker2 } })
|
|
25207
|
+
);
|
|
25208
|
+
const found = list.Aliases?.find(
|
|
25209
|
+
(a) => a.AliasName === aliasName
|
|
25210
|
+
);
|
|
25211
|
+
if (found)
|
|
25212
|
+
return { physicalId: aliasName, attributes: {} };
|
|
25213
|
+
marker2 = list.NextMarker;
|
|
25214
|
+
} while (marker2);
|
|
25215
|
+
return null;
|
|
25216
|
+
} catch (err) {
|
|
25217
|
+
if (err instanceof NotFoundException5)
|
|
25218
|
+
return null;
|
|
25219
|
+
throw err;
|
|
25220
|
+
}
|
|
25221
|
+
}
|
|
25222
|
+
if (input.knownPhysicalId) {
|
|
25223
|
+
try {
|
|
25224
|
+
await this.getClient().send(new DescribeKeyCommand({ KeyId: input.knownPhysicalId }));
|
|
25225
|
+
return { physicalId: input.knownPhysicalId, attributes: {} };
|
|
25226
|
+
} catch (err) {
|
|
25227
|
+
if (err instanceof NotFoundException5)
|
|
25228
|
+
return null;
|
|
25229
|
+
throw err;
|
|
25230
|
+
}
|
|
25231
|
+
}
|
|
25232
|
+
if (!input.cdkPath)
|
|
25233
|
+
return null;
|
|
25234
|
+
let marker;
|
|
25235
|
+
do {
|
|
25236
|
+
const list = await this.getClient().send(
|
|
25237
|
+
new ListKeysCommand({ ...marker && { Marker: marker } })
|
|
25238
|
+
);
|
|
25239
|
+
for (const key of list.Keys ?? []) {
|
|
25240
|
+
if (!key.KeyId)
|
|
25241
|
+
continue;
|
|
25242
|
+
try {
|
|
25243
|
+
const tagsResp = await this.getClient().send(
|
|
25244
|
+
new ListResourceTagsCommand({ KeyId: key.KeyId })
|
|
25245
|
+
);
|
|
25246
|
+
for (const tag of tagsResp.Tags ?? []) {
|
|
25247
|
+
if (tag.TagKey === CDK_PATH_TAG && tag.TagValue === input.cdkPath) {
|
|
25248
|
+
return { physicalId: key.KeyId, attributes: {} };
|
|
25249
|
+
}
|
|
25250
|
+
}
|
|
25251
|
+
} catch (err) {
|
|
25252
|
+
const name = err.name;
|
|
25253
|
+
if (name === "AccessDeniedException" || err instanceof NotFoundException5)
|
|
25254
|
+
continue;
|
|
25255
|
+
throw err;
|
|
25256
|
+
}
|
|
25257
|
+
}
|
|
25258
|
+
marker = list.NextMarker;
|
|
25259
|
+
} while (marker);
|
|
25260
|
+
return null;
|
|
25261
|
+
}
|
|
24604
25262
|
};
|
|
24605
25263
|
|
|
24606
25264
|
// src/provisioning/providers/kinesis-provider.ts
|
|
@@ -26579,7 +27237,7 @@ import {
|
|
|
26579
27237
|
CreateTableCommand as CreateTableCommand3,
|
|
26580
27238
|
DeleteTableCommand as DeleteTableCommand3,
|
|
26581
27239
|
ListNamespacesCommand,
|
|
26582
|
-
ListTablesCommand,
|
|
27240
|
+
ListTablesCommand as ListTablesCommand2,
|
|
26583
27241
|
NotFoundException as NotFoundException6
|
|
26584
27242
|
} from "@aws-sdk/client-s3tables";
|
|
26585
27243
|
var S3TablesProvider = class {
|
|
@@ -26725,7 +27383,7 @@ var S3TablesProvider = class {
|
|
|
26725
27383
|
let tableContinuationToken;
|
|
26726
27384
|
do {
|
|
26727
27385
|
const tablesResult = await this.getClient().send(
|
|
26728
|
-
new
|
|
27386
|
+
new ListTablesCommand2({
|
|
26729
27387
|
tableBucketARN,
|
|
26730
27388
|
namespace: namespaceName,
|
|
26731
27389
|
continuationToken: tableContinuationToken
|
|
@@ -29572,7 +30230,7 @@ import {
|
|
|
29572
30230
|
CreateBucketCommand as CreateBucketCommand4,
|
|
29573
30231
|
DeleteBucketCommand as DeleteBucketCommand3,
|
|
29574
30232
|
DeleteObjectsCommand as DeleteObjectsCommand3,
|
|
29575
|
-
HeadBucketCommand as
|
|
30233
|
+
HeadBucketCommand as HeadBucketCommand4,
|
|
29576
30234
|
ListObjectVersionsCommand as ListObjectVersionsCommand2,
|
|
29577
30235
|
ListObjectsV2Command as ListObjectsV2Command3,
|
|
29578
30236
|
PutBucketEncryptionCommand as PutBucketEncryptionCommand3,
|
|
@@ -29695,7 +30353,7 @@ async function stateMigrateBucketCommand(options) {
|
|
|
29695
30353
|
}
|
|
29696
30354
|
async function bucketExists2(s3, bucketName) {
|
|
29697
30355
|
try {
|
|
29698
|
-
await s3.send(new
|
|
30356
|
+
await s3.send(new HeadBucketCommand4({ Bucket: bucketName }));
|
|
29699
30357
|
return true;
|
|
29700
30358
|
} catch (error) {
|
|
29701
30359
|
const err = error;
|
|
@@ -30557,6 +31215,341 @@ function createStateCommand() {
|
|
|
30557
31215
|
return cmd;
|
|
30558
31216
|
}
|
|
30559
31217
|
|
|
31218
|
+
// src/cli/commands/import.ts
|
|
31219
|
+
import { readFileSync as readFileSync5 } from "node:fs";
|
|
31220
|
+
import * as readline4 from "node:readline/promises";
|
|
31221
|
+
import { Command as Command11 } from "commander";
|
|
31222
|
+
init_aws_clients();
|
|
31223
|
+
async function importCommand(stackArg, options) {
|
|
31224
|
+
const logger = getLogger();
|
|
31225
|
+
if (options.verbose) {
|
|
31226
|
+
logger.setLevel("debug");
|
|
31227
|
+
process.env["CDKD_NO_LIVE"] = "1";
|
|
31228
|
+
}
|
|
31229
|
+
const region = options.region || process.env["AWS_REGION"] || "us-east-1";
|
|
31230
|
+
const stateBucket = await resolveStateBucketWithDefault(options.stateBucket, region);
|
|
31231
|
+
if (options.region) {
|
|
31232
|
+
process.env["AWS_REGION"] = options.region;
|
|
31233
|
+
process.env["AWS_DEFAULT_REGION"] = options.region;
|
|
31234
|
+
}
|
|
31235
|
+
const awsClients = new AwsClients({
|
|
31236
|
+
...options.region && { region: options.region },
|
|
31237
|
+
...options.profile && { profile: options.profile }
|
|
31238
|
+
});
|
|
31239
|
+
setAwsClients(awsClients);
|
|
31240
|
+
try {
|
|
31241
|
+
const stateConfig = { bucket: stateBucket, prefix: options.statePrefix };
|
|
31242
|
+
const stateBackend = new S3StateBackend(awsClients.s3, stateConfig, {
|
|
31243
|
+
...options.region && { region: options.region },
|
|
31244
|
+
...options.profile && { profile: options.profile }
|
|
31245
|
+
});
|
|
31246
|
+
await stateBackend.verifyBucketExists();
|
|
31247
|
+
const lockManager = new LockManager(awsClients.s3, stateConfig);
|
|
31248
|
+
const providerRegistry = new ProviderRegistry();
|
|
31249
|
+
registerAllProviders(providerRegistry);
|
|
31250
|
+
const appCmd = options.app || resolveApp();
|
|
31251
|
+
if (!appCmd) {
|
|
31252
|
+
throw new Error(
|
|
31253
|
+
"`cdkd state import` requires a CDK app: pass --app or set it in cdk.json. The template is read to find logical IDs, resource types, and dependencies."
|
|
31254
|
+
);
|
|
31255
|
+
}
|
|
31256
|
+
logger.info("Synthesizing CDK app to read template...");
|
|
31257
|
+
const synthesizer = new Synthesizer();
|
|
31258
|
+
const context = parseContextOptions(options.context);
|
|
31259
|
+
const result = await synthesizer.synthesize({
|
|
31260
|
+
app: appCmd,
|
|
31261
|
+
output: options.output || "cdk.out",
|
|
31262
|
+
...Object.keys(context).length > 0 && { context }
|
|
31263
|
+
});
|
|
31264
|
+
let stackInfo;
|
|
31265
|
+
if (stackArg) {
|
|
31266
|
+
stackInfo = result.stacks.find((s) => s.stackName === stackArg || s.displayName === stackArg);
|
|
31267
|
+
if (!stackInfo) {
|
|
31268
|
+
throw new Error(
|
|
31269
|
+
`Stack '${stackArg}' not found in synthesized app. Available: ${result.stacks.map((s) => s.stackName).join(", ")}`
|
|
31270
|
+
);
|
|
31271
|
+
}
|
|
31272
|
+
} else if (result.stacks.length === 1) {
|
|
31273
|
+
stackInfo = result.stacks[0];
|
|
31274
|
+
} else {
|
|
31275
|
+
throw new Error(
|
|
31276
|
+
`Multiple stacks found: ${result.stacks.map((s) => s.stackName).join(", ")}. Specify the stack name as a positional argument.`
|
|
31277
|
+
);
|
|
31278
|
+
}
|
|
31279
|
+
const targetRegion = stackInfo.region || region;
|
|
31280
|
+
logger.info(`Target stack: ${stackInfo.stackName} (${targetRegion})`);
|
|
31281
|
+
const existing = await stateBackend.stateExists(stackInfo.stackName, targetRegion);
|
|
31282
|
+
if (existing && !options.force) {
|
|
31283
|
+
throw new Error(
|
|
31284
|
+
`State already exists for stack '${stackInfo.stackName}' (${targetRegion}). Pass --force to overwrite. (cdkd state import rebuilds the resource map from AWS, so the existing state \u2014 including any drift you've manually edited \u2014 will be lost.)`
|
|
31285
|
+
);
|
|
31286
|
+
}
|
|
31287
|
+
const overrides = parseResourceOverrides(options.resource, options.resourceMapping);
|
|
31288
|
+
if (overrides.size > 0) {
|
|
31289
|
+
logger.debug(`User-supplied physical IDs: ${[...overrides.keys()].join(", ")}`);
|
|
31290
|
+
}
|
|
31291
|
+
const template = stackInfo.template;
|
|
31292
|
+
const templateParser = new TemplateParser();
|
|
31293
|
+
const resources = collectImportableResources(template);
|
|
31294
|
+
logger.info(`Found ${resources.length} resource(s) in template`);
|
|
31295
|
+
const owner = `${process.env["USER"] || "unknown"}@${process.env["HOSTNAME"] || "host"}:${process.pid}`;
|
|
31296
|
+
await lockManager.acquireLock(stackInfo.stackName, targetRegion, owner, "import");
|
|
31297
|
+
try {
|
|
31298
|
+
const rows = [];
|
|
31299
|
+
for (const { logicalId, resource } of resources) {
|
|
31300
|
+
const outcome = await importOne({
|
|
31301
|
+
logicalId,
|
|
31302
|
+
resource,
|
|
31303
|
+
stackName: stackInfo.stackName,
|
|
31304
|
+
region: targetRegion,
|
|
31305
|
+
providerRegistry,
|
|
31306
|
+
override: overrides.get(logicalId)
|
|
31307
|
+
});
|
|
31308
|
+
rows.push(outcome);
|
|
31309
|
+
}
|
|
31310
|
+
printSummary(rows);
|
|
31311
|
+
if (options.dryRun) {
|
|
31312
|
+
logger.info("--dry-run: state will NOT be written. Re-run without --dry-run to apply.");
|
|
31313
|
+
return;
|
|
31314
|
+
}
|
|
31315
|
+
const importedRows = rows.filter((r) => r.outcome === "imported");
|
|
31316
|
+
if (importedRows.length === 0) {
|
|
31317
|
+
logger.warn("No resources were successfully imported. State will not be written.");
|
|
31318
|
+
return;
|
|
31319
|
+
}
|
|
31320
|
+
if (!options.yes) {
|
|
31321
|
+
const ok = await confirmPrompt2(
|
|
31322
|
+
`Write state for ${stackInfo.stackName} (${targetRegion}) with ${importedRows.length} resource(s)?`
|
|
31323
|
+
);
|
|
31324
|
+
if (!ok) {
|
|
31325
|
+
logger.info("Import cancelled.");
|
|
31326
|
+
return;
|
|
31327
|
+
}
|
|
31328
|
+
}
|
|
31329
|
+
const stackState = buildStackState(
|
|
31330
|
+
stackInfo.stackName,
|
|
31331
|
+
targetRegion,
|
|
31332
|
+
rows,
|
|
31333
|
+
templateParser,
|
|
31334
|
+
template
|
|
31335
|
+
);
|
|
31336
|
+
await stateBackend.saveState(stackInfo.stackName, targetRegion, stackState);
|
|
31337
|
+
logger.info(`\u2713 State written: ${stackInfo.stackName} (${targetRegion})`);
|
|
31338
|
+
logger.info(
|
|
31339
|
+
` ${importedRows.length} resource(s) imported. Run 'cdkd diff' to see how the imported state lines up with the template.`
|
|
31340
|
+
);
|
|
31341
|
+
} finally {
|
|
31342
|
+
await lockManager.releaseLock(stackInfo.stackName, targetRegion).catch((err) => {
|
|
31343
|
+
logger.warn(`Failed to release lock: ${err instanceof Error ? err.message : String(err)}`);
|
|
31344
|
+
});
|
|
31345
|
+
}
|
|
31346
|
+
} finally {
|
|
31347
|
+
awsClients.destroy();
|
|
31348
|
+
}
|
|
31349
|
+
}
|
|
31350
|
+
async function importOne(task) {
|
|
31351
|
+
const logger = getLogger();
|
|
31352
|
+
const { logicalId, resource, stackName, region, providerRegistry, override } = task;
|
|
31353
|
+
if (!providerRegistry.hasProvider(resource.Type)) {
|
|
31354
|
+
return {
|
|
31355
|
+
logicalId,
|
|
31356
|
+
resourceType: resource.Type,
|
|
31357
|
+
outcome: "skipped-no-impl",
|
|
31358
|
+
reason: "no provider registered"
|
|
31359
|
+
};
|
|
31360
|
+
}
|
|
31361
|
+
const provider = providerRegistry.getProvider(resource.Type);
|
|
31362
|
+
if (!provider.import) {
|
|
31363
|
+
return {
|
|
31364
|
+
logicalId,
|
|
31365
|
+
resourceType: resource.Type,
|
|
31366
|
+
outcome: "skipped-no-impl",
|
|
31367
|
+
reason: `provider does not implement import (yet)`
|
|
31368
|
+
};
|
|
31369
|
+
}
|
|
31370
|
+
const cdkPath = readCdkPath(resource);
|
|
31371
|
+
const input = {
|
|
31372
|
+
logicalId,
|
|
31373
|
+
resourceType: resource.Type,
|
|
31374
|
+
cdkPath,
|
|
31375
|
+
stackName,
|
|
31376
|
+
region,
|
|
31377
|
+
properties: resource.Properties ?? {},
|
|
31378
|
+
...override !== void 0 && { knownPhysicalId: override }
|
|
31379
|
+
};
|
|
31380
|
+
try {
|
|
31381
|
+
const result = await provider.import(input);
|
|
31382
|
+
if (!result) {
|
|
31383
|
+
return {
|
|
31384
|
+
logicalId,
|
|
31385
|
+
resourceType: resource.Type,
|
|
31386
|
+
outcome: "skipped-not-found",
|
|
31387
|
+
reason: "no matching AWS resource"
|
|
31388
|
+
};
|
|
31389
|
+
}
|
|
31390
|
+
return {
|
|
31391
|
+
logicalId,
|
|
31392
|
+
resourceType: resource.Type,
|
|
31393
|
+
outcome: "imported",
|
|
31394
|
+
physicalId: result.physicalId
|
|
31395
|
+
};
|
|
31396
|
+
} catch (error) {
|
|
31397
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
31398
|
+
logger.error(`Failed to import ${logicalId} (${resource.Type}): ${msg}`);
|
|
31399
|
+
return {
|
|
31400
|
+
logicalId,
|
|
31401
|
+
resourceType: resource.Type,
|
|
31402
|
+
outcome: "failed",
|
|
31403
|
+
reason: msg
|
|
31404
|
+
};
|
|
31405
|
+
}
|
|
31406
|
+
}
|
|
31407
|
+
function parseResourceOverrides(flags, mappingFile) {
|
|
31408
|
+
const map = /* @__PURE__ */ new Map();
|
|
31409
|
+
if (mappingFile) {
|
|
31410
|
+
let parsed;
|
|
31411
|
+
try {
|
|
31412
|
+
parsed = JSON.parse(readFileSync5(mappingFile, "utf-8"));
|
|
31413
|
+
} catch (err) {
|
|
31414
|
+
throw new Error(
|
|
31415
|
+
`Failed to read --resource-mapping file '${mappingFile}': ` + (err instanceof Error ? err.message : String(err))
|
|
31416
|
+
);
|
|
31417
|
+
}
|
|
31418
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
31419
|
+
throw new Error(
|
|
31420
|
+
`--resource-mapping file '${mappingFile}' must be a JSON object {logicalId: physicalId}`
|
|
31421
|
+
);
|
|
31422
|
+
}
|
|
31423
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
31424
|
+
if (typeof value !== "string") {
|
|
31425
|
+
throw new Error(
|
|
31426
|
+
`--resource-mapping: value for '${key}' must be a string, got ${typeof value}`
|
|
31427
|
+
);
|
|
31428
|
+
}
|
|
31429
|
+
map.set(key, value);
|
|
31430
|
+
}
|
|
31431
|
+
}
|
|
31432
|
+
for (const entry of flags ?? []) {
|
|
31433
|
+
const eq = entry.indexOf("=");
|
|
31434
|
+
if (eq <= 0 || eq === entry.length - 1) {
|
|
31435
|
+
throw new Error(`--resource expects 'logicalId=physicalId', got '${entry}'`);
|
|
31436
|
+
}
|
|
31437
|
+
map.set(entry.slice(0, eq), entry.slice(eq + 1));
|
|
31438
|
+
}
|
|
31439
|
+
return map;
|
|
31440
|
+
}
|
|
31441
|
+
function readCdkPath(resource) {
|
|
31442
|
+
const meta = resource.Metadata;
|
|
31443
|
+
if (!meta)
|
|
31444
|
+
return "";
|
|
31445
|
+
const v = meta["aws:cdk:path"];
|
|
31446
|
+
return typeof v === "string" ? v : "";
|
|
31447
|
+
}
|
|
31448
|
+
function collectImportableResources(template) {
|
|
31449
|
+
const out = [];
|
|
31450
|
+
for (const [logicalId, resource] of Object.entries(template.Resources)) {
|
|
31451
|
+
if (resource.Type === "AWS::CDK::Metadata")
|
|
31452
|
+
continue;
|
|
31453
|
+
out.push({ logicalId, resource });
|
|
31454
|
+
}
|
|
31455
|
+
return out;
|
|
31456
|
+
}
|
|
31457
|
+
function buildStackState(stackName, region, rows, templateParser, template) {
|
|
31458
|
+
const resources = {};
|
|
31459
|
+
for (const row of rows) {
|
|
31460
|
+
if (row.outcome !== "imported" || !row.physicalId)
|
|
31461
|
+
continue;
|
|
31462
|
+
const tmplResource = template.Resources[row.logicalId];
|
|
31463
|
+
if (!tmplResource)
|
|
31464
|
+
continue;
|
|
31465
|
+
const deps = templateParser.extractDependencies(tmplResource);
|
|
31466
|
+
resources[row.logicalId] = {
|
|
31467
|
+
physicalId: row.physicalId,
|
|
31468
|
+
resourceType: row.resourceType,
|
|
31469
|
+
properties: tmplResource.Properties ?? {},
|
|
31470
|
+
attributes: {},
|
|
31471
|
+
dependencies: [...deps]
|
|
31472
|
+
};
|
|
31473
|
+
}
|
|
31474
|
+
return {
|
|
31475
|
+
version: 2,
|
|
31476
|
+
stackName,
|
|
31477
|
+
region,
|
|
31478
|
+
resources,
|
|
31479
|
+
outputs: {},
|
|
31480
|
+
lastModified: Date.now()
|
|
31481
|
+
};
|
|
31482
|
+
}
|
|
31483
|
+
function printSummary(rows) {
|
|
31484
|
+
const logger = getLogger();
|
|
31485
|
+
const counts = {
|
|
31486
|
+
imported: 0,
|
|
31487
|
+
"skipped-no-impl": 0,
|
|
31488
|
+
"skipped-not-found": 0,
|
|
31489
|
+
failed: 0
|
|
31490
|
+
};
|
|
31491
|
+
logger.info("");
|
|
31492
|
+
logger.info("Import plan:");
|
|
31493
|
+
for (const r of rows) {
|
|
31494
|
+
counts[r.outcome]++;
|
|
31495
|
+
const tag = formatOutcome(r.outcome);
|
|
31496
|
+
const detail = r.outcome === "imported" ? ` (${r.physicalId})` : r.reason ? ` \u2014 ${r.reason}` : "";
|
|
31497
|
+
logger.info(` ${tag} ${r.logicalId} (${r.resourceType})${detail}`);
|
|
31498
|
+
}
|
|
31499
|
+
logger.info("");
|
|
31500
|
+
logger.info(
|
|
31501
|
+
`Summary: ${counts.imported} imported, ${counts["skipped-not-found"]} not found, ${counts["skipped-no-impl"]} unsupported, ${counts.failed} failed`
|
|
31502
|
+
);
|
|
31503
|
+
}
|
|
31504
|
+
function formatOutcome(outcome) {
|
|
31505
|
+
switch (outcome) {
|
|
31506
|
+
case "imported":
|
|
31507
|
+
return "\u2713";
|
|
31508
|
+
case "skipped-not-found":
|
|
31509
|
+
return "\xB7";
|
|
31510
|
+
case "skipped-no-impl":
|
|
31511
|
+
return "?";
|
|
31512
|
+
case "failed":
|
|
31513
|
+
return "\u2717";
|
|
31514
|
+
}
|
|
31515
|
+
}
|
|
31516
|
+
async function confirmPrompt2(prompt) {
|
|
31517
|
+
const rl = readline4.createInterface({ input: process.stdin, output: process.stdout });
|
|
31518
|
+
try {
|
|
31519
|
+
const ans = await rl.question(`${prompt} [y/N] `);
|
|
31520
|
+
return /^y(es)?$/i.test(ans.trim());
|
|
31521
|
+
} finally {
|
|
31522
|
+
rl.close();
|
|
31523
|
+
}
|
|
31524
|
+
}
|
|
31525
|
+
function createImportCommand() {
|
|
31526
|
+
const cmd = new Command11("import").description(
|
|
31527
|
+
"Adopt already-deployed AWS resources into cdkd state. Reads the CDK app to find logical IDs, resource types, and dependencies; uses the aws:cdk:path tag (or explicit --resource overrides) to find each resource in AWS."
|
|
31528
|
+
).argument(
|
|
31529
|
+
"[stack]",
|
|
31530
|
+
"Stack to import. Optional when the synthesized app contains exactly one stack."
|
|
31531
|
+
).option(
|
|
31532
|
+
"--resource <id=physical>",
|
|
31533
|
+
"Explicit physical-id override for one logical ID. Repeatable. Bypasses tag-based auto-lookup for that resource only.",
|
|
31534
|
+
collectMultiple,
|
|
31535
|
+
[]
|
|
31536
|
+
).option(
|
|
31537
|
+
"--resource-mapping <file>",
|
|
31538
|
+
"Path to a JSON file of {logicalId: physicalId} overrides (CDK CLI `cdk import --resource-mapping` compatible)."
|
|
31539
|
+
).option("--dry-run", "Show planned imports without writing state", false).option(
|
|
31540
|
+
"--force",
|
|
31541
|
+
"Overwrite an existing state record. Without this, an existing state file aborts the import.",
|
|
31542
|
+
false
|
|
31543
|
+
).action(withErrorHandling(importCommand));
|
|
31544
|
+
[...commonOptions, ...appOptions, ...stateOptions, ...contextOptions].forEach(
|
|
31545
|
+
(o) => cmd.addOption(o)
|
|
31546
|
+
);
|
|
31547
|
+
return cmd;
|
|
31548
|
+
}
|
|
31549
|
+
function collectMultiple(value, previous) {
|
|
31550
|
+
return [...previous ?? [], value];
|
|
31551
|
+
}
|
|
31552
|
+
|
|
30560
31553
|
// src/cli/index.ts
|
|
30561
31554
|
var SUBCOMMANDS = /* @__PURE__ */ new Set([
|
|
30562
31555
|
"bootstrap",
|
|
@@ -30566,6 +31559,7 @@ var SUBCOMMANDS = /* @__PURE__ */ new Set([
|
|
|
30566
31559
|
"deploy",
|
|
30567
31560
|
"diff",
|
|
30568
31561
|
"destroy",
|
|
31562
|
+
"import",
|
|
30569
31563
|
"publish-assets",
|
|
30570
31564
|
"force-unlock",
|
|
30571
31565
|
"state"
|
|
@@ -30581,14 +31575,15 @@ function reorderArgs(argv) {
|
|
|
30581
31575
|
return [...prefix, ...cmdAndAfter, ...beforeCmd];
|
|
30582
31576
|
}
|
|
30583
31577
|
async function main() {
|
|
30584
|
-
const program = new
|
|
30585
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.
|
|
31578
|
+
const program = new Command12();
|
|
31579
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.15.0");
|
|
30586
31580
|
program.addCommand(createBootstrapCommand());
|
|
30587
31581
|
program.addCommand(createSynthCommand());
|
|
30588
31582
|
program.addCommand(createListCommand());
|
|
30589
31583
|
program.addCommand(createDeployCommand());
|
|
30590
31584
|
program.addCommand(createDiffCommand());
|
|
30591
31585
|
program.addCommand(createDestroyCommand());
|
|
31586
|
+
program.addCommand(createImportCommand());
|
|
30592
31587
|
program.addCommand(createPublishAssetsCommand());
|
|
30593
31588
|
program.addCommand(createForceUnlockCommand());
|
|
30594
31589
|
program.addCommand(createStateCommand());
|