@friggframework/devtools 2.0.0--canary.623.71305f2.0 → 2.0.0--canary.622.fe9da2d.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.
|
@@ -1,20 +1,42 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Environment Builder Service
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* Domain Service - Hexagonal Architecture
|
|
5
|
-
*
|
|
5
|
+
*
|
|
6
6
|
* Builds Lambda environment variable configuration from:
|
|
7
7
|
* 1. AppDefinition environment flags
|
|
8
8
|
* 2. Discovered AWS resources (VPC IDs, KMS keys, etc.)
|
|
9
9
|
* 3. Generated resource references
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
// OTLP-family exporters read their endpoint/headers from these standard env
|
|
13
|
+
// vars (ADR-011). When such an exporter is configured we auto-register them as
|
|
14
|
+
// Serverless passthroughs so the deployed Lambda inherits them from the deploy
|
|
15
|
+
// environment — no need for the adopter to also list them under `environment`.
|
|
16
|
+
//
|
|
17
|
+
// NOTE (VPC egress): a Lambda in a private subnet needs a NAT gateway or a VPC
|
|
18
|
+
// endpoint to reach an external OTLP backend (Honeycomb/Datadog). Without egress
|
|
19
|
+
// the exporter fails silently within its flush timeout — see the deploy docs.
|
|
20
|
+
const OTLP_EXPORTER_TYPES = new Set(['otlp', 'honeycomb', 'datadog']);
|
|
21
|
+
const OTEL_PASSTHROUGH_VARS = [
|
|
22
|
+
'OTEL_EXPORTER_OTLP_ENDPOINT',
|
|
23
|
+
'OTEL_EXPORTER_OTLP_HEADERS',
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
function addTelemetryEnvPassthrough(appDefinition, envVars) {
|
|
27
|
+
const exporterType = appDefinition?.telemetry?.exporter?.type;
|
|
28
|
+
if (!OTLP_EXPORTER_TYPES.has(exporterType)) return;
|
|
29
|
+
for (const key of OTEL_PASSTHROUGH_VARS) {
|
|
30
|
+
envVars[key] = `\${env:${key}, ''}`;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
12
34
|
/**
|
|
13
35
|
* Get environment variables from AppDefinition
|
|
14
|
-
*
|
|
36
|
+
*
|
|
15
37
|
* Extracts environment variable definitions where value is true,
|
|
16
38
|
* and creates Serverless variable references.
|
|
17
|
-
*
|
|
39
|
+
*
|
|
18
40
|
* @param {Object} appDefinition - Application definition
|
|
19
41
|
* @returns {Object} Environment variable mappings
|
|
20
42
|
*/
|
|
@@ -38,6 +60,8 @@ function getAppEnvironmentVars(appDefinition) {
|
|
|
38
60
|
'AWS_SESSION_TOKEN',
|
|
39
61
|
]);
|
|
40
62
|
|
|
63
|
+
addTelemetryEnvPassthrough(appDefinition, envVars);
|
|
64
|
+
|
|
41
65
|
if (!appDefinition.environment) {
|
|
42
66
|
return envVars;
|
|
43
67
|
}
|
|
@@ -65,7 +89,8 @@ function getAppEnvironmentVars(appDefinition) {
|
|
|
65
89
|
}
|
|
66
90
|
if (skippedKeys.length > 0) {
|
|
67
91
|
console.log(
|
|
68
|
-
` ⚠️ Skipped ${
|
|
92
|
+
` ⚠️ Skipped ${
|
|
93
|
+
skippedKeys.length
|
|
69
94
|
} reserved AWS Lambda variables: ${skippedKeys.join(', ')}`
|
|
70
95
|
);
|
|
71
96
|
}
|
|
@@ -75,9 +100,9 @@ function getAppEnvironmentVars(appDefinition) {
|
|
|
75
100
|
|
|
76
101
|
/**
|
|
77
102
|
* Build complete environment configuration for Lambda functions
|
|
78
|
-
*
|
|
103
|
+
*
|
|
79
104
|
* Combines app environment vars with discovered AWS resource references
|
|
80
|
-
*
|
|
105
|
+
*
|
|
81
106
|
* @param {Object} appEnvironmentVars - Environment vars from AppDefinition
|
|
82
107
|
* @param {Object} discoveredResources - Discovered AWS resources
|
|
83
108
|
* @returns {Object} Complete environment configuration
|
|
@@ -85,7 +110,7 @@ function getAppEnvironmentVars(appDefinition) {
|
|
|
85
110
|
function buildEnvironment(appEnvironmentVars, discoveredResources) {
|
|
86
111
|
const environment = {
|
|
87
112
|
...appEnvironmentVars,
|
|
88
|
-
STAGE: '${self:provider.stage}',
|
|
113
|
+
STAGE: '${self:provider.stage}', // Used by encryption bypass logic
|
|
89
114
|
FRIGG_STACK: '${self:service}',
|
|
90
115
|
FRIGG_STAGE: '${self:provider.stage}',
|
|
91
116
|
FRIGG_REGION: '${self:provider.region}',
|
|
@@ -101,7 +126,9 @@ function buildEnvironment(appEnvironmentVars, discoveredResources) {
|
|
|
101
126
|
// Add database connection info if discovered
|
|
102
127
|
if (discoveredResources.auroraClusterEndpoint) {
|
|
103
128
|
environment.DATABASE_HOST = discoveredResources.auroraClusterEndpoint;
|
|
104
|
-
environment.DATABASE_PORT = String(
|
|
129
|
+
environment.DATABASE_PORT = String(
|
|
130
|
+
discoveredResources.auroraPort || 5432
|
|
131
|
+
);
|
|
105
132
|
}
|
|
106
133
|
|
|
107
134
|
// Add secrets manager secret ARN if discovered
|
|
@@ -116,4 +143,3 @@ module.exports = {
|
|
|
116
143
|
getAppEnvironmentVars,
|
|
117
144
|
buildEnvironment,
|
|
118
145
|
};
|
|
119
|
-
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tests for Environment Builder Service
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* Tests environment variable extraction and building
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
const {
|
|
7
|
+
const {
|
|
8
|
+
getAppEnvironmentVars,
|
|
9
|
+
buildEnvironment,
|
|
10
|
+
} = require('./environment-builder');
|
|
8
11
|
|
|
9
12
|
describe('Environment Builder', () => {
|
|
10
13
|
describe('getAppEnvironmentVars()', () => {
|
|
@@ -108,6 +111,42 @@ describe('Environment Builder', () => {
|
|
|
108
111
|
});
|
|
109
112
|
});
|
|
110
113
|
|
|
114
|
+
describe('telemetry env passthrough (ADR-011)', () => {
|
|
115
|
+
it('auto-adds OTLP env passthroughs when an OTLP-family exporter is configured', () => {
|
|
116
|
+
const result = getAppEnvironmentVars({
|
|
117
|
+
telemetry: { exporter: { type: 'otlp' } },
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
expect(result.OTEL_EXPORTER_OTLP_ENDPOINT).toBe(
|
|
121
|
+
"${env:OTEL_EXPORTER_OTLP_ENDPOINT, ''}"
|
|
122
|
+
);
|
|
123
|
+
expect(result.OTEL_EXPORTER_OTLP_HEADERS).toBe(
|
|
124
|
+
"${env:OTEL_EXPORTER_OTLP_HEADERS, ''}"
|
|
125
|
+
);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it.each(['honeycomb', 'datadog'])(
|
|
129
|
+
'adds OTLP passthroughs for the "%s" preset',
|
|
130
|
+
(type) => {
|
|
131
|
+
const result = getAppEnvironmentVars({
|
|
132
|
+
telemetry: { exporter: { type } },
|
|
133
|
+
});
|
|
134
|
+
expect(result.OTEL_EXPORTER_OTLP_ENDPOINT).toBeDefined();
|
|
135
|
+
}
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
it('adds no OTLP env vars for console/none exporters or absent telemetry', () => {
|
|
139
|
+
expect(
|
|
140
|
+
getAppEnvironmentVars({
|
|
141
|
+
telemetry: { exporter: { type: 'console' } },
|
|
142
|
+
}).OTEL_EXPORTER_OTLP_ENDPOINT
|
|
143
|
+
).toBeUndefined();
|
|
144
|
+
expect(
|
|
145
|
+
getAppEnvironmentVars({}).OTEL_EXPORTER_OTLP_ENDPOINT
|
|
146
|
+
).toBeUndefined();
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
|
|
111
150
|
describe('buildEnvironment()', () => {
|
|
112
151
|
it('should combine app vars with standard Frigg variables', () => {
|
|
113
152
|
const appEnvironmentVars = {
|
|
@@ -115,7 +154,10 @@ describe('Environment Builder', () => {
|
|
|
115
154
|
};
|
|
116
155
|
const discoveredResources = {};
|
|
117
156
|
|
|
118
|
-
const result = buildEnvironment(
|
|
157
|
+
const result = buildEnvironment(
|
|
158
|
+
appEnvironmentVars,
|
|
159
|
+
discoveredResources
|
|
160
|
+
);
|
|
119
161
|
|
|
120
162
|
expect(result.API_KEY).toBe("${env:API_KEY, ''}");
|
|
121
163
|
expect(result.STAGE).toBe('${self:provider.stage}');
|
|
@@ -130,9 +172,14 @@ describe('Environment Builder', () => {
|
|
|
130
172
|
kmsKeyId: 'arn:aws:kms:us-east-1:123456:key/abc-123',
|
|
131
173
|
};
|
|
132
174
|
|
|
133
|
-
const result = buildEnvironment(
|
|
175
|
+
const result = buildEnvironment(
|
|
176
|
+
appEnvironmentVars,
|
|
177
|
+
discoveredResources
|
|
178
|
+
);
|
|
134
179
|
|
|
135
|
-
expect(result.KMS_KEY_ARN).toBe(
|
|
180
|
+
expect(result.KMS_KEY_ARN).toBe(
|
|
181
|
+
'arn:aws:kms:us-east-1:123456:key/abc-123'
|
|
182
|
+
);
|
|
136
183
|
});
|
|
137
184
|
|
|
138
185
|
it('should prefer kmsKeyId over kmsKeyArn if both present', () => {
|
|
@@ -142,22 +189,33 @@ describe('Environment Builder', () => {
|
|
|
142
189
|
kmsKeyArn: 'arn:aws:kms:us-east-1:123456:key/secondary',
|
|
143
190
|
};
|
|
144
191
|
|
|
145
|
-
const result = buildEnvironment(
|
|
192
|
+
const result = buildEnvironment(
|
|
193
|
+
appEnvironmentVars,
|
|
194
|
+
discoveredResources
|
|
195
|
+
);
|
|
146
196
|
|
|
147
197
|
// Implementation uses if/else-if, so kmsKeyId takes priority
|
|
148
|
-
expect(result.KMS_KEY_ARN).toBe(
|
|
198
|
+
expect(result.KMS_KEY_ARN).toBe(
|
|
199
|
+
'arn:aws:kms:us-east-1:123456:key/primary'
|
|
200
|
+
);
|
|
149
201
|
});
|
|
150
202
|
|
|
151
203
|
it('should add database connection info if discovered', () => {
|
|
152
204
|
const appEnvironmentVars = {};
|
|
153
205
|
const discoveredResources = {
|
|
154
|
-
auroraClusterEndpoint:
|
|
206
|
+
auroraClusterEndpoint:
|
|
207
|
+
'cluster.abc.us-east-1.rds.amazonaws.com',
|
|
155
208
|
auroraPort: 5432,
|
|
156
209
|
};
|
|
157
210
|
|
|
158
|
-
const result = buildEnvironment(
|
|
211
|
+
const result = buildEnvironment(
|
|
212
|
+
appEnvironmentVars,
|
|
213
|
+
discoveredResources
|
|
214
|
+
);
|
|
159
215
|
|
|
160
|
-
expect(result.DATABASE_HOST).toBe(
|
|
216
|
+
expect(result.DATABASE_HOST).toBe(
|
|
217
|
+
'cluster.abc.us-east-1.rds.amazonaws.com'
|
|
218
|
+
);
|
|
161
219
|
expect(result.DATABASE_PORT).toBe('5432');
|
|
162
220
|
});
|
|
163
221
|
|
|
@@ -167,7 +225,10 @@ describe('Environment Builder', () => {
|
|
|
167
225
|
auroraClusterEndpoint: 'cluster.example.com',
|
|
168
226
|
};
|
|
169
227
|
|
|
170
|
-
const result = buildEnvironment(
|
|
228
|
+
const result = buildEnvironment(
|
|
229
|
+
appEnvironmentVars,
|
|
230
|
+
discoveredResources
|
|
231
|
+
);
|
|
171
232
|
|
|
172
233
|
expect(result.DATABASE_HOST).toBe('cluster.example.com');
|
|
173
234
|
expect(result.DATABASE_PORT).toBe('5432');
|
|
@@ -176,12 +237,18 @@ describe('Environment Builder', () => {
|
|
|
176
237
|
it('should add database secret ARN if discovered', () => {
|
|
177
238
|
const appEnvironmentVars = {};
|
|
178
239
|
const discoveredResources = {
|
|
179
|
-
databaseSecretArn:
|
|
240
|
+
databaseSecretArn:
|
|
241
|
+
'arn:aws:secretsmanager:us-east-1:123456:secret:db-secret',
|
|
180
242
|
};
|
|
181
243
|
|
|
182
|
-
const result = buildEnvironment(
|
|
244
|
+
const result = buildEnvironment(
|
|
245
|
+
appEnvironmentVars,
|
|
246
|
+
discoveredResources
|
|
247
|
+
);
|
|
183
248
|
|
|
184
|
-
expect(result.DATABASE_SECRET_ARN).toBe(
|
|
249
|
+
expect(result.DATABASE_SECRET_ARN).toBe(
|
|
250
|
+
'arn:aws:secretsmanager:us-east-1:123456:secret:db-secret'
|
|
251
|
+
);
|
|
185
252
|
});
|
|
186
253
|
|
|
187
254
|
it('should combine all discovered resources', () => {
|
|
@@ -192,19 +259,27 @@ describe('Environment Builder', () => {
|
|
|
192
259
|
kmsKeyArn: 'arn:aws:kms:us-east-1:123456:key/abc',
|
|
193
260
|
auroraClusterEndpoint: 'db.example.com',
|
|
194
261
|
auroraPort: 3306,
|
|
195
|
-
databaseSecretArn:
|
|
262
|
+
databaseSecretArn:
|
|
263
|
+
'arn:aws:secretsmanager:us-east-1:123456:secret:db',
|
|
196
264
|
};
|
|
197
265
|
|
|
198
|
-
const result = buildEnvironment(
|
|
266
|
+
const result = buildEnvironment(
|
|
267
|
+
appEnvironmentVars,
|
|
268
|
+
discoveredResources
|
|
269
|
+
);
|
|
199
270
|
|
|
200
271
|
expect(result.CUSTOM_VAR).toBe("${env:CUSTOM_VAR, ''}");
|
|
201
272
|
expect(result.FRIGG_STACK).toBe('${self:service}');
|
|
202
273
|
expect(result.FRIGG_STAGE).toBe('${self:provider.stage}');
|
|
203
274
|
expect(result.FRIGG_REGION).toBe('${self:provider.region}');
|
|
204
|
-
expect(result.KMS_KEY_ARN).toBe(
|
|
275
|
+
expect(result.KMS_KEY_ARN).toBe(
|
|
276
|
+
'arn:aws:kms:us-east-1:123456:key/abc'
|
|
277
|
+
);
|
|
205
278
|
expect(result.DATABASE_HOST).toBe('db.example.com');
|
|
206
279
|
expect(result.DATABASE_PORT).toBe('3306');
|
|
207
|
-
expect(result.DATABASE_SECRET_ARN).toBe(
|
|
280
|
+
expect(result.DATABASE_SECRET_ARN).toBe(
|
|
281
|
+
'arn:aws:secretsmanager:us-east-1:123456:secret:db'
|
|
282
|
+
);
|
|
208
283
|
});
|
|
209
284
|
|
|
210
285
|
it('should handle empty discoveredResources', () => {
|
|
@@ -213,7 +288,10 @@ describe('Environment Builder', () => {
|
|
|
213
288
|
};
|
|
214
289
|
const discoveredResources = {};
|
|
215
290
|
|
|
216
|
-
const result = buildEnvironment(
|
|
291
|
+
const result = buildEnvironment(
|
|
292
|
+
appEnvironmentVars,
|
|
293
|
+
discoveredResources
|
|
294
|
+
);
|
|
217
295
|
|
|
218
296
|
expect(result.API_KEY).toBe("${env:API_KEY, ''}");
|
|
219
297
|
expect(result.FRIGG_STACK).toBe('${self:service}');
|
|
@@ -237,11 +315,13 @@ describe('Environment Builder', () => {
|
|
|
237
315
|
auroraPort: 3306, // Number
|
|
238
316
|
};
|
|
239
317
|
|
|
240
|
-
const result = buildEnvironment(
|
|
318
|
+
const result = buildEnvironment(
|
|
319
|
+
appEnvironmentVars,
|
|
320
|
+
discoveredResources
|
|
321
|
+
);
|
|
241
322
|
|
|
242
323
|
expect(result.DATABASE_PORT).toBe('3306'); // String
|
|
243
324
|
expect(typeof result.DATABASE_PORT).toBe('string');
|
|
244
325
|
});
|
|
245
326
|
});
|
|
246
327
|
});
|
|
247
|
-
|
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.
|
|
4
|
+
"version": "2.0.0--canary.622.fe9da2d.0",
|
|
5
5
|
"bin": {
|
|
6
6
|
"frigg": "./frigg-cli/index.js"
|
|
7
7
|
},
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"@babel/eslint-parser": "^7.18.9",
|
|
26
26
|
"@babel/parser": "^7.25.3",
|
|
27
27
|
"@babel/traverse": "^7.25.3",
|
|
28
|
-
"@friggframework/core": "2.0.0--canary.
|
|
29
|
-
"@friggframework/schemas": "2.0.0--canary.
|
|
30
|
-
"@friggframework/test": "2.0.0--canary.
|
|
28
|
+
"@friggframework/core": "2.0.0--canary.622.fe9da2d.0",
|
|
29
|
+
"@friggframework/schemas": "2.0.0--canary.622.fe9da2d.0",
|
|
30
|
+
"@friggframework/test": "2.0.0--canary.622.fe9da2d.0",
|
|
31
31
|
"@hapi/boom": "^10.0.1",
|
|
32
32
|
"@inquirer/prompts": "^5.3.8",
|
|
33
33
|
"axios": "^1.18.0",
|
|
@@ -55,8 +55,8 @@
|
|
|
55
55
|
"validate-npm-package-name": "^5.0.0"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@friggframework/eslint-config": "2.0.0--canary.
|
|
59
|
-
"@friggframework/prettier-config": "2.0.0--canary.
|
|
58
|
+
"@friggframework/eslint-config": "2.0.0--canary.622.fe9da2d.0",
|
|
59
|
+
"@friggframework/prettier-config": "2.0.0--canary.622.fe9da2d.0",
|
|
60
60
|
"aws-sdk-client-mock": "^4.1.0",
|
|
61
61
|
"aws-sdk-client-mock-jest": "^4.1.0",
|
|
62
62
|
"jest": "^30.1.3",
|
|
@@ -88,5 +88,5 @@
|
|
|
88
88
|
"publishConfig": {
|
|
89
89
|
"access": "public"
|
|
90
90
|
},
|
|
91
|
-
"gitHead": "
|
|
91
|
+
"gitHead": "fe9da2d26354e6118a6f14350cdf18394408b3a4"
|
|
92
92
|
}
|