@go-to-k/cdkd 0.16.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1008,11 +1008,27 @@ async function resolveStateBucketWithDefaultAndSource(cliBucket, region) {
1008
1008
  const legacyName = getLegacyStateBucketName(accountId, region);
1009
1009
  const probe = new S3Client11({ region: "us-east-1" });
1010
1010
  try {
1011
- if (await bucketExists(probe, newName)) {
1011
+ const newExists = await bucketExists(probe, newName);
1012
+ const legacyExists = await bucketExists(probe, legacyName);
1013
+ if (newExists && legacyExists) {
1014
+ const newHasState = await bucketHasAnyState(probe, newName);
1015
+ if (!newHasState) {
1016
+ const legacyHasState = await bucketHasAnyState(probe, legacyName);
1017
+ if (legacyHasState) {
1018
+ logger.warn(
1019
+ `Both '${newName}' (new default) and '${legacyName}' (legacy default) exist, but the new bucket is empty and the legacy one has state. Reading from legacy. Run \`cdkd state migrate --region ${region}\` to copy the state into the new bucket and stop seeing this warning.`
1020
+ );
1021
+ return { bucket: legacyName, source: "default-legacy" };
1022
+ }
1023
+ }
1012
1024
  logger.debug(`State bucket: ${newName}`);
1013
1025
  return { bucket: newName, source: "default" };
1014
1026
  }
1015
- if (await bucketExists(probe, legacyName)) {
1027
+ if (newExists) {
1028
+ logger.debug(`State bucket: ${newName}`);
1029
+ return { bucket: newName, source: "default" };
1030
+ }
1031
+ if (legacyExists) {
1016
1032
  logger.warn(
1017
1033
  `Using legacy state bucket name '${legacyName}'. The default has changed to '${newName}'. To migrate, run:
1018
1034
 
@@ -1029,6 +1045,21 @@ async function resolveStateBucketWithDefaultAndSource(cliBucket, region) {
1029
1045
  probe.destroy();
1030
1046
  }
1031
1047
  }
1048
+ async function bucketHasAnyState(client, bucketName) {
1049
+ const { ListObjectsV2Command: ListObjectsV2Command5 } = await import("@aws-sdk/client-s3");
1050
+ try {
1051
+ const resp = await client.send(
1052
+ new ListObjectsV2Command5({
1053
+ Bucket: bucketName,
1054
+ Prefix: "cdkd/",
1055
+ MaxKeys: 1
1056
+ })
1057
+ );
1058
+ return (resp.KeyCount ?? 0) > 0;
1059
+ } catch {
1060
+ return true;
1061
+ }
1062
+ }
1032
1063
  async function bucketExists(client, bucketName) {
1033
1064
  const { HeadBucketCommand: HeadBucketCommand5 } = await import("@aws-sdk/client-s3");
1034
1065
  try {
@@ -17482,6 +17513,85 @@ var EC2Provider = class {
17482
17513
  const name = error.name ?? "";
17483
17514
  return message.includes("not found") || message.includes("does not exist") || message.includes("invalidparametervalue") || name === "InvalidVpcID.NotFound" || name === "InvalidSubnetID.NotFound" || name === "InvalidInternetGatewayID.NotFound" || name === "InvalidRouteTableID.NotFound" || name === "InvalidGroup.NotFound" || name === "InvalidAssociationID.NotFound" || name === "InvalidRoute.NotFound" || name === "InvalidInstanceID.NotFound" || name === "InvalidNetworkAclID.NotFound" || name === "InvalidNetworkAclEntry.NotFound";
17484
17515
  }
17516
+ /**
17517
+ * Adopt an existing EC2 networking resource into cdkd state.
17518
+ *
17519
+ * Supported types: `AWS::EC2::VPC`, `AWS::EC2::Subnet`,
17520
+ * `AWS::EC2::SecurityGroup`. Other EC2 types this provider creates
17521
+ * (RouteTable, Route, InternetGateway, VPCGatewayAttachment,
17522
+ * NetworkAcl, Instance) return `null` from import — most have no
17523
+ * stable identity to look up by tag (Routes are derived; SGIngress
17524
+ * is rule-level), and the typical adoption story is "find the VPC,
17525
+ * cdkd reconstructs the rest at deploy time".
17526
+ *
17527
+ * EC2 supports `Filters: [{Name: 'tag:aws:cdk:path', Values: [path]}]`
17528
+ * directly on `Describe*`, so the lookup is one API call per type.
17529
+ */
17530
+ async import(input) {
17531
+ if (input.knownPhysicalId) {
17532
+ return this.verifyExplicit(input.resourceType, input.knownPhysicalId);
17533
+ }
17534
+ if (!input.cdkPath)
17535
+ return null;
17536
+ const tagFilter = { Name: `tag:${CDK_PATH_TAG}`, Values: [input.cdkPath] };
17537
+ try {
17538
+ switch (input.resourceType) {
17539
+ case "AWS::EC2::VPC": {
17540
+ const resp = await this.ec2Client.send(new DescribeVpcsCommand2({ Filters: [tagFilter] }));
17541
+ const vpc = resp.Vpcs?.[0];
17542
+ return vpc?.VpcId ? { physicalId: vpc.VpcId, attributes: {} } : null;
17543
+ }
17544
+ case "AWS::EC2::Subnet": {
17545
+ const resp = await this.ec2Client.send(
17546
+ new DescribeSubnetsCommand2({ Filters: [tagFilter] })
17547
+ );
17548
+ const subnet = resp.Subnets?.[0];
17549
+ return subnet?.SubnetId ? { physicalId: subnet.SubnetId, attributes: {} } : null;
17550
+ }
17551
+ case "AWS::EC2::SecurityGroup": {
17552
+ const resp = await this.ec2Client.send(
17553
+ new DescribeSecurityGroupsCommand2({ Filters: [tagFilter] })
17554
+ );
17555
+ const sg = resp.SecurityGroups?.[0];
17556
+ return sg?.GroupId ? { physicalId: sg.GroupId, attributes: {} } : null;
17557
+ }
17558
+ default:
17559
+ return null;
17560
+ }
17561
+ } catch (error) {
17562
+ if (this.isNotFoundError(error))
17563
+ return null;
17564
+ throw error;
17565
+ }
17566
+ }
17567
+ async verifyExplicit(resourceType, physicalId) {
17568
+ try {
17569
+ switch (resourceType) {
17570
+ case "AWS::EC2::VPC": {
17571
+ const resp = await this.ec2Client.send(new DescribeVpcsCommand2({ VpcIds: [physicalId] }));
17572
+ return resp.Vpcs?.[0] ? { physicalId, attributes: {} } : null;
17573
+ }
17574
+ case "AWS::EC2::Subnet": {
17575
+ const resp = await this.ec2Client.send(
17576
+ new DescribeSubnetsCommand2({ SubnetIds: [physicalId] })
17577
+ );
17578
+ return resp.Subnets?.[0] ? { physicalId, attributes: {} } : null;
17579
+ }
17580
+ case "AWS::EC2::SecurityGroup": {
17581
+ const resp = await this.ec2Client.send(
17582
+ new DescribeSecurityGroupsCommand2({ GroupIds: [physicalId] })
17583
+ );
17584
+ return resp.SecurityGroups?.[0] ? { physicalId, attributes: {} } : null;
17585
+ }
17586
+ default:
17587
+ return null;
17588
+ }
17589
+ } catch (error) {
17590
+ if (this.isNotFoundError(error))
17591
+ return null;
17592
+ throw error;
17593
+ }
17594
+ }
17485
17595
  };
17486
17596
 
17487
17597
  // src/provisioning/providers/apigateway-provider.ts
@@ -18486,6 +18596,32 @@ var ApiGatewayProvider = class _ApiGatewayProvider {
18486
18596
  }
18487
18597
  return result;
18488
18598
  }
18599
+ /**
18600
+ * Adopt an existing API Gateway sub-resource into cdkd state.
18601
+ *
18602
+ * **Explicit override only.** API Gateway sub-resources (Authorizer,
18603
+ * Resource, Deployment, Stage, Method) live under a parent `RestApi`,
18604
+ * and their physical ids are not globally unique — they're scoped
18605
+ * `<restApiId>/<sub-id>`. Auto-lookup by `aws:cdk:path` would need to
18606
+ * walk every RestApi in the account, then every sub-resource within
18607
+ * each, which is impractical and error-prone.
18608
+ *
18609
+ * `AWS::ApiGateway::RestApi` itself is handled by the Cloud Control
18610
+ * API fallback (also explicit-override only — see
18611
+ * `cloud-control-provider.ts`).
18612
+ *
18613
+ * Users adopting an existing API Gateway should pass
18614
+ * `--resource <logicalId>=<physicalId>` for each sub-resource; the
18615
+ * physical id format follows what `create()` returns for the same
18616
+ * type (e.g. `<restApiId>|<resourceId>` for `AWS::ApiGateway::Resource`).
18617
+ */
18618
+ // eslint-disable-next-line @typescript-eslint/require-await -- explicit-override-only intentionally has no AWS calls
18619
+ async import(input) {
18620
+ if (input.knownPhysicalId) {
18621
+ return { physicalId: input.knownPhysicalId, attributes: {} };
18622
+ }
18623
+ return null;
18624
+ }
18489
18625
  };
18490
18626
 
18491
18627
  // src/provisioning/providers/apigatewayv2-provider.ts
@@ -19206,6 +19342,8 @@ import {
19206
19342
  DeleteDistributionCommand,
19207
19343
  GetDistributionCommand,
19208
19344
  GetDistributionConfigCommand,
19345
+ ListDistributionsCommand,
19346
+ ListTagsForResourceCommand as ListTagsForResourceCommand5,
19209
19347
  NoSuchDistribution
19210
19348
  } from "@aws-sdk/client-cloudfront";
19211
19349
  init_aws_clients();
@@ -19610,6 +19748,52 @@ var CloudFrontDistributionProvider = class {
19610
19748
  this.applyQuantityAtPath(nested, rest);
19611
19749
  }
19612
19750
  }
19751
+ /**
19752
+ * Adopt an existing CloudFront distribution into cdkd state.
19753
+ *
19754
+ * CloudFront distributions don't carry a template-supplied name
19755
+ * (physical id is the AWS-generated `E...` distribution id), so the
19756
+ * lookup is either explicit-override or `aws:cdk:path` tag match
19757
+ * via `ListDistributions` + `ListTagsForResource(ARN)`.
19758
+ */
19759
+ async import(input) {
19760
+ if (input.knownPhysicalId) {
19761
+ try {
19762
+ await this.cloudFrontClient.send(new GetDistributionCommand({ Id: input.knownPhysicalId }));
19763
+ return { physicalId: input.knownPhysicalId, attributes: {} };
19764
+ } catch (err) {
19765
+ if (err instanceof NoSuchDistribution)
19766
+ return null;
19767
+ throw err;
19768
+ }
19769
+ }
19770
+ if (!input.cdkPath)
19771
+ return null;
19772
+ let marker;
19773
+ do {
19774
+ const list = await this.cloudFrontClient.send(
19775
+ new ListDistributionsCommand({ ...marker && { Marker: marker } })
19776
+ );
19777
+ for (const d of list.DistributionList?.Items ?? []) {
19778
+ if (!d.Id || !d.ARN)
19779
+ continue;
19780
+ try {
19781
+ const tagsResp = await this.cloudFrontClient.send(
19782
+ new ListTagsForResourceCommand5({ Resource: d.ARN })
19783
+ );
19784
+ if (matchesCdkPath(tagsResp.Tags?.Items, input.cdkPath)) {
19785
+ return { physicalId: d.Id, attributes: {} };
19786
+ }
19787
+ } catch (err) {
19788
+ if (err instanceof NoSuchDistribution)
19789
+ continue;
19790
+ throw err;
19791
+ }
19792
+ }
19793
+ marker = list.DistributionList?.IsTruncated ? list.DistributionList?.NextMarker : void 0;
19794
+ } while (marker);
19795
+ return null;
19796
+ }
19613
19797
  };
19614
19798
 
19615
19799
  // src/provisioning/providers/agentcore-runtime-provider.ts
@@ -20099,7 +20283,10 @@ import {
20099
20283
  CreateServiceCommand,
20100
20284
  UpdateServiceCommand,
20101
20285
  DeleteServiceCommand,
20102
- DescribeServicesCommand
20286
+ DescribeServicesCommand,
20287
+ ListClustersCommand,
20288
+ ListServicesCommand,
20289
+ ListTagsForResourceCommand as ListTagsForResourceCommand6
20103
20290
  } from "@aws-sdk/client-ecs";
20104
20291
  function convertTags(tags) {
20105
20292
  if (!tags || tags.length === 0)
@@ -20828,6 +21015,128 @@ var ECSProvider = class {
20828
21015
  }
20829
21016
  return false;
20830
21017
  }
21018
+ /**
21019
+ * Adopt an existing ECS resource into cdkd state.
21020
+ *
21021
+ * Supported types: `AWS::ECS::Cluster`, `AWS::ECS::Service`,
21022
+ * `AWS::ECS::TaskDefinition`. ECS uses lowercase `key`/`value` tags
21023
+ * (vs the standard CFn `Key`/`Value`), so the standard
21024
+ * `matchesCdkPath` helper doesn't apply — match the tag manually.
21025
+ *
21026
+ * Service has a composite physical id of `<clusterArn>|<serviceName>`
21027
+ * (the form ECSProvider uses internally for mutation operations),
21028
+ * so the explicit-override path takes that composite form when
21029
+ * supplied.
21030
+ */
21031
+ async import(input) {
21032
+ switch (input.resourceType) {
21033
+ case "AWS::ECS::Cluster":
21034
+ return this.importCluster(input);
21035
+ case "AWS::ECS::Service":
21036
+ return this.importService(input);
21037
+ case "AWS::ECS::TaskDefinition":
21038
+ return this.importTaskDefinition(input);
21039
+ default:
21040
+ return null;
21041
+ }
21042
+ }
21043
+ async importCluster(input) {
21044
+ const explicit = resolveExplicitPhysicalId(input, "ClusterName");
21045
+ if (explicit) {
21046
+ try {
21047
+ const resp = await this.getClient().send(
21048
+ new DescribeClustersCommand({ clusters: [explicit] })
21049
+ );
21050
+ return resp.clusters?.[0]?.clusterName ? { physicalId: resp.clusters[0].clusterName, attributes: {} } : null;
21051
+ } catch (err) {
21052
+ if (this.isClusterNotFoundException(err) || this.isServiceNotFoundException(err)) {
21053
+ return null;
21054
+ }
21055
+ throw err;
21056
+ }
21057
+ }
21058
+ if (!input.cdkPath)
21059
+ return null;
21060
+ let nextToken;
21061
+ do {
21062
+ const list = await this.getClient().send(
21063
+ new ListClustersCommand({ ...nextToken && { nextToken } })
21064
+ );
21065
+ for (const arn of list.clusterArns ?? []) {
21066
+ const tagsResp = await this.getClient().send(
21067
+ new ListTagsForResourceCommand6({ resourceArn: arn })
21068
+ );
21069
+ if (this.tagsMatchCdkPath(tagsResp.tags, input.cdkPath)) {
21070
+ const name = arn.substring(arn.lastIndexOf("/") + 1);
21071
+ return { physicalId: name, attributes: {} };
21072
+ }
21073
+ }
21074
+ nextToken = list.nextToken;
21075
+ } while (nextToken);
21076
+ return null;
21077
+ }
21078
+ async importService(input) {
21079
+ if (input.knownPhysicalId) {
21080
+ return { physicalId: input.knownPhysicalId, attributes: {} };
21081
+ }
21082
+ if (!input.cdkPath)
21083
+ return null;
21084
+ let clusterToken;
21085
+ do {
21086
+ const clusterList = await this.getClient().send(
21087
+ new ListClustersCommand({ ...clusterToken && { nextToken: clusterToken } })
21088
+ );
21089
+ for (const clusterArn of clusterList.clusterArns ?? []) {
21090
+ let svcToken;
21091
+ do {
21092
+ const svcList = await this.getClient().send(
21093
+ new ListServicesCommand({
21094
+ cluster: clusterArn,
21095
+ ...svcToken && { nextToken: svcToken }
21096
+ })
21097
+ );
21098
+ for (const svcArn of svcList.serviceArns ?? []) {
21099
+ const tagsResp = await this.getClient().send(
21100
+ new ListTagsForResourceCommand6({ resourceArn: svcArn })
21101
+ );
21102
+ if (this.tagsMatchCdkPath(tagsResp.tags, input.cdkPath)) {
21103
+ const svcName = svcArn.substring(svcArn.lastIndexOf("/") + 1);
21104
+ return { physicalId: `${clusterArn}|${svcName}`, attributes: {} };
21105
+ }
21106
+ }
21107
+ svcToken = svcList.nextToken;
21108
+ } while (svcToken);
21109
+ }
21110
+ clusterToken = clusterList.nextToken;
21111
+ } while (clusterToken);
21112
+ return null;
21113
+ }
21114
+ async importTaskDefinition(input) {
21115
+ if (input.knownPhysicalId) {
21116
+ try {
21117
+ const resp = await this.getClient().send(
21118
+ new DescribeTaskDefinitionCommand({ taskDefinition: input.knownPhysicalId })
21119
+ );
21120
+ const arn = resp.taskDefinition?.taskDefinitionArn;
21121
+ return arn ? { physicalId: arn, attributes: {} } : null;
21122
+ } catch (err) {
21123
+ if (this.isClusterNotFoundException(err) || this.isServiceNotFoundException(err)) {
21124
+ return null;
21125
+ }
21126
+ throw err;
21127
+ }
21128
+ }
21129
+ return null;
21130
+ }
21131
+ tagsMatchCdkPath(tags, cdkPath) {
21132
+ if (!tags)
21133
+ return false;
21134
+ for (const t of tags) {
21135
+ if (t.key === "aws:cdk:path" && t.value === cdkPath)
21136
+ return true;
21137
+ }
21138
+ return false;
21139
+ }
20831
21140
  };
20832
21141
 
20833
21142
  // src/provisioning/providers/elbv2-provider.ts
@@ -21360,7 +21669,9 @@ import {
21360
21669
  DescribeDBInstancesCommand,
21361
21670
  CreateDBSubnetGroupCommand,
21362
21671
  DeleteDBSubnetGroupCommand,
21363
- ModifyDBSubnetGroupCommand
21672
+ DescribeDBSubnetGroupsCommand,
21673
+ ModifyDBSubnetGroupCommand,
21674
+ ListTagsForResourceCommand as ListTagsForResourceCommand7
21364
21675
  } from "@aws-sdk/client-rds";
21365
21676
  var RDSProvider = class {
21366
21677
  rdsClient;
@@ -21954,6 +22265,133 @@ var RDSProvider = class {
21954
22265
  sleep(ms) {
21955
22266
  return new Promise((resolve4) => setTimeout(resolve4, ms));
21956
22267
  }
22268
+ /**
22269
+ * Adopt an existing RDS resource into cdkd state.
22270
+ *
22271
+ * Supported types: `AWS::RDS::DBInstance`, `AWS::RDS::DBCluster`,
22272
+ * `AWS::RDS::DBSubnetGroup`. Identifier name properties (`DBInstance
22273
+ * Identifier` / `DBClusterIdentifier` / `DBSubnetGroupName`) are
22274
+ * usually present in CDK templates; fall back to `aws:cdk:path` tag
22275
+ * lookup via the corresponding `Describe*` + `ListTagsForResource`
22276
+ * pair otherwise.
22277
+ */
22278
+ async import(input) {
22279
+ switch (input.resourceType) {
22280
+ case "AWS::RDS::DBInstance":
22281
+ return this.importDBInstance(input);
22282
+ case "AWS::RDS::DBCluster":
22283
+ return this.importDBCluster(input);
22284
+ case "AWS::RDS::DBSubnetGroup":
22285
+ return this.importDBSubnetGroup(input);
22286
+ default:
22287
+ return null;
22288
+ }
22289
+ }
22290
+ async importDBInstance(input) {
22291
+ const explicit = resolveExplicitPhysicalId(input, "DBInstanceIdentifier");
22292
+ if (explicit) {
22293
+ try {
22294
+ await this.getClient().send(
22295
+ new DescribeDBInstancesCommand({ DBInstanceIdentifier: explicit })
22296
+ );
22297
+ return { physicalId: explicit, attributes: {} };
22298
+ } catch (err) {
22299
+ if (err.name === "DBInstanceNotFoundFault")
22300
+ return null;
22301
+ throw err;
22302
+ }
22303
+ }
22304
+ if (!input.cdkPath)
22305
+ return null;
22306
+ let marker;
22307
+ do {
22308
+ const list = await this.getClient().send(
22309
+ new DescribeDBInstancesCommand({ ...marker && { Marker: marker } })
22310
+ );
22311
+ for (const inst of list.DBInstances ?? []) {
22312
+ if (!inst.DBInstanceIdentifier || !inst.DBInstanceArn)
22313
+ continue;
22314
+ const tagsResp = await this.getClient().send(
22315
+ new ListTagsForResourceCommand7({ ResourceName: inst.DBInstanceArn })
22316
+ );
22317
+ if (matchesCdkPath(tagsResp.TagList, input.cdkPath)) {
22318
+ return { physicalId: inst.DBInstanceIdentifier, attributes: {} };
22319
+ }
22320
+ }
22321
+ marker = list.Marker;
22322
+ } while (marker);
22323
+ return null;
22324
+ }
22325
+ async importDBCluster(input) {
22326
+ const explicit = resolveExplicitPhysicalId(input, "DBClusterIdentifier");
22327
+ if (explicit) {
22328
+ try {
22329
+ await this.getClient().send(
22330
+ new DescribeDBClustersCommand({ DBClusterIdentifier: explicit })
22331
+ );
22332
+ return { physicalId: explicit, attributes: {} };
22333
+ } catch (err) {
22334
+ if (err.name === "DBClusterNotFoundFault")
22335
+ return null;
22336
+ throw err;
22337
+ }
22338
+ }
22339
+ if (!input.cdkPath)
22340
+ return null;
22341
+ let marker;
22342
+ do {
22343
+ const list = await this.getClient().send(
22344
+ new DescribeDBClustersCommand({ ...marker && { Marker: marker } })
22345
+ );
22346
+ for (const c of list.DBClusters ?? []) {
22347
+ if (!c.DBClusterIdentifier || !c.DBClusterArn)
22348
+ continue;
22349
+ const tagsResp = await this.getClient().send(
22350
+ new ListTagsForResourceCommand7({ ResourceName: c.DBClusterArn })
22351
+ );
22352
+ if (matchesCdkPath(tagsResp.TagList, input.cdkPath)) {
22353
+ return { physicalId: c.DBClusterIdentifier, attributes: {} };
22354
+ }
22355
+ }
22356
+ marker = list.Marker;
22357
+ } while (marker);
22358
+ return null;
22359
+ }
22360
+ async importDBSubnetGroup(input) {
22361
+ const explicit = resolveExplicitPhysicalId(input, "DBSubnetGroupName");
22362
+ if (explicit) {
22363
+ try {
22364
+ await this.getClient().send(
22365
+ new DescribeDBSubnetGroupsCommand({ DBSubnetGroupName: explicit })
22366
+ );
22367
+ return { physicalId: explicit, attributes: {} };
22368
+ } catch (err) {
22369
+ if (err.name === "DBSubnetGroupNotFoundFault")
22370
+ return null;
22371
+ throw err;
22372
+ }
22373
+ }
22374
+ if (!input.cdkPath)
22375
+ return null;
22376
+ let marker;
22377
+ do {
22378
+ const list = await this.getClient().send(
22379
+ new DescribeDBSubnetGroupsCommand({ ...marker && { Marker: marker } })
22380
+ );
22381
+ for (const sg of list.DBSubnetGroups ?? []) {
22382
+ if (!sg.DBSubnetGroupName || !sg.DBSubnetGroupArn)
22383
+ continue;
22384
+ const tagsResp = await this.getClient().send(
22385
+ new ListTagsForResourceCommand7({ ResourceName: sg.DBSubnetGroupArn })
22386
+ );
22387
+ if (matchesCdkPath(tagsResp.TagList, input.cdkPath)) {
22388
+ return { physicalId: sg.DBSubnetGroupName, attributes: {} };
22389
+ }
22390
+ }
22391
+ marker = list.Marker;
22392
+ } while (marker);
22393
+ return null;
22394
+ }
21957
22395
  };
21958
22396
 
21959
22397
  // src/provisioning/providers/route53-provider.ts
@@ -22849,6 +23287,8 @@ import {
22849
23287
  DeleteUserPoolCommand,
22850
23288
  UpdateUserPoolCommand,
22851
23289
  DescribeUserPoolCommand,
23290
+ ListUserPoolsCommand,
23291
+ ListTagsForResourceCommand as ListTagsForResourceCommand8,
22852
23292
  ResourceNotFoundException as ResourceNotFoundException12
22853
23293
  } from "@aws-sdk/client-cognito-identity-provider";
22854
23294
  var CognitoUserPoolProvider = class {
@@ -23184,6 +23624,71 @@ var CognitoUserPoolProvider = class {
23184
23624
  );
23185
23625
  }
23186
23626
  }
23627
+ /**
23628
+ * Adopt an existing Cognito User Pool into cdkd state.
23629
+ *
23630
+ * User Pool physical id is the AWS-generated `<region>_<random>` id.
23631
+ * Lookup chain:
23632
+ * 1. `--resource` override → `DescribeUserPool` to verify.
23633
+ * 2. `Properties.UserPoolName` (when CDK template carries it) →
23634
+ * `ListUserPools` walk + name match.
23635
+ * 3. `aws:cdk:path` tag match via `ListUserPools` +
23636
+ * `ListTagsForResource(<arn>)`. Cognito's tag map uses the same
23637
+ * `Tags: { [key]: value }` shape as Lambda.
23638
+ */
23639
+ async import(input) {
23640
+ if (input.knownPhysicalId) {
23641
+ try {
23642
+ await this.getClient().send(
23643
+ new DescribeUserPoolCommand({ UserPoolId: input.knownPhysicalId })
23644
+ );
23645
+ return { physicalId: input.knownPhysicalId, attributes: {} };
23646
+ } catch (err) {
23647
+ if (err instanceof ResourceNotFoundException12)
23648
+ return null;
23649
+ throw err;
23650
+ }
23651
+ }
23652
+ const desiredName = typeof input.properties?.["UserPoolName"] === "string" ? input.properties["UserPoolName"] : void 0;
23653
+ let nextToken;
23654
+ do {
23655
+ const list = await this.getClient().send(
23656
+ new ListUserPoolsCommand({
23657
+ MaxResults: 60,
23658
+ ...nextToken && { NextToken: nextToken }
23659
+ })
23660
+ );
23661
+ for (const pool of list.UserPools ?? []) {
23662
+ if (!pool.Id)
23663
+ continue;
23664
+ if (desiredName && pool.Name === desiredName) {
23665
+ return { physicalId: pool.Id, attributes: {} };
23666
+ }
23667
+ if (input.cdkPath) {
23668
+ try {
23669
+ const desc = await this.getClient().send(
23670
+ new DescribeUserPoolCommand({ UserPoolId: pool.Id })
23671
+ );
23672
+ const arn = desc.UserPool?.Arn;
23673
+ if (!arn)
23674
+ continue;
23675
+ const tagsResp = await this.getClient().send(
23676
+ new ListTagsForResourceCommand8({ ResourceArn: arn })
23677
+ );
23678
+ if (tagsResp.Tags?.[CDK_PATH_TAG] === input.cdkPath) {
23679
+ return { physicalId: pool.Id, attributes: {} };
23680
+ }
23681
+ } catch (err) {
23682
+ if (err instanceof ResourceNotFoundException12)
23683
+ continue;
23684
+ throw err;
23685
+ }
23686
+ }
23687
+ }
23688
+ nextToken = list.NextToken;
23689
+ } while (nextToken);
23690
+ return null;
23691
+ }
23187
23692
  };
23188
23693
 
23189
23694
  // src/provisioning/providers/elasticache-provider.ts
@@ -31630,7 +32135,7 @@ function reorderArgs(argv) {
31630
32135
  }
31631
32136
  async function main() {
31632
32137
  const program = new Command12();
31633
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.16.0");
32138
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.17.0");
31634
32139
  program.addCommand(createBootstrapCommand());
31635
32140
  program.addCommand(createSynthCommand());
31636
32141
  program.addCommand(createListCommand());