@friggframework/devtools 2.0.0--canary.397.155fecd.0 → 2.0.0--canary.398.e2147f7.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.
- package/infrastructure/AWS-IAM-CREDENTIAL-NEEDS.md +541 -0
- package/infrastructure/README-TESTING.md +332 -0
- package/infrastructure/__tests__/fixtures/mock-aws-resources.js +391 -0
- package/infrastructure/__tests__/helpers/test-utils.js +277 -0
- package/infrastructure/aws-discovery.js +395 -0
- package/infrastructure/aws-discovery.test.js +373 -0
- package/infrastructure/build-time-discovery.js +197 -0
- package/infrastructure/build-time-discovery.test.js +375 -0
- package/infrastructure/create-frigg-infrastructure.js +9 -1
- package/infrastructure/integration.test.js +383 -0
- package/infrastructure/serverless-template.js +510 -6
- package/infrastructure/serverless-template.test.js +498 -0
- package/package.json +5 -5
- package/test/mock-integration.js +14 -4
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const { composeServerlessDefinition } = require('./serverless-template');
|
|
3
|
+
const { AWSDiscovery } = require('./aws-discovery');
|
|
4
|
+
const { BuildTimeDiscovery } = require('./build-time-discovery');
|
|
5
|
+
const FriggServerlessPlugin = require('../../serverless-plugin/index');
|
|
6
|
+
|
|
7
|
+
// Integration tests for end-to-end AWS discovery and serverless config generation
|
|
8
|
+
describe('VPC/KMS/SSM Integration Tests', () => {
|
|
9
|
+
let mockAWSDiscovery;
|
|
10
|
+
let buildTimeDiscovery;
|
|
11
|
+
|
|
12
|
+
const mockAWSResources = {
|
|
13
|
+
defaultVpcId: 'vpc-12345678',
|
|
14
|
+
defaultSecurityGroupId: 'sg-12345678',
|
|
15
|
+
privateSubnetId1: 'subnet-private-1',
|
|
16
|
+
privateSubnetId2: 'subnet-private-2',
|
|
17
|
+
privateRouteTableId: 'rtb-12345678',
|
|
18
|
+
defaultKmsKeyId: 'arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012'
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
// Mock AWSDiscovery to return consistent test data
|
|
23
|
+
mockAWSDiscovery = {
|
|
24
|
+
discoverResources: jest.fn().mockResolvedValue(mockAWSResources),
|
|
25
|
+
findDefaultVpc: jest.fn().mockResolvedValue({ VpcId: mockAWSResources.defaultVpcId }),
|
|
26
|
+
findPrivateSubnets: jest.fn().mockResolvedValue([
|
|
27
|
+
{ SubnetId: mockAWSResources.privateSubnetId1 },
|
|
28
|
+
{ SubnetId: mockAWSResources.privateSubnetId2 }
|
|
29
|
+
]),
|
|
30
|
+
findDefaultSecurityGroup: jest.fn().mockResolvedValue({ GroupId: mockAWSResources.defaultSecurityGroupId }),
|
|
31
|
+
findPrivateRouteTable: jest.fn().mockResolvedValue({ RouteTableId: mockAWSResources.privateRouteTableId }),
|
|
32
|
+
findDefaultKmsKey: jest.fn().mockResolvedValue(mockAWSResources.defaultKmsKeyId)
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
jest.doMock('./aws-discovery', () => ({
|
|
36
|
+
AWSDiscovery: jest.fn(() => mockAWSDiscovery)
|
|
37
|
+
}));
|
|
38
|
+
|
|
39
|
+
buildTimeDiscovery = new BuildTimeDiscovery('us-east-1');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
afterEach(() => {
|
|
43
|
+
jest.clearAllMocks();
|
|
44
|
+
jest.resetModules();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe('End-to-End Serverless Configuration Generation', () => {
|
|
48
|
+
it('should generate complete serverless config with VPC, KMS, and SSM enabled', async () => {
|
|
49
|
+
const appDefinition = {
|
|
50
|
+
name: 'test-frigg-app',
|
|
51
|
+
vpc: { enable: true },
|
|
52
|
+
encryption: { useDefaultKMSForFieldLevelEncryption: true },
|
|
53
|
+
ssm: { enable: true },
|
|
54
|
+
integrations: [{
|
|
55
|
+
Definition: {
|
|
56
|
+
name: 'testIntegration'
|
|
57
|
+
}
|
|
58
|
+
}]
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// Run AWS discovery
|
|
62
|
+
const discoveredResources = await mockAWSDiscovery.discoverResources();
|
|
63
|
+
|
|
64
|
+
// Set environment variables as would happen in build
|
|
65
|
+
process.env.AWS_DISCOVERY_VPC_ID = discoveredResources.defaultVpcId;
|
|
66
|
+
process.env.AWS_DISCOVERY_SECURITY_GROUP_ID = discoveredResources.defaultSecurityGroupId;
|
|
67
|
+
process.env.AWS_DISCOVERY_SUBNET_ID_1 = discoveredResources.privateSubnetId1;
|
|
68
|
+
process.env.AWS_DISCOVERY_SUBNET_ID_2 = discoveredResources.privateSubnetId2;
|
|
69
|
+
process.env.AWS_DISCOVERY_ROUTE_TABLE_ID = discoveredResources.privateRouteTableId;
|
|
70
|
+
process.env.AWS_DISCOVERY_KMS_KEY_ID = discoveredResources.defaultKmsKeyId;
|
|
71
|
+
|
|
72
|
+
// Generate serverless configuration
|
|
73
|
+
const serverlessConfig = composeServerlessDefinition(appDefinition);
|
|
74
|
+
|
|
75
|
+
// Verify VPC configuration
|
|
76
|
+
expect(serverlessConfig.provider.vpc).toBe('${self:custom.vpc.${self:provider.stage}}');
|
|
77
|
+
expect(serverlessConfig.custom.vpc).toEqual({
|
|
78
|
+
'${self:provider.stage}': {
|
|
79
|
+
securityGroupIds: ['${env:AWS_DISCOVERY_SECURITY_GROUP_ID}'],
|
|
80
|
+
subnetIds: [
|
|
81
|
+
'${env:AWS_DISCOVERY_SUBNET_ID_1}',
|
|
82
|
+
'${env:AWS_DISCOVERY_SUBNET_ID_2}'
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Verify VPC Endpoint
|
|
88
|
+
expect(serverlessConfig.resources.Resources.VPCEndpointS3).toEqual({
|
|
89
|
+
Type: 'AWS::EC2::VPCEndpoint',
|
|
90
|
+
Properties: {
|
|
91
|
+
VpcId: '${env:AWS_DISCOVERY_VPC_ID}',
|
|
92
|
+
ServiceName: 'com.amazonaws.${self:provider.region}.s3',
|
|
93
|
+
VpcEndpointType: 'Gateway',
|
|
94
|
+
RouteTableIds: ['${env:AWS_DISCOVERY_ROUTE_TABLE_ID}']
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// Verify KMS configuration
|
|
99
|
+
expect(serverlessConfig.plugins).toContain('serverless-kms-grants');
|
|
100
|
+
expect(serverlessConfig.provider.environment.KMS_KEY_ARN).toBe('${self:custom.kmsGrants.kmsKeyId}');
|
|
101
|
+
expect(serverlessConfig.custom.kmsGrants).toEqual({
|
|
102
|
+
kmsKeyId: '${env:AWS_DISCOVERY_KMS_KEY_ID}'
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Verify KMS IAM permissions
|
|
106
|
+
const kmsPermission = serverlessConfig.provider.iamRoleStatements.find(
|
|
107
|
+
statement => statement.Action.includes('kms:GenerateDataKey')
|
|
108
|
+
);
|
|
109
|
+
expect(kmsPermission).toBeDefined();
|
|
110
|
+
|
|
111
|
+
// Verify SSM configuration
|
|
112
|
+
expect(serverlessConfig.provider.layers).toEqual([
|
|
113
|
+
'arn:aws:lambda:${self:provider.region}:177933569100:layer:AWS-Parameters-and-Secrets-Lambda-Extension:11'
|
|
114
|
+
]);
|
|
115
|
+
expect(serverlessConfig.provider.environment.SSM_PARAMETER_PREFIX).toBe('/${self:service}/${self:provider.stage}');
|
|
116
|
+
|
|
117
|
+
// Verify SSM IAM permissions
|
|
118
|
+
const ssmPermission = serverlessConfig.provider.iamRoleStatements.find(
|
|
119
|
+
statement => statement.Action.includes('ssm:GetParameter')
|
|
120
|
+
);
|
|
121
|
+
expect(ssmPermission).toBeDefined();
|
|
122
|
+
|
|
123
|
+
// Verify integration resources
|
|
124
|
+
expect(serverlessConfig.functions.testIntegration).toBeDefined();
|
|
125
|
+
expect(serverlessConfig.functions.testIntegrationQueueWorker).toBeDefined();
|
|
126
|
+
expect(serverlessConfig.resources.Resources.TestIntegrationQueue).toBeDefined();
|
|
127
|
+
|
|
128
|
+
// Clean up environment
|
|
129
|
+
delete process.env.AWS_DISCOVERY_VPC_ID;
|
|
130
|
+
delete process.env.AWS_DISCOVERY_SECURITY_GROUP_ID;
|
|
131
|
+
delete process.env.AWS_DISCOVERY_SUBNET_ID_1;
|
|
132
|
+
delete process.env.AWS_DISCOVERY_SUBNET_ID_2;
|
|
133
|
+
delete process.env.AWS_DISCOVERY_ROUTE_TABLE_ID;
|
|
134
|
+
delete process.env.AWS_DISCOVERY_KMS_KEY_ID;
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('should generate config with only VPC enabled', async () => {
|
|
138
|
+
const appDefinition = {
|
|
139
|
+
name: 'vpc-only-app',
|
|
140
|
+
vpc: { enable: true },
|
|
141
|
+
integrations: []
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
process.env.AWS_DISCOVERY_VPC_ID = mockAWSResources.defaultVpcId;
|
|
145
|
+
process.env.AWS_DISCOVERY_SECURITY_GROUP_ID = mockAWSResources.defaultSecurityGroupId;
|
|
146
|
+
process.env.AWS_DISCOVERY_SUBNET_ID_1 = mockAWSResources.privateSubnetId1;
|
|
147
|
+
process.env.AWS_DISCOVERY_SUBNET_ID_2 = mockAWSResources.privateSubnetId2;
|
|
148
|
+
process.env.AWS_DISCOVERY_ROUTE_TABLE_ID = mockAWSResources.privateRouteTableId;
|
|
149
|
+
|
|
150
|
+
const serverlessConfig = composeServerlessDefinition(appDefinition);
|
|
151
|
+
|
|
152
|
+
// Should have VPC config
|
|
153
|
+
expect(serverlessConfig.provider.vpc).toBeDefined();
|
|
154
|
+
expect(serverlessConfig.custom.vpc).toBeDefined();
|
|
155
|
+
expect(serverlessConfig.resources.Resources.VPCEndpointS3).toBeDefined();
|
|
156
|
+
|
|
157
|
+
// Should not have KMS config
|
|
158
|
+
expect(serverlessConfig.plugins).not.toContain('serverless-kms-grants');
|
|
159
|
+
expect(serverlessConfig.provider.environment.KMS_KEY_ARN).toBeUndefined();
|
|
160
|
+
|
|
161
|
+
// Should not have SSM config
|
|
162
|
+
expect(serverlessConfig.provider.layers).toBeUndefined();
|
|
163
|
+
expect(serverlessConfig.provider.environment.SSM_PARAMETER_PREFIX).toBeUndefined();
|
|
164
|
+
|
|
165
|
+
// Clean up
|
|
166
|
+
delete process.env.AWS_DISCOVERY_VPC_ID;
|
|
167
|
+
delete process.env.AWS_DISCOVERY_SECURITY_GROUP_ID;
|
|
168
|
+
delete process.env.AWS_DISCOVERY_SUBNET_ID_1;
|
|
169
|
+
delete process.env.AWS_DISCOVERY_SUBNET_ID_2;
|
|
170
|
+
delete process.env.AWS_DISCOVERY_ROUTE_TABLE_ID;
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('should generate config with only KMS enabled', async () => {
|
|
174
|
+
const appDefinition = {
|
|
175
|
+
name: 'kms-only-app',
|
|
176
|
+
encryption: { useDefaultKMSForFieldLevelEncryption: true },
|
|
177
|
+
integrations: []
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
process.env.AWS_DISCOVERY_KMS_KEY_ID = mockAWSResources.defaultKmsKeyId;
|
|
181
|
+
|
|
182
|
+
const serverlessConfig = composeServerlessDefinition(appDefinition);
|
|
183
|
+
|
|
184
|
+
// Should have KMS config
|
|
185
|
+
expect(serverlessConfig.plugins).toContain('serverless-kms-grants');
|
|
186
|
+
expect(serverlessConfig.custom.kmsGrants).toBeDefined();
|
|
187
|
+
|
|
188
|
+
// Should not have VPC config
|
|
189
|
+
expect(serverlessConfig.provider.vpc).toBeUndefined();
|
|
190
|
+
|
|
191
|
+
// Should not have SSM config
|
|
192
|
+
expect(serverlessConfig.provider.layers).toBeUndefined();
|
|
193
|
+
|
|
194
|
+
delete process.env.AWS_DISCOVERY_KMS_KEY_ID;
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
describe('Plugin Integration', () => {
|
|
199
|
+
it('should trigger AWS discovery through serverless plugin', async () => {
|
|
200
|
+
const mockServerless = {
|
|
201
|
+
cli: { log: jest.fn() },
|
|
202
|
+
service: {
|
|
203
|
+
provider: {
|
|
204
|
+
name: 'aws',
|
|
205
|
+
region: 'us-east-1',
|
|
206
|
+
vpc: '${self:custom.vpc.${self:provider.stage}}'
|
|
207
|
+
},
|
|
208
|
+
plugins: ['serverless-kms-grants'],
|
|
209
|
+
custom: {},
|
|
210
|
+
functions: {}
|
|
211
|
+
},
|
|
212
|
+
processedInput: { commands: [] },
|
|
213
|
+
getProvider: jest.fn(() => ({})),
|
|
214
|
+
extendConfiguration: jest.fn()
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
const plugin = new FriggServerlessPlugin(mockServerless, { stage: 'test' });
|
|
218
|
+
|
|
219
|
+
// Mock BuildTimeDiscovery
|
|
220
|
+
const mockBuildTimeDiscovery = {
|
|
221
|
+
preBuildHook: jest.fn().mockResolvedValue(mockAWSResources)
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
jest.doMock('./build-time-discovery', () => ({
|
|
225
|
+
BuildTimeDiscovery: jest.fn(() => mockBuildTimeDiscovery)
|
|
226
|
+
}));
|
|
227
|
+
|
|
228
|
+
// Test the beforePackageInitialize hook
|
|
229
|
+
await plugin.beforePackageInitialize();
|
|
230
|
+
|
|
231
|
+
expect(mockBuildTimeDiscovery.preBuildHook).toHaveBeenCalledWith(
|
|
232
|
+
expect.objectContaining({
|
|
233
|
+
vpc: { enable: true },
|
|
234
|
+
encryption: { useDefaultKMSForFieldLevelEncryption: true }
|
|
235
|
+
}),
|
|
236
|
+
'us-east-1'
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
expect(mockServerless.cli.log).toHaveBeenCalledWith('AWS discovery completed successfully');
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
it('should handle plugin discovery failure gracefully', async () => {
|
|
243
|
+
const mockServerless = {
|
|
244
|
+
cli: { log: jest.fn() },
|
|
245
|
+
service: {
|
|
246
|
+
provider: {
|
|
247
|
+
name: 'aws',
|
|
248
|
+
region: 'us-east-1',
|
|
249
|
+
vpc: '${self:custom.vpc}'
|
|
250
|
+
},
|
|
251
|
+
plugins: [],
|
|
252
|
+
custom: {},
|
|
253
|
+
functions: {}
|
|
254
|
+
},
|
|
255
|
+
processedInput: { commands: [] },
|
|
256
|
+
getProvider: jest.fn(() => ({})),
|
|
257
|
+
extendConfiguration: jest.fn()
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
const plugin = new FriggServerlessPlugin(mockServerless, { stage: 'test' });
|
|
261
|
+
|
|
262
|
+
// Mock BuildTimeDiscovery to fail
|
|
263
|
+
const mockBuildTimeDiscovery = {
|
|
264
|
+
preBuildHook: jest.fn().mockRejectedValue(new Error('AWS API Error'))
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
jest.doMock('./build-time-discovery', () => ({
|
|
268
|
+
BuildTimeDiscovery: jest.fn(() => mockBuildTimeDiscovery)
|
|
269
|
+
}));
|
|
270
|
+
|
|
271
|
+
await plugin.beforePackageInitialize();
|
|
272
|
+
|
|
273
|
+
expect(mockServerless.cli.log).toHaveBeenCalledWith('AWS discovery failed, continuing with deployment...');
|
|
274
|
+
expect(mockServerless.cli.log).toHaveBeenCalledWith('Using fallback values for AWS resources');
|
|
275
|
+
|
|
276
|
+
// Verify fallback values are set
|
|
277
|
+
expect(process.env.AWS_DISCOVERY_VPC_ID).toBe('vpc-fallback');
|
|
278
|
+
expect(process.env.AWS_DISCOVERY_KMS_KEY_ID).toBe('arn:aws:kms:*:*:key/*');
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
describe('Template Variable Replacement', () => {
|
|
283
|
+
it('should replace environment variable placeholders with actual values', () => {
|
|
284
|
+
const template = `
|
|
285
|
+
provider:
|
|
286
|
+
vpc:
|
|
287
|
+
securityGroupIds:
|
|
288
|
+
- \${env:AWS_DISCOVERY_SECURITY_GROUP_ID}
|
|
289
|
+
subnetIds:
|
|
290
|
+
- \${env:AWS_DISCOVERY_SUBNET_ID_1}
|
|
291
|
+
- \${env:AWS_DISCOVERY_SUBNET_ID_2}
|
|
292
|
+
environment:
|
|
293
|
+
KMS_KEY_ARN: \${env:AWS_DISCOVERY_KMS_KEY_ID}
|
|
294
|
+
resources:
|
|
295
|
+
VPCEndpoint:
|
|
296
|
+
Properties:
|
|
297
|
+
VpcId: \${env:AWS_DISCOVERY_VPC_ID}
|
|
298
|
+
`;
|
|
299
|
+
|
|
300
|
+
// Set environment variables
|
|
301
|
+
process.env.AWS_DISCOVERY_VPC_ID = mockAWSResources.defaultVpcId;
|
|
302
|
+
process.env.AWS_DISCOVERY_SECURITY_GROUP_ID = mockAWSResources.defaultSecurityGroupId;
|
|
303
|
+
process.env.AWS_DISCOVERY_SUBNET_ID_1 = mockAWSResources.privateSubnetId1;
|
|
304
|
+
process.env.AWS_DISCOVERY_SUBNET_ID_2 = mockAWSResources.privateSubnetId2;
|
|
305
|
+
process.env.AWS_DISCOVERY_KMS_KEY_ID = mockAWSResources.defaultKmsKeyId;
|
|
306
|
+
|
|
307
|
+
// In a real deployment, serverless framework would resolve these environment variables
|
|
308
|
+
// For testing, we can verify the placeholders are correctly formatted
|
|
309
|
+
expect(template).toContain('${env:AWS_DISCOVERY_VPC_ID}');
|
|
310
|
+
expect(template).toContain('${env:AWS_DISCOVERY_SECURITY_GROUP_ID}');
|
|
311
|
+
expect(template).toContain('${env:AWS_DISCOVERY_SUBNET_ID_1}');
|
|
312
|
+
expect(template).toContain('${env:AWS_DISCOVERY_SUBNET_ID_2}');
|
|
313
|
+
expect(template).toContain('${env:AWS_DISCOVERY_KMS_KEY_ID}');
|
|
314
|
+
|
|
315
|
+
// Clean up
|
|
316
|
+
delete process.env.AWS_DISCOVERY_VPC_ID;
|
|
317
|
+
delete process.env.AWS_DISCOVERY_SECURITY_GROUP_ID;
|
|
318
|
+
delete process.env.AWS_DISCOVERY_SUBNET_ID_1;
|
|
319
|
+
delete process.env.AWS_DISCOVERY_SUBNET_ID_2;
|
|
320
|
+
delete process.env.AWS_DISCOVERY_KMS_KEY_ID;
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
describe('Error Scenarios', () => {
|
|
325
|
+
it('should handle AWS discovery timeout gracefully', async () => {
|
|
326
|
+
const mockFailingDiscovery = {
|
|
327
|
+
discoverResources: jest.fn().mockRejectedValue(new Error('Request timeout'))
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
jest.doMock('./aws-discovery', () => ({
|
|
331
|
+
AWSDiscovery: jest.fn(() => mockFailingDiscovery)
|
|
332
|
+
}));
|
|
333
|
+
|
|
334
|
+
const appDefinition = {
|
|
335
|
+
vpc: { enable: true },
|
|
336
|
+
integrations: []
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
await expect(buildTimeDiscovery.preBuildHook(appDefinition, 'us-east-1')).rejects.toThrow('Request timeout');
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
it('should handle partial AWS resource discovery', async () => {
|
|
343
|
+
const partialResources = {
|
|
344
|
+
defaultVpcId: 'vpc-12345678',
|
|
345
|
+
defaultSecurityGroupId: 'sg-12345678',
|
|
346
|
+
privateSubnetId1: 'subnet-1',
|
|
347
|
+
privateSubnetId2: 'subnet-1', // Same subnet used twice
|
|
348
|
+
privateRouteTableId: 'rtb-12345678',
|
|
349
|
+
defaultKmsKeyId: '*' // Fallback KMS key
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
mockAWSDiscovery.discoverResources.mockResolvedValue(partialResources);
|
|
353
|
+
|
|
354
|
+
const appDefinition = {
|
|
355
|
+
vpc: { enable: true },
|
|
356
|
+
encryption: { useDefaultKMSForFieldLevelEncryption: true },
|
|
357
|
+
integrations: []
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
const result = await buildTimeDiscovery.preBuildHook(appDefinition, 'us-east-1');
|
|
361
|
+
|
|
362
|
+
expect(result).toEqual(partialResources);
|
|
363
|
+
expect(result.privateSubnetId2).toBe(result.privateSubnetId1); // Should handle single subnet scenario
|
|
364
|
+
expect(result.defaultKmsKeyId).toBe('*'); // Should handle KMS fallback
|
|
365
|
+
});
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
describe('Multi-Region Support', () => {
|
|
369
|
+
it('should support different AWS regions', async () => {
|
|
370
|
+
const appDefinition = {
|
|
371
|
+
vpc: { enable: true },
|
|
372
|
+
integrations: []
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
const euWestDiscovery = new BuildTimeDiscovery('eu-west-1');
|
|
376
|
+
|
|
377
|
+
await euWestDiscovery.preBuildHook(appDefinition, 'eu-west-1');
|
|
378
|
+
|
|
379
|
+
// Verify that AWSDiscovery was instantiated with correct region
|
|
380
|
+
expect(mockAWSDiscovery.discoverResources).toHaveBeenCalled();
|
|
381
|
+
});
|
|
382
|
+
});
|
|
383
|
+
});
|