@friggframework/devtools 2.0.0--canary.454.16de0f8.0 → 2.0.0--canary.458.c150d9a.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/frigg-cli/__tests__/unit/commands/db-setup.test.js +1 -1
- package/frigg-cli/__tests__/unit/utils/prisma-runner.test.js +486 -0
- package/frigg-cli/db-setup-command/index.js +1 -8
- package/frigg-cli/utils/database-validator.js +1 -4
- package/frigg-cli/utils/prisma-runner.js +280 -0
- package/infrastructure/README.md +0 -51
- package/infrastructure/aws-discovery.js +2 -504
- package/infrastructure/aws-discovery.test.js +1 -447
- package/infrastructure/serverless-template.js +11 -412
- package/infrastructure/serverless-template.test.js +0 -91
- package/management-ui/src/App.jsx +1 -85
- package/management-ui/src/hooks/useFrigg.jsx +1 -215
- package/package.json +6 -8
- package/infrastructure/POSTGRES-CONFIGURATION.md +0 -630
- package/infrastructure/__tests__/postgres-config.test.js +0 -914
- package/infrastructure/scripts/build-prisma-layer.js +0 -394
|
@@ -21,23 +21,11 @@ const {
|
|
|
21
21
|
STSClient,
|
|
22
22
|
GetCallerIdentityCommand
|
|
23
23
|
} = require('@aws-sdk/client-sts');
|
|
24
|
-
const {
|
|
25
|
-
RDSClient,
|
|
26
|
-
DescribeDBClustersCommand,
|
|
27
|
-
DescribeDBSubnetGroupsCommand
|
|
28
|
-
} = require('@aws-sdk/client-rds');
|
|
29
|
-
const {
|
|
30
|
-
SecretsManagerClient,
|
|
31
|
-
ListSecretsCommand,
|
|
32
|
-
DescribeSecretCommand
|
|
33
|
-
} = require('@aws-sdk/client-secrets-manager');
|
|
34
24
|
|
|
35
25
|
// Create mock clients
|
|
36
26
|
const ec2Mock = mockClient(EC2Client);
|
|
37
27
|
const kmsMock = mockClient(KMSClient);
|
|
38
28
|
const stsMock = mockClient(STSClient);
|
|
39
|
-
const rdsMock = mockClient(RDSClient);
|
|
40
|
-
const secretsManagerMock = mockClient(SecretsManagerClient);
|
|
41
29
|
|
|
42
30
|
describe('AWSDiscovery', () => {
|
|
43
31
|
let discovery;
|
|
@@ -47,71 +35,10 @@ describe('AWSDiscovery', () => {
|
|
|
47
35
|
ec2Mock.reset();
|
|
48
36
|
kmsMock.reset();
|
|
49
37
|
stsMock.reset();
|
|
50
|
-
rdsMock.reset();
|
|
51
|
-
secretsManagerMock.reset();
|
|
52
|
-
|
|
53
|
-
// Set up default STS mock for credential validation
|
|
54
|
-
// This is needed because validateCredentials() is now called in discoverResources()
|
|
55
|
-
stsMock.on(GetCallerIdentityCommand).resolves({
|
|
56
|
-
Account: '123456789012',
|
|
57
|
-
Arn: 'arn:aws:iam::123456789012:user/test-user',
|
|
58
|
-
UserId: 'AIDAI1234567890EXAMPLE'
|
|
59
|
-
});
|
|
60
38
|
|
|
61
39
|
discovery = new AWSDiscovery('us-east-1');
|
|
62
40
|
});
|
|
63
41
|
|
|
64
|
-
describe('validateCredentials', () => {
|
|
65
|
-
it('should return valid credentials info when credentials are valid', async () => {
|
|
66
|
-
const mockResponse = {
|
|
67
|
-
Account: '123456789012',
|
|
68
|
-
Arn: 'arn:aws:iam::123456789012:user/test-user',
|
|
69
|
-
UserId: 'AIDAI1234567890EXAMPLE'
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
stsMock.reset();
|
|
73
|
-
stsMock.on(GetCallerIdentityCommand).resolves(mockResponse);
|
|
74
|
-
|
|
75
|
-
const result = await discovery.validateCredentials();
|
|
76
|
-
|
|
77
|
-
expect(result).toEqual({
|
|
78
|
-
valid: true,
|
|
79
|
-
accountId: '123456789012',
|
|
80
|
-
arn: 'arn:aws:iam::123456789012:user/test-user',
|
|
81
|
-
userId: 'AIDAI1234567890EXAMPLE'
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it('should throw descriptive error for expired credentials', async () => {
|
|
86
|
-
stsMock.reset();
|
|
87
|
-
const expiredError = new Error('Request has expired.');
|
|
88
|
-
expiredError.Code = 'RequestExpired';
|
|
89
|
-
stsMock.on(GetCallerIdentityCommand).rejects(expiredError);
|
|
90
|
-
|
|
91
|
-
await expect(discovery.validateCredentials())
|
|
92
|
-
.rejects.toThrow('AWS credential validation failed: Request has expired.');
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it('should throw descriptive error for invalid credentials', async () => {
|
|
96
|
-
stsMock.reset();
|
|
97
|
-
const invalidError = new Error('The security token included in the request is invalid');
|
|
98
|
-
invalidError.Code = 'InvalidClientTokenId';
|
|
99
|
-
stsMock.on(GetCallerIdentityCommand).rejects(invalidError);
|
|
100
|
-
|
|
101
|
-
await expect(discovery.validateCredentials())
|
|
102
|
-
.rejects.toThrow('AWS credential validation failed');
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it('should throw descriptive error when credentials cannot be loaded', async () => {
|
|
106
|
-
stsMock.reset();
|
|
107
|
-
const noCredsError = new Error('Could not load credentials from any providers');
|
|
108
|
-
stsMock.on(GetCallerIdentityCommand).rejects(noCredsError);
|
|
109
|
-
|
|
110
|
-
await expect(discovery.validateCredentials())
|
|
111
|
-
.rejects.toThrow('AWS credential validation failed');
|
|
112
|
-
});
|
|
113
|
-
});
|
|
114
|
-
|
|
115
42
|
describe('getAccountId', () => {
|
|
116
43
|
it('should return AWS account ID', async () => {
|
|
117
44
|
const mockAccountId = '123456789012';
|
|
@@ -1173,7 +1100,7 @@ describe('AWSDiscovery', () => {
|
|
|
1173
1100
|
jest.spyOn(discovery, 'isSubnetPrivate')
|
|
1174
1101
|
.mockResolvedValue(false); // All subnets are public
|
|
1175
1102
|
|
|
1176
|
-
const result = await discovery.discoverResources({
|
|
1103
|
+
const result = await discovery.discoverResources({ selfHeal: true });
|
|
1177
1104
|
|
|
1178
1105
|
// Verify that findPrivateSubnets was called with autoConvert=true
|
|
1179
1106
|
expect(discovery.findPrivateSubnets).toHaveBeenCalledWith('vpc-12345678', true);
|
|
@@ -1290,377 +1217,4 @@ describe('AWSDiscovery', () => {
|
|
|
1290
1217
|
expect(customDiscovery.region).toBe('us-west-2');
|
|
1291
1218
|
});
|
|
1292
1219
|
});
|
|
1293
|
-
|
|
1294
|
-
describe('Aurora PostgreSQL Discovery', () => {
|
|
1295
|
-
describe('findAuroraCluster', () => {
|
|
1296
|
-
it('should return cluster matching specific clusterIdentifier', async () => {
|
|
1297
|
-
const mockClusters = {
|
|
1298
|
-
DBClusters: [
|
|
1299
|
-
{
|
|
1300
|
-
DBClusterIdentifier: 'target-cluster',
|
|
1301
|
-
Engine: 'aurora-postgresql',
|
|
1302
|
-
Status: 'available',
|
|
1303
|
-
Endpoint: 'target.cluster.us-east-1.rds.amazonaws.com',
|
|
1304
|
-
Port: 5432,
|
|
1305
|
-
EngineVersion: '15.3',
|
|
1306
|
-
MasterUsername: 'admin',
|
|
1307
|
-
DatabaseName: 'mydb',
|
|
1308
|
-
TagList: []
|
|
1309
|
-
},
|
|
1310
|
-
{
|
|
1311
|
-
DBClusterIdentifier: 'other-cluster',
|
|
1312
|
-
Engine: 'aurora-postgresql',
|
|
1313
|
-
Status: 'available',
|
|
1314
|
-
Endpoint: 'other.cluster.us-east-1.rds.amazonaws.com',
|
|
1315
|
-
Port: 5432,
|
|
1316
|
-
TagList: []
|
|
1317
|
-
}
|
|
1318
|
-
]
|
|
1319
|
-
};
|
|
1320
|
-
|
|
1321
|
-
rdsMock.on(DescribeDBClustersCommand).resolves(mockClusters);
|
|
1322
|
-
|
|
1323
|
-
const result = await discovery.findAuroraCluster('target-cluster');
|
|
1324
|
-
|
|
1325
|
-
expect(result).toBeDefined();
|
|
1326
|
-
expect(result.identifier).toBe('target-cluster');
|
|
1327
|
-
expect(result.endpoint).toBe('target.cluster.us-east-1.rds.amazonaws.com');
|
|
1328
|
-
expect(result.port).toBe(5432);
|
|
1329
|
-
});
|
|
1330
|
-
|
|
1331
|
-
it('should prioritize Frigg-managed cluster with matching service+stage tags', async () => {
|
|
1332
|
-
const mockClusters = {
|
|
1333
|
-
DBClusters: [
|
|
1334
|
-
{
|
|
1335
|
-
DBClusterIdentifier: 'generic-frigg-cluster',
|
|
1336
|
-
Engine: 'aurora-postgresql',
|
|
1337
|
-
Status: 'available',
|
|
1338
|
-
TagList: [
|
|
1339
|
-
{ Key: 'ManagedBy', Value: 'Frigg' }
|
|
1340
|
-
]
|
|
1341
|
-
},
|
|
1342
|
-
{
|
|
1343
|
-
DBClusterIdentifier: 'matching-cluster',
|
|
1344
|
-
Engine: 'aurora-postgresql',
|
|
1345
|
-
Status: 'available',
|
|
1346
|
-
Endpoint: 'matching.cluster.us-east-1.rds.amazonaws.com',
|
|
1347
|
-
Port: 5432,
|
|
1348
|
-
TagList: [
|
|
1349
|
-
{ Key: 'ManagedBy', Value: 'Frigg' },
|
|
1350
|
-
{ Key: 'Service', Value: 'test-service' },
|
|
1351
|
-
{ Key: 'Stage', Value: 'dev' }
|
|
1352
|
-
]
|
|
1353
|
-
},
|
|
1354
|
-
{
|
|
1355
|
-
DBClusterIdentifier: 'non-frigg-cluster',
|
|
1356
|
-
Engine: 'aurora-postgresql',
|
|
1357
|
-
Status: 'available',
|
|
1358
|
-
TagList: []
|
|
1359
|
-
}
|
|
1360
|
-
]
|
|
1361
|
-
};
|
|
1362
|
-
|
|
1363
|
-
rdsMock.on(DescribeDBClustersCommand).resolves(mockClusters);
|
|
1364
|
-
|
|
1365
|
-
const result = await discovery.findAuroraCluster(null, 'test-service', 'dev');
|
|
1366
|
-
|
|
1367
|
-
expect(result).toBeDefined();
|
|
1368
|
-
expect(result.identifier).toBe('matching-cluster');
|
|
1369
|
-
});
|
|
1370
|
-
|
|
1371
|
-
it('should fall back to any Frigg-managed cluster', async () => {
|
|
1372
|
-
const mockClusters = {
|
|
1373
|
-
DBClusters: [
|
|
1374
|
-
{
|
|
1375
|
-
DBClusterIdentifier: 'non-frigg-cluster',
|
|
1376
|
-
Engine: 'aurora-postgresql',
|
|
1377
|
-
Status: 'available',
|
|
1378
|
-
TagList: []
|
|
1379
|
-
},
|
|
1380
|
-
{
|
|
1381
|
-
DBClusterIdentifier: 'frigg-cluster',
|
|
1382
|
-
Engine: 'aurora-postgresql',
|
|
1383
|
-
Status: 'available',
|
|
1384
|
-
Endpoint: 'frigg.cluster.us-east-1.rds.amazonaws.com',
|
|
1385
|
-
Port: 5432,
|
|
1386
|
-
TagList: [
|
|
1387
|
-
{ Key: 'ManagedBy', Value: 'Frigg' }
|
|
1388
|
-
]
|
|
1389
|
-
}
|
|
1390
|
-
]
|
|
1391
|
-
};
|
|
1392
|
-
|
|
1393
|
-
rdsMock.on(DescribeDBClustersCommand).resolves(mockClusters);
|
|
1394
|
-
|
|
1395
|
-
const result = await discovery.findAuroraCluster(null, 'different-service', 'prod');
|
|
1396
|
-
|
|
1397
|
-
expect(result).toBeDefined();
|
|
1398
|
-
expect(result.identifier).toBe('frigg-cluster');
|
|
1399
|
-
});
|
|
1400
|
-
|
|
1401
|
-
it('should return first available cluster as last fallback', async () => {
|
|
1402
|
-
const mockClusters = {
|
|
1403
|
-
DBClusters: [
|
|
1404
|
-
{
|
|
1405
|
-
DBClusterIdentifier: 'first-cluster',
|
|
1406
|
-
Engine: 'aurora-postgresql',
|
|
1407
|
-
Status: 'available',
|
|
1408
|
-
Endpoint: 'first.cluster.us-east-1.rds.amazonaws.com',
|
|
1409
|
-
Port: 5432,
|
|
1410
|
-
TagList: []
|
|
1411
|
-
},
|
|
1412
|
-
{
|
|
1413
|
-
DBClusterIdentifier: 'second-cluster',
|
|
1414
|
-
Engine: 'aurora-postgresql',
|
|
1415
|
-
Status: 'available',
|
|
1416
|
-
TagList: []
|
|
1417
|
-
}
|
|
1418
|
-
]
|
|
1419
|
-
};
|
|
1420
|
-
|
|
1421
|
-
rdsMock.on(DescribeDBClustersCommand).resolves(mockClusters);
|
|
1422
|
-
|
|
1423
|
-
const result = await discovery.findAuroraCluster();
|
|
1424
|
-
|
|
1425
|
-
expect(result).toBeDefined();
|
|
1426
|
-
expect(result.identifier).toBe('first-cluster');
|
|
1427
|
-
});
|
|
1428
|
-
|
|
1429
|
-
it('should return null when no clusters found', async () => {
|
|
1430
|
-
rdsMock.on(DescribeDBClustersCommand).resolves({ DBClusters: [] });
|
|
1431
|
-
|
|
1432
|
-
const result = await discovery.findAuroraCluster();
|
|
1433
|
-
|
|
1434
|
-
expect(result).toBeNull();
|
|
1435
|
-
});
|
|
1436
|
-
});
|
|
1437
|
-
|
|
1438
|
-
describe('findDBSubnetGroup', () => {
|
|
1439
|
-
it('should return Frigg-managed subnet group in VPC', async () => {
|
|
1440
|
-
const mockSubnetGroups = {
|
|
1441
|
-
DBSubnetGroups: [
|
|
1442
|
-
{
|
|
1443
|
-
DBSubnetGroupName: 'other-subnet-group',
|
|
1444
|
-
VpcId: 'vpc-12345',
|
|
1445
|
-
Subnets: [{ SubnetIdentifier: 'subnet-1' }],
|
|
1446
|
-
Tags: []
|
|
1447
|
-
},
|
|
1448
|
-
{
|
|
1449
|
-
DBSubnetGroupName: 'frigg-subnet-group',
|
|
1450
|
-
VpcId: 'vpc-12345',
|
|
1451
|
-
Subnets: [
|
|
1452
|
-
{ SubnetIdentifier: 'subnet-1' },
|
|
1453
|
-
{ SubnetIdentifier: 'subnet-2' }
|
|
1454
|
-
],
|
|
1455
|
-
DBSubnetGroupDescription: 'Frigg managed',
|
|
1456
|
-
Tags: [
|
|
1457
|
-
{ Key: 'ManagedBy', Value: 'Frigg' }
|
|
1458
|
-
]
|
|
1459
|
-
}
|
|
1460
|
-
]
|
|
1461
|
-
};
|
|
1462
|
-
|
|
1463
|
-
rdsMock.on(DescribeDBSubnetGroupsCommand).resolves(mockSubnetGroups);
|
|
1464
|
-
|
|
1465
|
-
const result = await discovery.findDBSubnetGroup('vpc-12345');
|
|
1466
|
-
|
|
1467
|
-
expect(result).toBeDefined();
|
|
1468
|
-
expect(result.name).toBe('frigg-subnet-group');
|
|
1469
|
-
expect(result.vpcId).toBe('vpc-12345');
|
|
1470
|
-
expect(result.subnets).toEqual(['subnet-1', 'subnet-2']);
|
|
1471
|
-
});
|
|
1472
|
-
|
|
1473
|
-
it('should return first available subnet group as fallback', async () => {
|
|
1474
|
-
const mockSubnetGroups = {
|
|
1475
|
-
DBSubnetGroups: [
|
|
1476
|
-
{
|
|
1477
|
-
DBSubnetGroupName: 'first-subnet-group',
|
|
1478
|
-
VpcId: 'vpc-12345',
|
|
1479
|
-
Subnets: [{ SubnetIdentifier: 'subnet-a' }],
|
|
1480
|
-
DBSubnetGroupDescription: 'First group',
|
|
1481
|
-
Tags: []
|
|
1482
|
-
}
|
|
1483
|
-
]
|
|
1484
|
-
};
|
|
1485
|
-
|
|
1486
|
-
rdsMock.on(DescribeDBSubnetGroupsCommand).resolves(mockSubnetGroups);
|
|
1487
|
-
|
|
1488
|
-
const result = await discovery.findDBSubnetGroup('vpc-12345');
|
|
1489
|
-
|
|
1490
|
-
expect(result).toBeDefined();
|
|
1491
|
-
expect(result.name).toBe('first-subnet-group');
|
|
1492
|
-
});
|
|
1493
|
-
|
|
1494
|
-
it('should return null when no subnet groups found in VPC', async () => {
|
|
1495
|
-
const mockSubnetGroups = {
|
|
1496
|
-
DBSubnetGroups: [
|
|
1497
|
-
{
|
|
1498
|
-
DBSubnetGroupName: 'wrong-vpc-group',
|
|
1499
|
-
VpcId: 'vpc-wrong',
|
|
1500
|
-
Subnets: [{ SubnetIdentifier: 'subnet-x' }],
|
|
1501
|
-
Tags: []
|
|
1502
|
-
}
|
|
1503
|
-
]
|
|
1504
|
-
};
|
|
1505
|
-
|
|
1506
|
-
rdsMock.on(DescribeDBSubnetGroupsCommand).resolves(mockSubnetGroups);
|
|
1507
|
-
|
|
1508
|
-
const result = await discovery.findDBSubnetGroup('vpc-12345');
|
|
1509
|
-
|
|
1510
|
-
expect(result).toBeNull();
|
|
1511
|
-
});
|
|
1512
|
-
});
|
|
1513
|
-
|
|
1514
|
-
describe('findDatabaseSecret', () => {
|
|
1515
|
-
it('should return secret with matching service+stage tags', async () => {
|
|
1516
|
-
const mockSecrets = {
|
|
1517
|
-
SecretList: [
|
|
1518
|
-
{
|
|
1519
|
-
ARN: 'arn:aws:secretsmanager:us-east-1:123:secret:generic-secret',
|
|
1520
|
-
Name: 'generic-aurora-secret',
|
|
1521
|
-
Tags: [
|
|
1522
|
-
{ Key: 'ManagedBy', Value: 'Frigg' }
|
|
1523
|
-
]
|
|
1524
|
-
},
|
|
1525
|
-
{
|
|
1526
|
-
ARN: 'arn:aws:secretsmanager:us-east-1:123:secret:matching-secret',
|
|
1527
|
-
Name: 'test-service-dev-aurora-credentials',
|
|
1528
|
-
Tags: [
|
|
1529
|
-
{ Key: 'ManagedBy', Value: 'Frigg' },
|
|
1530
|
-
{ Key: 'Service', Value: 'test-service' },
|
|
1531
|
-
{ Key: 'Stage', Value: 'dev' }
|
|
1532
|
-
]
|
|
1533
|
-
}
|
|
1534
|
-
]
|
|
1535
|
-
};
|
|
1536
|
-
|
|
1537
|
-
secretsManagerMock.on(ListSecretsCommand).resolves(mockSecrets);
|
|
1538
|
-
|
|
1539
|
-
const result = await discovery.findDatabaseSecret('test-service', 'dev');
|
|
1540
|
-
|
|
1541
|
-
expect(result).toBeDefined();
|
|
1542
|
-
expect(result.name).toBe('test-service-dev-aurora-credentials');
|
|
1543
|
-
expect(result.arn).toBe('arn:aws:secretsmanager:us-east-1:123:secret:matching-secret');
|
|
1544
|
-
});
|
|
1545
|
-
|
|
1546
|
-
it('should return any Frigg-managed database secret as fallback', async () => {
|
|
1547
|
-
const mockSecrets = {
|
|
1548
|
-
SecretList: [
|
|
1549
|
-
{
|
|
1550
|
-
ARN: 'arn:aws:secretsmanager:us-east-1:123:secret:frigg-secret',
|
|
1551
|
-
Name: 'frigg-database-credentials',
|
|
1552
|
-
Tags: [
|
|
1553
|
-
{ Key: 'ManagedBy', Value: 'Frigg' }
|
|
1554
|
-
]
|
|
1555
|
-
}
|
|
1556
|
-
]
|
|
1557
|
-
};
|
|
1558
|
-
|
|
1559
|
-
secretsManagerMock.on(ListSecretsCommand).resolves(mockSecrets);
|
|
1560
|
-
|
|
1561
|
-
const result = await discovery.findDatabaseSecret('different-service', 'staging');
|
|
1562
|
-
|
|
1563
|
-
expect(result).toBeDefined();
|
|
1564
|
-
expect(result.name).toBe('frigg-database-credentials');
|
|
1565
|
-
});
|
|
1566
|
-
|
|
1567
|
-
it('should return null when no Frigg database secrets found', async () => {
|
|
1568
|
-
const mockSecrets = {
|
|
1569
|
-
SecretList: [
|
|
1570
|
-
{
|
|
1571
|
-
ARN: 'arn:aws:secretsmanager:us-east-1:123:secret:other',
|
|
1572
|
-
Name: 'other-secret',
|
|
1573
|
-
Tags: []
|
|
1574
|
-
}
|
|
1575
|
-
]
|
|
1576
|
-
};
|
|
1577
|
-
|
|
1578
|
-
secretsManagerMock.on(ListSecretsCommand).resolves(mockSecrets);
|
|
1579
|
-
|
|
1580
|
-
const result = await discovery.findDatabaseSecret('test-service', 'dev');
|
|
1581
|
-
|
|
1582
|
-
expect(result).toBeNull();
|
|
1583
|
-
});
|
|
1584
|
-
});
|
|
1585
|
-
|
|
1586
|
-
describe('discoverAuroraResources', () => {
|
|
1587
|
-
it('should return needsCreation=true in create-new mode', async () => {
|
|
1588
|
-
const result = await discovery.discoverAuroraResources({
|
|
1589
|
-
vpcId: 'vpc-123',
|
|
1590
|
-
management: 'create-new'
|
|
1591
|
-
});
|
|
1592
|
-
|
|
1593
|
-
expect(result.needsCreation).toBe(true);
|
|
1594
|
-
expect(result.clusterIdentifier).toBeNull();
|
|
1595
|
-
});
|
|
1596
|
-
|
|
1597
|
-
it('should discover all resources in discover mode', async () => {
|
|
1598
|
-
const mockClusters = {
|
|
1599
|
-
DBClusters: [{
|
|
1600
|
-
DBClusterIdentifier: 'discovered-cluster',
|
|
1601
|
-
Engine: 'aurora-postgresql',
|
|
1602
|
-
Status: 'available',
|
|
1603
|
-
Endpoint: 'discovered.cluster.us-east-1.rds.amazonaws.com',
|
|
1604
|
-
Port: 5432,
|
|
1605
|
-
EngineVersion: '15.3',
|
|
1606
|
-
TagList: []
|
|
1607
|
-
}]
|
|
1608
|
-
};
|
|
1609
|
-
|
|
1610
|
-
const mockSubnetGroups = {
|
|
1611
|
-
DBSubnetGroups: [{
|
|
1612
|
-
DBSubnetGroupName: 'discovered-subnet-group',
|
|
1613
|
-
VpcId: 'vpc-123',
|
|
1614
|
-
Subnets: [{ SubnetIdentifier: 'subnet-1' }, { SubnetIdentifier: 'subnet-2' }],
|
|
1615
|
-
Tags: []
|
|
1616
|
-
}]
|
|
1617
|
-
};
|
|
1618
|
-
|
|
1619
|
-
const mockSecrets = {
|
|
1620
|
-
SecretList: [{
|
|
1621
|
-
ARN: 'arn:aws:secretsmanager:us-east-1:123:secret:discovered-secret',
|
|
1622
|
-
Name: 'discovered-aurora-credentials',
|
|
1623
|
-
Tags: [{ Key: 'ManagedBy', Value: 'Frigg' }]
|
|
1624
|
-
}]
|
|
1625
|
-
};
|
|
1626
|
-
|
|
1627
|
-
rdsMock.on(DescribeDBClustersCommand).resolves(mockClusters);
|
|
1628
|
-
rdsMock.on(DescribeDBSubnetGroupsCommand).resolves(mockSubnetGroups);
|
|
1629
|
-
secretsManagerMock.on(ListSecretsCommand).resolves(mockSecrets);
|
|
1630
|
-
|
|
1631
|
-
const result = await discovery.discoverAuroraResources({
|
|
1632
|
-
vpcId: 'vpc-123',
|
|
1633
|
-
management: 'discover'
|
|
1634
|
-
});
|
|
1635
|
-
|
|
1636
|
-
expect(result.needsCreation).toBe(false);
|
|
1637
|
-
expect(result.clusterIdentifier).toBe('discovered-cluster');
|
|
1638
|
-
expect(result.endpoint).toBe('discovered.cluster.us-east-1.rds.amazonaws.com');
|
|
1639
|
-
expect(result.port).toBe(5432);
|
|
1640
|
-
expect(result.dbSubnetGroupName).toBe('discovered-subnet-group');
|
|
1641
|
-
expect(result.secretArn).toBe('arn:aws:secretsmanager:us-east-1:123:secret:discovered-secret');
|
|
1642
|
-
});
|
|
1643
|
-
|
|
1644
|
-
it('should require clusterIdentifier in use-existing mode and throw error if missing', async () => {
|
|
1645
|
-
await expect(
|
|
1646
|
-
discovery.discoverAuroraResources({
|
|
1647
|
-
vpcId: 'vpc-123',
|
|
1648
|
-
management: 'use-existing'
|
|
1649
|
-
})
|
|
1650
|
-
).rejects.toThrow('clusterIdentifier is required');
|
|
1651
|
-
});
|
|
1652
|
-
|
|
1653
|
-
it('should return needsCreation=true when no cluster found in discover mode', async () => {
|
|
1654
|
-
rdsMock.on(DescribeDBClustersCommand).resolves({ DBClusters: [] });
|
|
1655
|
-
|
|
1656
|
-
const result = await discovery.discoverAuroraResources({
|
|
1657
|
-
vpcId: 'vpc-123',
|
|
1658
|
-
management: 'discover'
|
|
1659
|
-
});
|
|
1660
|
-
|
|
1661
|
-
expect(result.needsCreation).toBe(true);
|
|
1662
|
-
expect(result.clusterIdentifier).toBeNull();
|
|
1663
|
-
});
|
|
1664
|
-
});
|
|
1665
|
-
});
|
|
1666
1220
|
});
|