@friggframework/devtools 2.0.0--canary.490.eec7dcd.0 → 2.0.0--canary.490.7d57f02.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.
|
@@ -111,6 +111,74 @@ class CloudFormationDiscovery {
|
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Extract external resource references from stack resource properties
|
|
116
|
+
*
|
|
117
|
+
* When VPC/subnets/NAT are external, they're referenced in routing resources' properties.
|
|
118
|
+
* We query EC2 to get the actual VPC ID, NAT Gateway ID, and subnet IDs from the route table.
|
|
119
|
+
*
|
|
120
|
+
* @private
|
|
121
|
+
* @param {string} stackName - Stack name
|
|
122
|
+
* @param {Array} resources - CloudFormation stack resources
|
|
123
|
+
* @param {Object} discovered - Object to populate with discovered resources
|
|
124
|
+
*/
|
|
125
|
+
async _extractExternalReferencesFromStackResources(stackName, resources, discovered) {
|
|
126
|
+
if (!this.provider || !this.provider.getEC2Client) {
|
|
127
|
+
console.log(' ℹ Skipping external reference extraction (EC2 client not available)');
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
// If we found a route table in the stack, query EC2 for its details
|
|
133
|
+
// This gives us VPC ID, NAT Gateway ID, and subnet IDs
|
|
134
|
+
if (discovered.routeTableId) {
|
|
135
|
+
try {
|
|
136
|
+
console.log(` ℹ Querying route table ${discovered.routeTableId} for external references...`);
|
|
137
|
+
const { DescribeRouteTablesCommand } = require('@aws-sdk/client-ec2');
|
|
138
|
+
const ec2 = this.provider.getEC2Client();
|
|
139
|
+
const rtResponse = await ec2.send(new DescribeRouteTablesCommand({
|
|
140
|
+
RouteTableIds: [discovered.routeTableId]
|
|
141
|
+
}));
|
|
142
|
+
|
|
143
|
+
if (rtResponse.RouteTables && rtResponse.RouteTables.length > 0) {
|
|
144
|
+
const routeTable = rtResponse.RouteTables[0];
|
|
145
|
+
|
|
146
|
+
// Extract VPC ID
|
|
147
|
+
if (routeTable.VpcId && !discovered.defaultVpcId) {
|
|
148
|
+
discovered.defaultVpcId = routeTable.VpcId;
|
|
149
|
+
console.log(` ✓ Extracted VPC ID from route table: ${routeTable.VpcId}`);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Extract NAT Gateway ID from routes
|
|
153
|
+
const natRoute = routeTable.Routes?.find(r => r.NatGatewayId);
|
|
154
|
+
if (natRoute && natRoute.NatGatewayId && !discovered.natGatewayId) {
|
|
155
|
+
discovered.natGatewayId = natRoute.NatGatewayId;
|
|
156
|
+
discovered.existingNatGatewayId = natRoute.NatGatewayId;
|
|
157
|
+
console.log(` ✓ Extracted NAT Gateway ID from routes: ${natRoute.NatGatewayId}`);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Extract subnet IDs from route table associations
|
|
161
|
+
const associations = routeTable.Associations || [];
|
|
162
|
+
const subnetAssociations = associations.filter(a => a.SubnetId);
|
|
163
|
+
|
|
164
|
+
if (subnetAssociations.length >= 1 && !discovered.privateSubnetId1) {
|
|
165
|
+
discovered.privateSubnetId1 = subnetAssociations[0].SubnetId;
|
|
166
|
+
console.log(` ✓ Extracted private subnet 1 from associations: ${subnetAssociations[0].SubnetId}`);
|
|
167
|
+
}
|
|
168
|
+
if (subnetAssociations.length >= 2 && !discovered.privateSubnetId2) {
|
|
169
|
+
discovered.privateSubnetId2 = subnetAssociations[1].SubnetId;
|
|
170
|
+
console.log(` ✓ Extracted private subnet 2 from associations: ${subnetAssociations[1].SubnetId}`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
} catch (error) {
|
|
174
|
+
console.warn(` ⚠️ Could not query route table for external references: ${error.message}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
} catch (error) {
|
|
178
|
+
console.warn(` ⚠️ Error extracting external references: ${error.message}`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
114
182
|
/**
|
|
115
183
|
* Extract discovered resources from CloudFormation stack resources
|
|
116
184
|
*
|
|
@@ -342,6 +410,10 @@ class CloudFormationDiscovery {
|
|
|
342
410
|
}
|
|
343
411
|
}
|
|
344
412
|
|
|
413
|
+
// Extract VPC ID and other external references from routing resource properties
|
|
414
|
+
// This handles the pattern where VPC is external but routing is in the stack
|
|
415
|
+
await this._extractExternalReferencesFromStackResources(stackName, resources, discovered);
|
|
416
|
+
|
|
345
417
|
// If we have a VPC ID but no subnet IDs, query EC2 for Frigg-managed subnets
|
|
346
418
|
if (discovered.defaultVpcId && this.provider &&
|
|
347
419
|
!discovered.privateSubnetId1 && !discovered.publicSubnetId1) {
|
|
@@ -536,6 +536,29 @@ class AWSProviderAdapter extends CloudProviderAdapter {
|
|
|
536
536
|
return [];
|
|
537
537
|
}
|
|
538
538
|
}
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Describe a specific stack resource to get its full details including properties
|
|
542
|
+
* @param {string} stackName - Stack name
|
|
543
|
+
* @param {string} logicalResourceId - Logical resource ID
|
|
544
|
+
* @returns {Promise<Object>} Resource details
|
|
545
|
+
*/
|
|
546
|
+
async describeStackResource(stackName, logicalResourceId) {
|
|
547
|
+
const cf = this.getCloudFormationClient();
|
|
548
|
+
|
|
549
|
+
try {
|
|
550
|
+
const { DescribeStackResourceCommand } = require('@aws-sdk/client-cloudformation');
|
|
551
|
+
const response = await cf.send(new DescribeStackResourceCommand({
|
|
552
|
+
StackName: stackName,
|
|
553
|
+
LogicalResourceId: logicalResourceId,
|
|
554
|
+
}));
|
|
555
|
+
|
|
556
|
+
return response.StackResourceDetail || null;
|
|
557
|
+
} catch (error) {
|
|
558
|
+
console.warn(`Failed to describe stack resource ${logicalResourceId}:`, error.message);
|
|
559
|
+
return null;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
539
562
|
}
|
|
540
563
|
|
|
541
564
|
module.exports = {
|
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.490.
|
|
4
|
+
"version": "2.0.0--canary.490.7d57f02.0",
|
|
5
5
|
"bin": {
|
|
6
6
|
"frigg": "./frigg-cli/index.js"
|
|
7
7
|
},
|
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
"@babel/eslint-parser": "^7.18.9",
|
|
17
17
|
"@babel/parser": "^7.25.3",
|
|
18
18
|
"@babel/traverse": "^7.25.3",
|
|
19
|
-
"@friggframework/core": "2.0.0--canary.490.
|
|
20
|
-
"@friggframework/schemas": "2.0.0--canary.490.
|
|
21
|
-
"@friggframework/test": "2.0.0--canary.490.
|
|
19
|
+
"@friggframework/core": "2.0.0--canary.490.7d57f02.0",
|
|
20
|
+
"@friggframework/schemas": "2.0.0--canary.490.7d57f02.0",
|
|
21
|
+
"@friggframework/test": "2.0.0--canary.490.7d57f02.0",
|
|
22
22
|
"@hapi/boom": "^10.0.1",
|
|
23
23
|
"@inquirer/prompts": "^5.3.8",
|
|
24
24
|
"axios": "^1.7.2",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"validate-npm-package-name": "^5.0.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@friggframework/eslint-config": "2.0.0--canary.490.
|
|
50
|
-
"@friggframework/prettier-config": "2.0.0--canary.490.
|
|
49
|
+
"@friggframework/eslint-config": "2.0.0--canary.490.7d57f02.0",
|
|
50
|
+
"@friggframework/prettier-config": "2.0.0--canary.490.7d57f02.0",
|
|
51
51
|
"aws-sdk-client-mock": "^4.1.0",
|
|
52
52
|
"aws-sdk-client-mock-jest": "^4.1.0",
|
|
53
53
|
"jest": "^30.1.3",
|
|
@@ -79,5 +79,5 @@
|
|
|
79
79
|
"publishConfig": {
|
|
80
80
|
"access": "public"
|
|
81
81
|
},
|
|
82
|
-
"gitHead": "
|
|
82
|
+
"gitHead": "7d57f02625ea51ce9dadd5e1535aac1c4491b9da"
|
|
83
83
|
}
|