@go-to-k/cdkd 0.51.5 → 0.51.6

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
@@ -21780,10 +21780,13 @@ var EC2Provider = class {
21780
21780
  * **AWS::EC2::SecurityGroupIngress**, **AWS::EC2::NetworkAclEntry**,
21781
21781
  * **AWS::EC2::SubnetNetworkAclAssociation**: rule / association
21782
21782
  * sub-resources whose AWS API surfaces them inside the parent's
21783
- * list, not as standalone Get* responses. v1 drift coverage focuses
21784
- * on top-level resources where the property shape comparison is
21785
- * cheap and unambiguous; these sub-resources need a more elaborate
21786
- * extraction layer that's out of scope for this PR.
21783
+ * `Describe*` list response, not as standalone `Get*` calls. cdkd
21784
+ * parses the physicalId to recover the parent id + entry-key, then
21785
+ * walks the parent's response to find the matching entry and
21786
+ * reverse-maps it to CFn property shape. `SecurityGroupIngress` uses
21787
+ * state's full rule signature (when passed via the optional
21788
+ * `properties` arg) to disambiguate among multiple AWS rules
21789
+ * sharing the same `(group, protocol, ports)` tuple.
21787
21790
  *
21788
21791
  * Returns `undefined` when the resource is gone (any `*NotFound` /
21789
21792
  * `Invalid*` error from the EC2 SDK matches `isNotFoundError`).
