@friggframework/devtools 2.0.0--canary.428.b4a2c90.0 → 2.0.0--canary.428.3bab734.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.
@@ -372,7 +372,7 @@ const createVPCInfrastructure = (AppDefinition) => {
372
372
  },
373
373
  },
374
374
 
375
- // Private Route Table
375
+ // Private Route Table for Private Subnets
376
376
  FriggPrivateRouteTable: {
377
377
  Type: 'AWS::EC2::RouteTable',
378
378
  Properties: {
@@ -1086,36 +1086,40 @@ const composeServerlessDefinition = async (AppDefinition) => {
1086
1086
  // ALWAYS manage NAT Gateway through CloudFormation for self-healing
1087
1087
  // This ensures NAT Gateway is always in the correct subnet with proper configuration
1088
1088
 
1089
+ const natGatewayMethod =
1090
+ AppDefinition.vpc.natGateway?.method || 'useExisting';
1089
1091
  const needsNewNatGateway =
1090
- (natGatewayMethod ===
1091
- AppDefinition.vpc.natGateway?.method) ===
1092
- 'createAndManage';
1092
+ natGatewayMethod === 'createAndManage';
1093
1093
 
1094
- if (needsNewNatGateway) {
1095
- console.log(
1096
- 'Creating CloudFormation-managed NAT Gateway resources...'
1094
+ // Helper function to validate discovered public subnet
1095
+ const isValidPublicSubnet = (subnetId, discoveredResources) => {
1096
+ // Basic validation - in production, AWSDiscovery should check route tables for IGW routes
1097
+ return (
1098
+ discoveredResources.publicSubnetHasIgwRoute !== false
1097
1099
  );
1100
+ };
1101
+
1102
+ if (needsNewNatGateway) {
1103
+ // Always create new dedicated resources in create mode to avoid confusion with existing ones
1098
1104
  console.log(
1099
- 'Note: Any existing misconfigured NAT Gateways will be replaced by CloudFormation'
1105
+ 'Create mode: Creating dedicated EIP, public subnet, and NAT Gateway...'
1100
1106
  );
1101
1107
 
1102
- // Only create EIP if we don't have an existing one available
1103
- if (!discoveredResources.existingElasticIpAllocationId) {
1104
- definition.resources.Resources.FriggNATGatewayEIP = {
1105
- Type: 'AWS::EC2::EIP',
1106
- Properties: {
1107
- Domain: 'vpc',
1108
- Tags: [
1109
- {
1110
- Key: 'Name',
1111
- Value: '${self:service}-${self:provider.stage}-nat-eip',
1112
- },
1113
- ],
1114
- },
1115
- };
1116
- }
1108
+ // Create EIP (ignore any discovered)
1109
+ definition.resources.Resources.FriggNATGatewayEIP = {
1110
+ Type: 'AWS::EC2::EIP',
1111
+ Properties: {
1112
+ Domain: 'vpc',
1113
+ Tags: [
1114
+ {
1115
+ Key: 'Name',
1116
+ Value: '${self:service}-${self:provider.stage}-nat-eip',
1117
+ },
1118
+ ],
1119
+ },
1120
+ };
1117
1121
 
1118
- // If no public subnet exists, create one for NAT Gateway placement
1122
+ // Create public subnet (ignore any discovered; ensure it's in a matching AZ)
1119
1123
  if (!discoveredResources.publicSubnetId) {
1120
1124
  console.log(
1121
1125
  'No public subnet found, creating one for NAT Gateway placement...'
@@ -1155,7 +1159,7 @@ const composeServerlessDefinition = async (AppDefinition) => {
1155
1159
  VpcId: discoveredResources.defaultVpcId,
1156
1160
  CidrBlock:
1157
1161
  AppDefinition.vpc.natGateway
1158
- ?.publicSubnetCidr || '172.31.250.0/24', // Small /24 subnet
1162
+ ?.publicSubnetCidr || '172.31.250.0/24',
1159
1163
  AvailabilityZone: {
1160
1164
  'Fn::Select': [0, { 'Fn::GetAZs': '' }],
1161
1165
  },
@@ -1216,17 +1220,16 @@ const composeServerlessDefinition = async (AppDefinition) => {
1216
1220
  };
1217
1221
  }
1218
1222
 
1219
- // ALWAYS create NAT Gateway in CloudFormation for management and self-healing
1223
+ // Create NAT Gateway using the new resources
1220
1224
  definition.resources.Resources.FriggNATGateway = {
1221
1225
  Type: 'AWS::EC2::NatGateway',
1222
1226
  Properties: {
1223
- AllocationId:
1224
- discoveredResources.existingElasticIpAllocationId || {
1225
- 'Fn::GetAtt': [
1226
- 'FriggNATGatewayEIP',
1227
- 'AllocationId',
1228
- ],
1229
- },
1227
+ AllocationId: {
1228
+ 'Fn::GetAtt': [
1229
+ 'FriggNATGatewayEIP',
1230
+ 'AllocationId',
1231
+ ],
1232
+ },
1230
1233
  SubnetId: discoveredResources.publicSubnetId || {
1231
1234
  Ref: 'FriggPublicSubnet',
1232
1235
  },
@@ -1242,17 +1245,32 @@ const composeServerlessDefinition = async (AppDefinition) => {
1242
1245
  ],
1243
1246
  },
1244
1247
  };
1248
+ } else if (discoveredResources.existingNatGatewayId) {
1249
+ // Reuse mode: Use existing NAT, but validate first
1250
+ if (
1251
+ discoveredResources.publicSubnetId &&
1252
+ isValidPublicSubnet(
1253
+ discoveredResources.publicSubnetId,
1254
+ discoveredResources
1255
+ )
1256
+ ) {
1257
+ console.log(
1258
+ 'Reuse mode: Valid existing NAT found; adding routes...'
1259
+ );
1260
+ // No new NAT creation; just add routes referencing existingNatGatewayId
1261
+ } else {
1262
+ throw new Error(
1263
+ 'Existing NAT discovered but public subnet is invalid or missing. Set method to "createAndManage" or fix subnet configuration.'
1264
+ );
1265
+ }
1245
1266
  } else {
1246
- // We have an existing valid NAT Gateway - import it into CloudFormation management
1247
- console.log(
1248
- 'Found existing NAT Gateway - importing into CloudFormation management for self-healing...'
1267
+ // No NAT and not in create mode: Error out to prevent isolated subnets
1268
+ throw new Error(
1269
+ 'No existing NAT Gateway found and createAndManage not enabled. Update appDefinition.vpc.natGateway.method or ensure discovery finds a valid NAT.'
1249
1270
  );
1250
-
1251
- // Note: CloudFormation will detect if a NAT Gateway already exists with these properties
1252
- // and will adopt it rather than creating a duplicate
1253
1271
  }
1254
1272
 
1255
- // Create route table for Lambda subnets to use NAT Gateway
1273
+ // Always add route table and routes (referencing the NAT, whether new or existing)
1256
1274
  definition.resources.Resources.FriggLambdaRouteTable = {
1257
1275
  Type: 'AWS::EC2::RouteTable',
1258
1276
  Properties: {
@@ -1274,7 +1292,17 @@ const composeServerlessDefinition = async (AppDefinition) => {
1274
1292
  Properties: {
1275
1293
  RouteTableId: { Ref: 'FriggLambdaRouteTable' },
1276
1294
  DestinationCidrBlock: '0.0.0.0/0',
1277
- NatGatewayId: { Ref: 'FriggNATGateway' }, // Always use CloudFormation-managed NAT Gateway
1295
+ NatGatewayId: { Ref: 'FriggNATGateway' },
1296
+ },
1297
+ };
1298
+ } else {
1299
+ definition.resources.Resources.FriggNATRoute = {
1300
+ Type: 'AWS::EC2::Route',
1301
+ Properties: {
1302
+ RouteTableId: { Ref: 'FriggLambdaRouteTable' },
1303
+ DestinationCidrBlock: '0.0.0.0/0',
1304
+ NatGatewayId:
1305
+ discoveredResources.existingNatGatewayId,
1278
1306
  },
1279
1307
  };
1280
1308
  }
@@ -1346,7 +1374,9 @@ const composeServerlessDefinition = async (AppDefinition) => {
1346
1374
  IpProtocol: 'tcp',
1347
1375
  FromPort: 443,
1348
1376
  ToPort: 443,
1349
- CidrIp: '172.31.0.0/16', // VPC CIDR
1377
+ CidrIp:
1378
+ discoveredResources.vpcCidr ||
1379
+ '10.0.0.0/16', // Dynamic VPC CIDR
1350
1380
  },
1351
1381
  ],
1352
1382
  Tags: [
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@friggframework/devtools",
3
3
  "prettier": "@friggframework/prettier-config",
4
- "version": "2.0.0--canary.428.b4a2c90.0",
4
+ "version": "2.0.0--canary.428.3bab734.0",
5
5
  "dependencies": {
6
6
  "@aws-sdk/client-ec2": "^3.835.0",
7
7
  "@aws-sdk/client-kms": "^3.835.0",
@@ -9,8 +9,8 @@
9
9
  "@babel/eslint-parser": "^7.18.9",
10
10
  "@babel/parser": "^7.25.3",
11
11
  "@babel/traverse": "^7.25.3",
12
- "@friggframework/schemas": "2.0.0--canary.428.b4a2c90.0",
13
- "@friggframework/test": "2.0.0--canary.428.b4a2c90.0",
12
+ "@friggframework/schemas": "2.0.0--canary.428.3bab734.0",
13
+ "@friggframework/test": "2.0.0--canary.428.3bab734.0",
14
14
  "@hapi/boom": "^10.0.1",
15
15
  "@inquirer/prompts": "^5.3.8",
16
16
  "axios": "^1.7.2",
@@ -32,8 +32,8 @@
32
32
  "serverless-http": "^2.7.0"
33
33
  },
34
34
  "devDependencies": {
35
- "@friggframework/eslint-config": "2.0.0--canary.428.b4a2c90.0",
36
- "@friggframework/prettier-config": "2.0.0--canary.428.b4a2c90.0",
35
+ "@friggframework/eslint-config": "2.0.0--canary.428.3bab734.0",
36
+ "@friggframework/prettier-config": "2.0.0--canary.428.3bab734.0",
37
37
  "jest": "^30.1.3",
38
38
  "prettier": "^2.7.1",
39
39
  "serverless": "3.39.0",
@@ -66,5 +66,5 @@
66
66
  "publishConfig": {
67
67
  "access": "public"
68
68
  },
69
- "gitHead": "b4a2c9027b96e1009f95926205f39044560edc83"
69
+ "gitHead": "3bab734d2f509d43177d80959ac59df495b3df7b"
70
70
  }