@friggframework/devtools 2.0.0--canary.461.6b7bf79.0 → 2.0.0--canary.461.4116d1e.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.
|
@@ -108,9 +108,15 @@ class CloudFormationDiscovery {
|
|
|
108
108
|
* @param {Object} discovered - Object to populate with discovered resources
|
|
109
109
|
*/
|
|
110
110
|
async _extractFromResources(resources, discovered) {
|
|
111
|
+
console.log(` DEBUG: Processing ${resources.length} CloudFormation resources...`);
|
|
111
112
|
for (const resource of resources) {
|
|
112
113
|
const { LogicalResourceId, PhysicalResourceId, ResourceType } = resource;
|
|
113
114
|
|
|
115
|
+
// Debug Aurora detection
|
|
116
|
+
if (LogicalResourceId.includes('Aurora')) {
|
|
117
|
+
console.log(` DEBUG: Found Aurora resource: ${LogicalResourceId} (${ResourceType})`);
|
|
118
|
+
}
|
|
119
|
+
|
|
114
120
|
// Security Group - use to get VPC ID
|
|
115
121
|
if (LogicalResourceId === 'FriggLambdaSecurityGroup' && ResourceType === 'AWS::EC2::SecurityGroup') {
|
|
116
122
|
discovered.securityGroupId = PhysicalResourceId;
|
|
@@ -141,21 +147,21 @@ class CloudFormationDiscovery {
|
|
|
141
147
|
if (LogicalResourceId === 'FriggAuroraCluster' && ResourceType === 'AWS::RDS::DBCluster') {
|
|
142
148
|
discovered.auroraClusterId = PhysicalResourceId;
|
|
143
149
|
console.log(` ✓ Found Aurora cluster in stack: ${PhysicalResourceId}`);
|
|
144
|
-
|
|
150
|
+
|
|
145
151
|
// Query RDS to get cluster endpoint
|
|
146
152
|
if (this.provider && !discovered.auroraClusterEndpoint) {
|
|
147
153
|
try {
|
|
148
154
|
console.log(` Querying RDS to get Aurora endpoint...`);
|
|
149
155
|
const { DescribeDBClustersCommand } = require('@aws-sdk/client-rds');
|
|
150
156
|
const { RDSClient } = require('@aws-sdk/client-rds');
|
|
151
|
-
|
|
157
|
+
|
|
152
158
|
const rdsClient = new RDSClient({ region: this.provider.region });
|
|
153
159
|
const clusterDetails = await rdsClient.send(
|
|
154
160
|
new DescribeDBClustersCommand({
|
|
155
161
|
DBClusterIdentifier: PhysicalResourceId
|
|
156
162
|
})
|
|
157
163
|
);
|
|
158
|
-
|
|
164
|
+
|
|
159
165
|
if (clusterDetails.DBClusters && clusterDetails.DBClusters.length > 0) {
|
|
160
166
|
const cluster = clusterDetails.DBClusters[0];
|
|
161
167
|
discovered.auroraClusterEndpoint = cluster.Endpoint;
|
|
@@ -235,6 +241,58 @@ class CloudFormationDiscovery {
|
|
|
235
241
|
discovered.sqsVpcEndpointId = PhysicalResourceId;
|
|
236
242
|
}
|
|
237
243
|
}
|
|
244
|
+
|
|
245
|
+
// If we have a VPC ID but no subnet IDs, query EC2 for Frigg-managed subnets
|
|
246
|
+
if (discovered.defaultVpcId && this.provider &&
|
|
247
|
+
!discovered.privateSubnetId1 && !discovered.publicSubnetId1) {
|
|
248
|
+
try {
|
|
249
|
+
console.log(' Querying EC2 for Frigg-managed subnets...');
|
|
250
|
+
const { DescribeSubnetsCommand } = require('@aws-sdk/client-ec2');
|
|
251
|
+
const subnetResponse = await this.provider.getEC2Client().send(
|
|
252
|
+
new DescribeSubnetsCommand({
|
|
253
|
+
Filters: [
|
|
254
|
+
{ Name: 'vpc-id', Values: [discovered.defaultVpcId] },
|
|
255
|
+
{ Name: 'tag:ManagedBy', Values: ['Frigg'] },
|
|
256
|
+
],
|
|
257
|
+
})
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
if (subnetResponse.Subnets && subnetResponse.Subnets.length > 0) {
|
|
261
|
+
// Extract subnet IDs by logical ID from tags
|
|
262
|
+
const subnets = subnetResponse.Subnets.map(subnet => ({
|
|
263
|
+
subnetId: subnet.SubnetId,
|
|
264
|
+
logicalId: subnet.Tags?.find(t => t.Key === 'aws:cloudformation:logical-id')?.Value,
|
|
265
|
+
isPublic: subnet.MapPublicIpOnLaunch,
|
|
266
|
+
}));
|
|
267
|
+
|
|
268
|
+
// Find private subnets
|
|
269
|
+
const privateSubnets = subnets.filter(s => !s.isPublic).sort((a, b) =>
|
|
270
|
+
a.logicalId?.localeCompare(b.logicalId) || 0
|
|
271
|
+
);
|
|
272
|
+
if (privateSubnets.length >= 1) {
|
|
273
|
+
discovered.privateSubnetId1 = privateSubnets[0].subnetId;
|
|
274
|
+
}
|
|
275
|
+
if (privateSubnets.length >= 2) {
|
|
276
|
+
discovered.privateSubnetId2 = privateSubnets[1].subnetId;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Find public subnets
|
|
280
|
+
const publicSubnets = subnets.filter(s => s.isPublic).sort((a, b) =>
|
|
281
|
+
a.logicalId?.localeCompare(b.logicalId) || 0
|
|
282
|
+
);
|
|
283
|
+
if (publicSubnets.length >= 1) {
|
|
284
|
+
discovered.publicSubnetId1 = publicSubnets[0].subnetId;
|
|
285
|
+
}
|
|
286
|
+
if (publicSubnets.length >= 2) {
|
|
287
|
+
discovered.publicSubnetId2 = publicSubnets[1].subnetId;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
console.log(` ✓ Found ${subnets.length} Frigg-managed subnets via EC2 query`);
|
|
291
|
+
}
|
|
292
|
+
} catch (error) {
|
|
293
|
+
console.warn(` ⚠️ Could not query EC2 for subnets: ${error.message}`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
238
296
|
}
|
|
239
297
|
}
|
|
240
298
|
|
|
@@ -307,6 +307,98 @@ describe('CloudFormationDiscovery', () => {
|
|
|
307
307
|
|
|
308
308
|
expect(result).toEqual({});
|
|
309
309
|
});
|
|
310
|
+
|
|
311
|
+
it('should query EC2 for subnets when VPC found but no subnet resources in stack', async () => {
|
|
312
|
+
const mockStack = {
|
|
313
|
+
StackName: 'test-stack',
|
|
314
|
+
Outputs: [],
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
const mockResources = [
|
|
318
|
+
{
|
|
319
|
+
LogicalResourceId: 'FriggLambdaSecurityGroup',
|
|
320
|
+
PhysicalResourceId: 'sg-123',
|
|
321
|
+
ResourceType: 'AWS::EC2::SecurityGroup',
|
|
322
|
+
},
|
|
323
|
+
];
|
|
324
|
+
|
|
325
|
+
const mockEC2Client = {
|
|
326
|
+
send: jest.fn(),
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
mockProvider.describeStack.mockResolvedValue(mockStack);
|
|
330
|
+
mockProvider.listStackResources.mockResolvedValue(mockResources);
|
|
331
|
+
mockProvider.getEC2Client = jest.fn().mockReturnValue(mockEC2Client);
|
|
332
|
+
|
|
333
|
+
// Mock security group query for VPC ID
|
|
334
|
+
mockEC2Client.send.mockResolvedValueOnce({
|
|
335
|
+
SecurityGroups: [{ VpcId: 'vpc-123' }],
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
// Mock subnet query
|
|
339
|
+
mockEC2Client.send.mockResolvedValueOnce({
|
|
340
|
+
Subnets: [
|
|
341
|
+
{
|
|
342
|
+
SubnetId: 'subnet-private-1',
|
|
343
|
+
MapPublicIpOnLaunch: false,
|
|
344
|
+
Tags: [
|
|
345
|
+
{ Key: 'ManagedBy', Value: 'Frigg' },
|
|
346
|
+
{ Key: 'aws:cloudformation:logical-id', Value: 'FriggPrivateSubnet1' },
|
|
347
|
+
],
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
SubnetId: 'subnet-private-2',
|
|
351
|
+
MapPublicIpOnLaunch: false,
|
|
352
|
+
Tags: [
|
|
353
|
+
{ Key: 'ManagedBy', Value: 'Frigg' },
|
|
354
|
+
{ Key: 'aws:cloudformation:logical-id', Value: 'FriggPrivateSubnet2' },
|
|
355
|
+
],
|
|
356
|
+
},
|
|
357
|
+
],
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
const result = await cfDiscovery.discoverFromStack('test-stack');
|
|
361
|
+
|
|
362
|
+
expect(result.privateSubnetId1).toBe('subnet-private-1');
|
|
363
|
+
expect(result.privateSubnetId2).toBe('subnet-private-2');
|
|
364
|
+
expect(mockEC2Client.send).toHaveBeenCalledTimes(2);
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
it('should handle EC2 subnet query errors gracefully', async () => {
|
|
368
|
+
const mockStack = {
|
|
369
|
+
StackName: 'test-stack',
|
|
370
|
+
Outputs: [],
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
const mockResources = [
|
|
374
|
+
{
|
|
375
|
+
LogicalResourceId: 'FriggLambdaSecurityGroup',
|
|
376
|
+
PhysicalResourceId: 'sg-123',
|
|
377
|
+
ResourceType: 'AWS::EC2::SecurityGroup',
|
|
378
|
+
},
|
|
379
|
+
];
|
|
380
|
+
|
|
381
|
+
const mockEC2Client = {
|
|
382
|
+
send: jest.fn(),
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
mockProvider.describeStack.mockResolvedValue(mockStack);
|
|
386
|
+
mockProvider.listStackResources.mockResolvedValue(mockResources);
|
|
387
|
+
mockProvider.getEC2Client = jest.fn().mockReturnValue(mockEC2Client);
|
|
388
|
+
|
|
389
|
+
// Mock security group query for VPC ID
|
|
390
|
+
mockEC2Client.send.mockResolvedValueOnce({
|
|
391
|
+
SecurityGroups: [{ VpcId: 'vpc-123' }],
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
// Mock subnet query failure
|
|
395
|
+
mockEC2Client.send.mockRejectedValueOnce(new Error('EC2 API Error'));
|
|
396
|
+
|
|
397
|
+
const result = await cfDiscovery.discoverFromStack('test-stack');
|
|
398
|
+
|
|
399
|
+
expect(result.defaultVpcId).toBe('vpc-123');
|
|
400
|
+
expect(result.privateSubnetId1).toBeUndefined();
|
|
401
|
+
});
|
|
310
402
|
});
|
|
311
403
|
});
|
|
312
404
|
|
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.461.
|
|
4
|
+
"version": "2.0.0--canary.461.4116d1e.0",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@aws-sdk/client-ec2": "^3.835.0",
|
|
7
7
|
"@aws-sdk/client-kms": "^3.835.0",
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
"@babel/eslint-parser": "^7.18.9",
|
|
12
12
|
"@babel/parser": "^7.25.3",
|
|
13
13
|
"@babel/traverse": "^7.25.3",
|
|
14
|
-
"@friggframework/schemas": "2.0.0--canary.461.
|
|
15
|
-
"@friggframework/test": "2.0.0--canary.461.
|
|
14
|
+
"@friggframework/schemas": "2.0.0--canary.461.4116d1e.0",
|
|
15
|
+
"@friggframework/test": "2.0.0--canary.461.4116d1e.0",
|
|
16
16
|
"@hapi/boom": "^10.0.1",
|
|
17
17
|
"@inquirer/prompts": "^5.3.8",
|
|
18
18
|
"axios": "^1.7.2",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"serverless-http": "^2.7.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@friggframework/eslint-config": "2.0.0--canary.461.
|
|
38
|
-
"@friggframework/prettier-config": "2.0.0--canary.461.
|
|
37
|
+
"@friggframework/eslint-config": "2.0.0--canary.461.4116d1e.0",
|
|
38
|
+
"@friggframework/prettier-config": "2.0.0--canary.461.4116d1e.0",
|
|
39
39
|
"aws-sdk-client-mock": "^4.1.0",
|
|
40
40
|
"aws-sdk-client-mock-jest": "^4.1.0",
|
|
41
41
|
"jest": "^30.1.3",
|
|
@@ -70,5 +70,5 @@
|
|
|
70
70
|
"publishConfig": {
|
|
71
71
|
"access": "public"
|
|
72
72
|
},
|
|
73
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "4116d1e999b2ef801f8433755d107b34a12ad817"
|
|
74
74
|
}
|