@@ -21807,6 +21810,18 @@ var EC2Provider = class {
21807
21810
  return await this.readInstanceCurrentState(physicalId);
21808
21811
  case "AWS::EC2::NetworkAcl":
21809
21812
  return await this.readNetworkAclCurrentState(physicalId);
21813
+ case "AWS::EC2::VPCGatewayAttachment":
21814
+ return await this.readVpcGatewayAttachmentCurrentState(physicalId);
21815
+ case "AWS::EC2::Route":
21816
+ return await this.readRouteCurrentState(physicalId);
21817
+ case "AWS::EC2::SubnetRouteTableAssociation":
21818
+ return await this.readSubnetRouteTableAssociationCurrentState(physicalId);
21819
+ case "AWS::EC2::SecurityGroupIngress":
21820
+ return await this.readSecurityGroupIngressCurrentState(physicalId, properties);
21821
+ case "AWS::EC2::NetworkAclEntry":
21822
+ return await this.readNetworkAclEntryCurrentState(physicalId);
21823
+ case "AWS::EC2::SubnetNetworkAclAssociation":
21824
+ return await this.readSubnetNetworkAclAssociationCurrentState(physicalId);
21810
21825
  default:
21811
21826
  this.logger.debug(
21812
21827
  `readCurrentState: unsupported resource type ${resourceType} for ${logicalId}`
@@ -22036,6 +22051,269 @@ var EC2Provider = class {
22036
22051
  result["VpcId"] = acl.VpcId;
22037
22052
  return result;
22038
22053
  }
22054
+ /**
22055
+ * AWS::EC2::VPCGatewayAttachment readCurrentState.
22056
+ *
22057
+ * physicalId format: `<igwId>|<vpcId>` (cdkd `createVpcGatewayAttachment`).
22058
+ * AWS API: `DescribeInternetGateways(igwId)` → walk `Attachments[]` for
22059
+ * the matching `VpcId`. Returns `undefined` when the IGW is gone OR is no
22060
+ * longer attached to the recorded VPC. Both fields are immutable on this
22061
+ * resource — drift signal is binary (exists / gone) plus VpcId mismatch.
22062
+ */
22063
+ async readVpcGatewayAttachmentCurrentState(physicalId) {
22064
+ const [igwId, vpcId] = physicalId.split("|");
22065
+ if (!igwId || !vpcId)
22066
+ return void 0;
22067
+ const resp = await this.ec2Client.send(
22068
+ new DescribeInternetGatewaysCommand({ InternetGatewayIds: [igwId] })
22069
+ );
22070
+ const igw = resp.InternetGateways?.[0];
22071
+ if (!igw)
22072
+ return void 0;
22073
+ const attached = igw.Attachments?.some((a) => a.VpcId === vpcId);
22074
+ if (!attached)
22075
+ return void 0;
22076
+ return { InternetGatewayId: igwId, VpcId: vpcId };
22077
+ }
22078
+ /**
22079
+ * AWS::EC2::Route readCurrentState.
22080
+ *
22081
+ * physicalId format: `<routeTableId>|<cidr>` where cidr is either v4 or v6.
22082
+ * AWS API: `DescribeRouteTables(routeTableId)` → walk `Routes[]` for the
22083
+ * entry whose `DestinationCidrBlock` or `DestinationIpv6CidrBlock` matches
22084
+ * the cidr. Returns `undefined` when the route table is gone or the route
22085
+ * has been removed.
22086
+ *
22087
+ * Surfaces the target field (`GatewayId` / `NatGatewayId` / `InstanceId` /
22088
+ * `NetworkInterfaceId` / `VpcPeeringConnectionId` / `EgressOnlyInternetGatewayId` /
22089
+ * `TransitGatewayId` / `VpcEndpointId`) AWS reports for that route. Drift
22090
+ * signal: route target changed.
22091
+ */
22092
+ async readRouteCurrentState(physicalId) {
22093
+ const [rtbId, cidr] = physicalId.split("|");
22094
+ if (!rtbId || !cidr)
22095
+ return void 0;
22096
+ const resp = await this.ec2Client.send(
22097
+ new DescribeRouteTablesCommand2({ RouteTableIds: [rtbId] })
22098
+ );
22099
+ const rtb = resp.RouteTables?.[0];
22100
+ if (!rtb)
22101
+ return void 0;
22102
+ const route = rtb.Routes?.find(
22103
+ (r) => r.DestinationCidrBlock === cidr || r.DestinationIpv6CidrBlock === cidr
22104
+ );
22105
+ if (!route)
22106
+ return void 0;
22107
+ const result = { RouteTableId: rtbId };
22108
+ if (route.DestinationCidrBlock !== void 0) {
22109
+ result["DestinationCidrBlock"] = route.DestinationCidrBlock;
22110
+ } else if (route.DestinationIpv6CidrBlock !== void 0) {
22111
+ result["DestinationIpv6CidrBlock"] = route.DestinationIpv6CidrBlock;
22112
+ }
22113
+ if (route.GatewayId !== void 0)
22114
+ result["GatewayId"] = route.GatewayId;
22115
+ if (route.NatGatewayId !== void 0)
22116
+ result["NatGatewayId"] = route.NatGatewayId;
22117
+ if (route.InstanceId !== void 0)
22118
+ result["InstanceId"] = route.InstanceId;
22119
+ if (route.NetworkInterfaceId !== void 0) {
22120
+ result["NetworkInterfaceId"] = route.NetworkInterfaceId;
22121
+ }
22122
+ if (route.VpcPeeringConnectionId !== void 0) {
22123
+ result["VpcPeeringConnectionId"] = route.VpcPeeringConnectionId;
22124
+ }
22125
+ if (route.EgressOnlyInternetGatewayId !== void 0) {
22126
+ result["EgressOnlyInternetGatewayId"] = route.EgressOnlyInternetGatewayId;
22127
+ }
22128
+ if (route.TransitGatewayId !== void 0) {
22129
+ result["TransitGatewayId"] = route.TransitGatewayId;
22130
+ }
22131
+ if (route.LocalGatewayId !== void 0) {
22132
+ result["LocalGatewayId"] = route.LocalGatewayId;
22133
+ }
22134
+ if (route.CarrierGatewayId !== void 0) {
22135
+ result["CarrierGatewayId"] = route.CarrierGatewayId;
22136
+ }
22137
+ if (route.CoreNetworkArn !== void 0) {
22138
+ result["CoreNetworkArn"] = route.CoreNetworkArn;
22139
+ }
22140
+ return result;
22141
+ }
22142
+ /**
22143
+ * AWS::EC2::SubnetRouteTableAssociation readCurrentState.
22144
+ *
22145
+ * physicalId format: `<rtbassoc-xxx>` (returned by `AssociateRouteTable`).
22146
+ * AWS API: `DescribeRouteTables` filtered by `association.route-table-association-id`,
22147
+ * then walk `Associations[]` for the matching entry. Returns `undefined`
22148
+ * when no route table carries the association id.
22149
+ *
22150
+ * Both `SubnetId` and `RouteTableId` are immutable on this resource —
22151
+ * drift signal is binary (exists / gone).
22152
+ */
22153
+ async readSubnetRouteTableAssociationCurrentState(physicalId) {
22154
+ const resp = await this.ec2Client.send(
22155
+ new DescribeRouteTablesCommand2({
22156
+ Filters: [{ Name: "association.route-table-association-id", Values: [physicalId] }]
22157
+ })
22158
+ );
22159
+ for (const rtb of resp.RouteTables ?? []) {
22160
+ const assoc = rtb.Associations?.find((a) => a.RouteTableAssociationId === physicalId);
22161
+ if (assoc) {
22162
+ const result = {};
22163
+ if (assoc.SubnetId !== void 0)
22164
+ result["SubnetId"] = assoc.SubnetId;
22165
+ if (assoc.RouteTableId !== void 0)
22166
+ result["RouteTableId"] = assoc.RouteTableId;
22167
+ return result;
22168
+ }
22169
+ }
22170
+ return void 0;
22171
+ }
22172
+ /**
22173
+ * AWS::EC2::SecurityGroupIngress (standalone) readCurrentState.
22174
+ *
22175
+ * physicalId format: `<groupId>|<protocol>|<fromPort>|<toPort>` (cdkd
22176
+ * `createSecurityGroupIngress`). The same tuple can identify multiple
22177
+ * AWS rules (one per `IpRanges` / `Ipv6Ranges` / `UserIdGroupPairs` /
22178
+ * `PrefixListIds` entry). State's full rule signature (passed via the
22179
+ * optional `properties` arg) is used to find the exact matching rule.
22180
+ *
22181
+ * AWS API: `DescribeSecurityGroups(groupId)` → walk `IpPermissions[]`
22182
+ * filtered by protocol+ports → flatten via `flattenIpPermissions` →
22183
+ * find the entry matching state's full signature (CIDR / peer / prefix /
22184
+ * description). Returns `undefined` when the parent SG is gone or no
22185
+ * matching rule exists.
22186
+ */
22187
+ async readSecurityGroupIngressCurrentState(physicalId, properties) {
22188
+ const parts = physicalId.split("|");
22189
+ if (parts.length < 4)
22190
+ return void 0;
22191
+ const groupId = parts[0];
22192
+ const protocol = parts[1];
22193
+ const fromPort = parts[2] === "-1" ? void 0 : parseInt(parts[2], 10);
22194
+ const toPort = parts[3] === "-1" ? void 0 : parseInt(parts[3], 10);
22195
+ const resp = await this.ec2Client.send(
22196
+ new DescribeSecurityGroupsCommand2({ GroupIds: [groupId] })
22197
+ );
22198
+ const sg = resp.SecurityGroups?.[0];
22199
+ if (!sg)
22200
+ return void 0;
22201
+ const candidates = (sg.IpPermissions ?? []).filter(
22202
+ (p) => (p.IpProtocol ?? "-1") === protocol && (p.FromPort ?? void 0) === fromPort && (p.ToPort ?? void 0) === toPort
22203
+ );
22204
+ if (candidates.length === 0)
22205
+ return void 0;
22206
+ const flat = flattenIpPermissions(candidates, "ingress");
22207
+ if (properties && Object.keys(properties).length > 0) {
22208
+ const stateKey = sgRuleKey(properties, "ingress");
22209
+ const match = flat.find((r) => sgRuleKey(r, "ingress") === stateKey);
22210
+ if (match) {
22211
+ return { GroupId: groupId, ...match };
22212
+ }
22213
+ return void 0;
22214
+ }
22215
+ return { GroupId: groupId, ...flat[0] };
22216
+ }
22217
+ /**
22218
+ * AWS::EC2::NetworkAclEntry readCurrentState.
22219
+ *
22220
+ * physicalId format: `<aclId>|<ruleNumber>|<egress>` (cdkd
22221
+ * `createNetworkAclEntry`).
22222
+ *
22223
+ * AWS API: `DescribeNetworkAcls(aclId)` → walk `Entries[]` for the entry
22224
+ * matching `(RuleNumber, Egress)`. Returns `undefined` when the parent
22225
+ * ACL is gone or the rule has been removed.
22226
+ *
22227
+ * Surfaces every user-controllable CFn property (`Protocol`, `RuleAction`,
22228
+ * `CidrBlock`, `Ipv6CidrBlock`, `PortRange`, `IcmpTypeCode`). `Protocol`
22229
+ * is normalized to a number to match CFn input shape (AWS returns it as
22230
+ * a string).
22231
+ */
22232
+ async readNetworkAclEntryCurrentState(physicalId) {
22233
+ const parts = physicalId.split("|");
22234
+ if (parts.length < 3)
22235
+ return void 0;
22236
+ const aclId = parts[0];
22237
+ const ruleNumber = parseInt(parts[1], 10);
22238
+ const egress = parts[2] === "true";
22239
+ const resp = await this.ec2Client.send(
22240
+ new DescribeNetworkAclsCommand({ NetworkAclIds: [aclId] })
22241
+ );
22242
+ const acl = resp.NetworkAcls?.[0];
22243
+ if (!acl)
22244
+ return void 0;
22245
+ const entry = acl.Entries?.find(
22246
+ (e) => e.RuleNumber === ruleNumber && (e.Egress ?? false) === egress
22247
+ );
22248
+ if (!entry)
22249
+ return void 0;
22250
+ const result = {
22251
+ NetworkAclId: aclId,
22252
+ RuleNumber: ruleNumber,
22253
+ Egress: egress
22254
+ };
22255
+ if (entry.Protocol !== void 0) {
22256
+ const n = parseInt(entry.Protocol, 10);
22257
+ result["Protocol"] = Number.isNaN(n) ? entry.Protocol : n;
22258
+ }
22259
+ if (entry.RuleAction !== void 0)
22260
+ result["RuleAction"] = entry.RuleAction;
22261
+ if (entry.CidrBlock !== void 0)
22262
+ result["CidrBlock"] = entry.CidrBlock;
22263
+ if (entry.Ipv6CidrBlock !== void 0)
22264
+ result["Ipv6CidrBlock"] = entry.Ipv6CidrBlock;
22265
+ if (entry.PortRange) {
22266
+ const pr = {};
22267
+ if (entry.PortRange.From !== void 0)
22268
+ pr["From"] = entry.PortRange.From;
22269
+ if (entry.PortRange.To !== void 0)
22270
+ pr["To"] = entry.PortRange.To;
22271
+ if (Object.keys(pr).length > 0)
22272
+ result["PortRange"] = pr;
22273
+ }
22274
+ if (entry.IcmpTypeCode) {
22275
+ const icmp = {};
22276
+ if (entry.IcmpTypeCode.Type !== void 0)
22277
+ icmp["Type"] = entry.IcmpTypeCode.Type;
22278
+ if (entry.IcmpTypeCode.Code !== void 0)
22279
+ icmp["Code"] = entry.IcmpTypeCode.Code;
22280
+ if (Object.keys(icmp).length > 0)
22281
+ result["IcmpTypeCode"] = icmp;
22282
+ }
22283
+ return result;
22284
+ }
22285
+ /**
22286
+ * AWS::EC2::SubnetNetworkAclAssociation readCurrentState.
22287
+ *
22288
+ * physicalId format: `<aclassoc-xxx>` (returned by
22289
+ * `ReplaceNetworkAclAssociation`).
22290
+ *
22291
+ * AWS API: `DescribeNetworkAcls` filtered by `association.association-id`,
22292
+ * then walk `Associations[]` for the matching entry. Returns `undefined`
22293
+ * when no NACL carries the association id.
22294
+ *
22295
+ * Surfaces `NetworkAclId` + `SubnetId`. Drift signal: NetworkAclId
22296
+ * changed (subnet was reassigned to a different NACL via console).
22297
+ */
22298
+ async readSubnetNetworkAclAssociationCurrentState(physicalId) {
22299
+ const resp = await this.ec2Client.send(
22300
+ new DescribeNetworkAclsCommand({
22301
+ Filters: [{ Name: "association.association-id", Values: [physicalId] }]
22302
+ })
22303
+ );
22304
+ for (const acl of resp.NetworkAcls ?? []) {
22305
+ const assoc = acl.Associations?.find((a) => a.NetworkAclAssociationId === physicalId);
22306
+ if (assoc) {
22307
+ const result = {};
22308
+ if (assoc.NetworkAclId !== void 0)
22309
+ result["NetworkAclId"] = assoc.NetworkAclId;
22310
+ if (assoc.SubnetId !== void 0)
22311
+ result["SubnetId"] = assoc.SubnetId;
22312
+ return result;
22313
+ }
22314
+ }
22315
+ return void 0;
22316
+ }
22039
22317
  async verifyExplicit(resourceType, physicalId) {
22040
22318
  try {
22041
22319
  switch (resourceType) {
@@ -44795,7 +45073,7 @@ function reorderArgs(argv) {
44795
45073
  }
44796
45074
  async function main() {
44797
45075
  const program = new Command14();
44798
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.51.5");
45076
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.51.6");
44799
45077
  program.addCommand(createBootstrapCommand());
44800
45078
  program.addCommand(createSynthCommand());
44801
45079
  program.addCommand(createListCommand());