@friggframework/devtools 2.0.0--canary.461.84ff4f5.0 → 2.0.0--canary.461.ec909cf.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-discovery.js +42 -19
- package/infrastructure/domains/database/aurora-builder.js +307 -0
- package/infrastructure/domains/database/aurora-builder.test.js +482 -0
- package/infrastructure/domains/networking/vpc-builder.js +718 -0
- package/infrastructure/domains/networking/vpc-builder.test.js +772 -0
- package/infrastructure/domains/networking/vpc-discovery.js +159 -0
- package/infrastructure/domains/shared/providers/aws-provider-adapter.js +445 -0
- package/infrastructure/domains/shared/utilities/base-definition-factory.js +385 -0
- package/infrastructure/domains/shared/utilities/handler-path-resolver.js +129 -0
- package/infrastructure/infrastructure-composer.test.js +1895 -0
- package/infrastructure/serverless-template.js +226 -42
- package/infrastructure/serverless-template.test.js +3 -1
- package/package.json +6 -6
|
@@ -356,13 +356,31 @@ class AWSDiscovery {
|
|
|
356
356
|
console.warn(
|
|
357
357
|
'Please create a public subnet or use VPC endpoints instead'
|
|
358
358
|
);
|
|
359
|
-
return null;
|
|
359
|
+
return { primary: null, secondary: null, all: [] };
|
|
360
360
|
}
|
|
361
361
|
|
|
362
|
+
// Sort by AZ to get subnets in different zones
|
|
363
|
+
const sortedByAz = publicSubnets.sort((a, b) =>
|
|
364
|
+
a.AvailabilityZone.localeCompare(b.AvailabilityZone)
|
|
365
|
+
);
|
|
366
|
+
|
|
367
|
+
// Get subnets from different AZs if possible
|
|
368
|
+
const primary = sortedByAz[0];
|
|
369
|
+
const secondary = sortedByAz.find(s => s.AvailabilityZone !== primary.AvailabilityZone)
|
|
370
|
+
|| sortedByAz[1]
|
|
371
|
+
|| sortedByAz[0]; // Fallback to same subnet if only one exists
|
|
372
|
+
|
|
362
373
|
console.log(
|
|
363
|
-
`Found ${publicSubnets.length} public
|
|
374
|
+
`Found ${publicSubnets.length} public subnet(s)`
|
|
364
375
|
);
|
|
365
|
-
|
|
376
|
+
console.log(` Primary (NAT Gateway): ${primary.SubnetId} (${primary.AvailabilityZone})`);
|
|
377
|
+
if (secondary.SubnetId !== primary.SubnetId) {
|
|
378
|
+
console.log(` Secondary (Aurora): ${secondary.SubnetId} (${secondary.AvailabilityZone})`);
|
|
379
|
+
} else {
|
|
380
|
+
console.warn(` ⚠️ Only one public subnet found - Aurora public deployments will require creating a second subnet`);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
return { primary, secondary, all: publicSubnets };
|
|
366
384
|
} catch (error) {
|
|
367
385
|
console.error('Error finding public subnets:', error);
|
|
368
386
|
throw error;
|
|
@@ -1147,10 +1165,10 @@ class AWSDiscovery {
|
|
|
1147
1165
|
.join(', ')}`
|
|
1148
1166
|
);
|
|
1149
1167
|
|
|
1150
|
-
const
|
|
1151
|
-
if (
|
|
1168
|
+
const publicSubnets = await this.findPublicSubnets(vpc.VpcId);
|
|
1169
|
+
if (publicSubnets.primary) {
|
|
1152
1170
|
console.log(
|
|
1153
|
-
`\n✅ Found public subnet for NAT Gateway
|
|
1171
|
+
`\n✅ Found public subnet(s) for NAT Gateway and Aurora`
|
|
1154
1172
|
);
|
|
1155
1173
|
} else {
|
|
1156
1174
|
console.log(
|
|
@@ -1221,15 +1239,15 @@ class AWSDiscovery {
|
|
|
1221
1239
|
|
|
1222
1240
|
const subnet1IsActuallyPrivate = privateSubnets[0]
|
|
1223
1241
|
? await this.isSubnetPrivate(
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1242
|
+
privateSubnets[0].SubnetId,
|
|
1243
|
+
privateSubnets[0].VpcId || vpc.VpcId
|
|
1244
|
+
)
|
|
1227
1245
|
: false;
|
|
1228
1246
|
const subnet2IsActuallyPrivate = privateSubnets[1]
|
|
1229
1247
|
? await this.isSubnetPrivate(
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1248
|
+
privateSubnets[1].SubnetId,
|
|
1249
|
+
privateSubnets[1].VpcId || vpc.VpcId
|
|
1250
|
+
)
|
|
1233
1251
|
: subnet1IsActuallyPrivate;
|
|
1234
1252
|
|
|
1235
1253
|
const subnetStatus = {
|
|
@@ -1265,16 +1283,19 @@ class AWSDiscovery {
|
|
|
1265
1283
|
.join(', ')}`
|
|
1266
1284
|
);
|
|
1267
1285
|
console.log(
|
|
1268
|
-
` NAT Subnet: ${
|
|
1269
|
-
publicSubnet?.SubnetId || 'None (needs creation)'
|
|
1286
|
+
` NAT Subnet: ${publicSubnets.primary?.SubnetId || 'None (needs creation)'
|
|
1270
1287
|
}`
|
|
1271
1288
|
);
|
|
1289
|
+
if (publicSubnets.secondary && publicSubnets.secondary.SubnetId !== publicSubnets.primary?.SubnetId) {
|
|
1290
|
+
console.log(
|
|
1291
|
+
` Aurora Public Subnet 2: ${publicSubnets.secondary.SubnetId}`
|
|
1292
|
+
);
|
|
1293
|
+
}
|
|
1272
1294
|
console.log(
|
|
1273
1295
|
` NAT Gateway: ${natGatewayId || 'None (will be created)'}`
|
|
1274
1296
|
);
|
|
1275
1297
|
console.log(
|
|
1276
|
-
` Elastic IP: ${
|
|
1277
|
-
elasticIpAllocationId || 'None (will be allocated)'
|
|
1298
|
+
` Elastic IP: ${elasticIpAllocationId || 'None (will be allocated)'
|
|
1278
1299
|
}`
|
|
1279
1300
|
);
|
|
1280
1301
|
if (subnetStatus.requiresConversion) {
|
|
@@ -1289,7 +1310,9 @@ class AWSDiscovery {
|
|
|
1289
1310
|
privateSubnetId1: privateSubnets[0]?.SubnetId,
|
|
1290
1311
|
privateSubnetId2:
|
|
1291
1312
|
privateSubnets[1]?.SubnetId || privateSubnets[0]?.SubnetId,
|
|
1292
|
-
publicSubnetId:
|
|
1313
|
+
publicSubnetId: publicSubnets.primary?.SubnetId || null, // Keep for NAT Gateway backward compat
|
|
1314
|
+
publicSubnetId1: publicSubnets.primary?.SubnetId || null,
|
|
1315
|
+
publicSubnetId2: publicSubnets.secondary?.SubnetId || null,
|
|
1293
1316
|
privateRouteTableId: routeTable.RouteTableId,
|
|
1294
1317
|
defaultKmsKeyId: kmsKeyArn,
|
|
1295
1318
|
kmsAliasExists: kmsAliasExists,
|
|
@@ -1607,8 +1630,8 @@ class AWSDiscovery {
|
|
|
1607
1630
|
|
|
1608
1631
|
throw new Error(
|
|
1609
1632
|
`No private subnets found in VPC ${vpcId}. ` +
|
|
1610
|
-
|
|
1611
|
-
|
|
1633
|
+
`Found ${publicSubnets.length} public subnets. ` +
|
|
1634
|
+
`Lambda requires private subnets. Enable selfHeal or create private subnets.`
|
|
1612
1635
|
);
|
|
1613
1636
|
}
|
|
1614
1637
|
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aurora PostgreSQL Builder
|
|
3
|
+
*
|
|
4
|
+
* Domain Layer - Hexagonal Architecture
|
|
5
|
+
*
|
|
6
|
+
* Responsible for:
|
|
7
|
+
* - Aurora Serverless v2 cluster creation or discovery
|
|
8
|
+
* - Database subnet groups
|
|
9
|
+
* - Database security groups
|
|
10
|
+
* - Secrets Manager integration for credentials
|
|
11
|
+
* - Database connection environment variables
|
|
12
|
+
*
|
|
13
|
+
* Supports three management modes:
|
|
14
|
+
* 1. create-new: Creates new Aurora cluster
|
|
15
|
+
* 2. use-existing: Uses explicitly provided cluster
|
|
16
|
+
* 3. discover (default): Discovers existing cluster
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const { InfrastructureBuilder, ValidationResult } = require('../shared/base-builder');
|
|
20
|
+
|
|
21
|
+
class AuroraBuilder extends InfrastructureBuilder {
|
|
22
|
+
constructor() {
|
|
23
|
+
super();
|
|
24
|
+
this.name = 'AuroraBuilder';
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
shouldExecute(appDefinition) {
|
|
28
|
+
// Skip Aurora in local mode (when FRIGG_SKIP_AWS_DISCOVERY is set)
|
|
29
|
+
// Aurora is an AWS-specific service that should only be created in production
|
|
30
|
+
if (process.env.FRIGG_SKIP_AWS_DISCOVERY === 'true') {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return appDefinition.database?.postgres?.enable === true;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
getDependencies() {
|
|
38
|
+
return ['VpcBuilder']; // Aurora requires VPC to be configured first
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
validate(appDefinition) {
|
|
42
|
+
const result = new ValidationResult();
|
|
43
|
+
|
|
44
|
+
if (!appDefinition.database?.postgres) {
|
|
45
|
+
result.addError('PostgreSQL database configuration is missing');
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const dbConfig = appDefinition.database.postgres;
|
|
50
|
+
|
|
51
|
+
// Validate management mode
|
|
52
|
+
const validModes = ['discover', 'create-new', 'use-existing'];
|
|
53
|
+
const management = dbConfig.management || 'discover';
|
|
54
|
+
if (!validModes.includes(management)) {
|
|
55
|
+
result.addError(`Invalid database.postgres.management: "${management}"`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Validate use-existing requirements
|
|
59
|
+
if (management === 'use-existing' && !dbConfig.endpoint) {
|
|
60
|
+
result.addError('database.postgres.endpoint is required when management="use-existing"');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Validate capacity settings
|
|
64
|
+
if (dbConfig.minCapacity !== undefined && (dbConfig.minCapacity < 0.5 || dbConfig.minCapacity > 128)) {
|
|
65
|
+
result.addError('database.postgres.minCapacity must be between 0.5 and 128');
|
|
66
|
+
}
|
|
67
|
+
if (dbConfig.maxCapacity !== undefined && (dbConfig.maxCapacity < 0.5 || dbConfig.maxCapacity > 128)) {
|
|
68
|
+
result.addError('database.postgres.maxCapacity must be between 0.5 and 128');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Warn about public accessibility in production
|
|
72
|
+
if (dbConfig.publiclyAccessible === true) {
|
|
73
|
+
result.addWarning('database.postgres.publiclyAccessible=true is not recommended for production');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Build Aurora infrastructure
|
|
81
|
+
*/
|
|
82
|
+
async build(appDefinition, discoveredResources) {
|
|
83
|
+
console.log(`\n[${this.name}] Configuring Aurora PostgreSQL...`);
|
|
84
|
+
|
|
85
|
+
const dbConfig = appDefinition.database.postgres;
|
|
86
|
+
const management = dbConfig.management || 'discover';
|
|
87
|
+
|
|
88
|
+
console.log(` PostgreSQL Management Mode: ${management}`);
|
|
89
|
+
|
|
90
|
+
const result = {
|
|
91
|
+
resources: {},
|
|
92
|
+
iamStatements: [],
|
|
93
|
+
environment: {},
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// Handle different management modes
|
|
97
|
+
switch (management) {
|
|
98
|
+
case 'create-new':
|
|
99
|
+
await this.createNewAurora(appDefinition, discoveredResources, result);
|
|
100
|
+
break;
|
|
101
|
+
case 'use-existing':
|
|
102
|
+
await this.useExistingAurora(appDefinition, discoveredResources, result);
|
|
103
|
+
break;
|
|
104
|
+
case 'discover':
|
|
105
|
+
default:
|
|
106
|
+
await this.discoverAurora(appDefinition, discoveredResources, result);
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
console.log(`[${this.name}] ✅ Aurora PostgreSQL configuration completed`);
|
|
111
|
+
return result;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Create new Aurora cluster
|
|
116
|
+
*/
|
|
117
|
+
async createNewAurora(appDefinition, discoveredResources, result) {
|
|
118
|
+
console.log(' Creating new Aurora Serverless v2 cluster...');
|
|
119
|
+
|
|
120
|
+
const dbConfig = appDefinition.database.postgres;
|
|
121
|
+
const publiclyAccessible = dbConfig.publiclyAccessible === true;
|
|
122
|
+
|
|
123
|
+
// Get subnet IDs for DB Subnet Group
|
|
124
|
+
const subnetIds = publiclyAccessible
|
|
125
|
+
? [discoveredResources.publicSubnetId1, discoveredResources.publicSubnetId2]
|
|
126
|
+
: [discoveredResources.privateSubnetId1, discoveredResources.privateSubnetId2];
|
|
127
|
+
|
|
128
|
+
if (!subnetIds[0] || !subnetIds[1]) {
|
|
129
|
+
throw new Error(
|
|
130
|
+
`Aurora requires 2 ${publiclyAccessible ? 'public' : 'private'} subnets in different AZs. ` +
|
|
131
|
+
'Ensure VPC is configured correctly.'
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Database Subnet Group
|
|
136
|
+
result.resources.FriggDBSubnetGroup = {
|
|
137
|
+
Type: 'AWS::RDS::DBSubnetGroup',
|
|
138
|
+
Properties: {
|
|
139
|
+
DBSubnetGroupName: '${self:service}-${self:provider.stage}-db-subnet-group',
|
|
140
|
+
DBSubnetGroupDescription: 'Subnet group for Frigg Aurora cluster',
|
|
141
|
+
SubnetIds: subnetIds,
|
|
142
|
+
Tags: [
|
|
143
|
+
{ Key: 'Name', Value: '${self:service}-${self:provider.stage}-db-subnet' },
|
|
144
|
+
{ Key: 'ManagedBy', Value: 'Frigg' },
|
|
145
|
+
],
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
// Database Credentials Secret
|
|
150
|
+
result.resources.FriggDBSecret = {
|
|
151
|
+
Type: 'AWS::SecretsManager::Secret',
|
|
152
|
+
Properties: {
|
|
153
|
+
Name: '${self:service}-${self:provider.stage}-db-credentials',
|
|
154
|
+
Description: 'Aurora database credentials',
|
|
155
|
+
GenerateSecretString: {
|
|
156
|
+
SecretStringTemplate: JSON.stringify({ username: dbConfig.username || 'postgres' }),
|
|
157
|
+
GenerateStringKey: 'password',
|
|
158
|
+
PasswordLength: 32,
|
|
159
|
+
ExcludeCharacters: '"@/\\',
|
|
160
|
+
},
|
|
161
|
+
Tags: [
|
|
162
|
+
{ Key: 'Name', Value: '${self:service}-${self:provider.stage}-db-secret' },
|
|
163
|
+
{ Key: 'ManagedBy', Value: 'Frigg' },
|
|
164
|
+
],
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// Aurora Cluster
|
|
169
|
+
result.resources.FriggAuroraCluster = {
|
|
170
|
+
Type: 'AWS::RDS::DBCluster',
|
|
171
|
+
DeletionPolicy: 'Snapshot',
|
|
172
|
+
Properties: {
|
|
173
|
+
Engine: 'aurora-postgresql',
|
|
174
|
+
EngineMode: 'provisioned',
|
|
175
|
+
EngineVersion: '15.5',
|
|
176
|
+
DatabaseName: dbConfig.database || 'frigg',
|
|
177
|
+
MasterUsername: {
|
|
178
|
+
'Fn::Sub': '{{resolve:secretsmanager:${FriggDBSecret}:SecretString:username}}',
|
|
179
|
+
},
|
|
180
|
+
MasterUserPassword: {
|
|
181
|
+
'Fn::Sub': '{{resolve:secretsmanager:${FriggDBSecret}:SecretString:password}}',
|
|
182
|
+
},
|
|
183
|
+
DBSubnetGroupName: { Ref: 'FriggDBSubnetGroup' },
|
|
184
|
+
VpcSecurityGroupIds: discoveredResources.vpcSecurityGroupIds || [
|
|
185
|
+
{ Ref: 'FriggLambdaSecurityGroup' },
|
|
186
|
+
],
|
|
187
|
+
PubliclyAccessible: publiclyAccessible,
|
|
188
|
+
ServerlessV2ScalingConfiguration: {
|
|
189
|
+
MinCapacity: dbConfig.minCapacity || 0.5,
|
|
190
|
+
MaxCapacity: dbConfig.maxCapacity || 1,
|
|
191
|
+
},
|
|
192
|
+
EnableHttpEndpoint: false,
|
|
193
|
+
BackupRetentionPeriod: 7,
|
|
194
|
+
PreferredBackupWindow: '03:00-04:00',
|
|
195
|
+
PreferredMaintenanceWindow: 'sun:04:00-sun:05:00',
|
|
196
|
+
Tags: [
|
|
197
|
+
{ Key: 'Name', Value: '${self:service}-${self:provider.stage}-aurora' },
|
|
198
|
+
{ Key: 'ManagedBy', Value: 'Frigg' },
|
|
199
|
+
],
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
// Aurora Instance
|
|
204
|
+
result.resources.FriggAuroraInstance = {
|
|
205
|
+
Type: 'AWS::RDS::DBInstance',
|
|
206
|
+
Properties: {
|
|
207
|
+
Engine: 'aurora-postgresql',
|
|
208
|
+
DBInstanceClass: 'db.serverless',
|
|
209
|
+
DBClusterIdentifier: { Ref: 'FriggAuroraCluster' },
|
|
210
|
+
PubliclyAccessible: publiclyAccessible,
|
|
211
|
+
Tags: [
|
|
212
|
+
{ Key: 'Name', Value: '${self:service}-${self:provider.stage}-aurora-instance' },
|
|
213
|
+
{ Key: 'ManagedBy', Value: 'Frigg' },
|
|
214
|
+
],
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
// Environment variables
|
|
219
|
+
result.environment.DATABASE_URL = this.buildDatabaseUrl(
|
|
220
|
+
{ 'Fn::GetAtt': ['FriggAuroraCluster', 'Endpoint.Address'] },
|
|
221
|
+
{ 'Fn::GetAtt': ['FriggAuroraCluster', 'Endpoint.Port'] },
|
|
222
|
+
dbConfig.database || 'frigg',
|
|
223
|
+
{ Ref: 'FriggDBSecret' }
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
// IAM permissions for Secrets Manager
|
|
227
|
+
result.iamStatements.push({
|
|
228
|
+
Effect: 'Allow',
|
|
229
|
+
Action: ['secretsmanager:GetSecretValue'],
|
|
230
|
+
Resource: { Ref: 'FriggDBSecret' },
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
console.log(' ✅ Aurora Serverless v2 cluster resources created');
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Use existing Aurora cluster
|
|
238
|
+
*/
|
|
239
|
+
async useExistingAurora(appDefinition, discoveredResources, result) {
|
|
240
|
+
console.log(' Using existing Aurora cluster...');
|
|
241
|
+
|
|
242
|
+
const dbConfig = appDefinition.database.postgres;
|
|
243
|
+
|
|
244
|
+
if (!dbConfig.endpoint) {
|
|
245
|
+
throw new Error('database.postgres.endpoint is required when management="use-existing"');
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Set environment variables for existing cluster
|
|
249
|
+
result.environment.DATABASE_HOST = dbConfig.endpoint;
|
|
250
|
+
result.environment.DATABASE_PORT = String(dbConfig.port || 5432);
|
|
251
|
+
result.environment.DATABASE_NAME = dbConfig.database || 'frigg';
|
|
252
|
+
result.environment.DATABASE_USER = dbConfig.username || 'postgres';
|
|
253
|
+
|
|
254
|
+
console.log(` ✅ Using existing cluster: ${dbConfig.endpoint}`);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Discover existing Aurora cluster
|
|
259
|
+
*/
|
|
260
|
+
async discoverAurora(appDefinition, discoveredResources, result) {
|
|
261
|
+
console.log(' Discovering Aurora cluster...');
|
|
262
|
+
|
|
263
|
+
if (!discoveredResources.auroraClusterEndpoint) {
|
|
264
|
+
throw new Error(
|
|
265
|
+
'No Aurora cluster found in discovery mode. Set management to "create-new" or provide endpoint with "use-existing".'
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
console.log(` ✅ Using discovered Aurora cluster: ${discoveredResources.auroraClusterEndpoint}`);
|
|
270
|
+
|
|
271
|
+
// Use discovered cluster details
|
|
272
|
+
result.environment.DATABASE_HOST = discoveredResources.auroraClusterEndpoint;
|
|
273
|
+
result.environment.DATABASE_PORT = String(discoveredResources.auroraPort || 5432);
|
|
274
|
+
|
|
275
|
+
if (discoveredResources.databaseSecretArn) {
|
|
276
|
+
result.environment.DATABASE_SECRET_ARN = discoveredResources.databaseSecretArn;
|
|
277
|
+
result.iamStatements.push({
|
|
278
|
+
Effect: 'Allow',
|
|
279
|
+
Action: ['secretsmanager:GetSecretValue'],
|
|
280
|
+
Resource: discoveredResources.databaseSecretArn,
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
console.log(` ✅ Discovered cluster configuration complete`);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Build DATABASE_URL connection string
|
|
289
|
+
*/
|
|
290
|
+
buildDatabaseUrl(host, port, database, secretRef) {
|
|
291
|
+
return {
|
|
292
|
+
'Fn::Sub': [
|
|
293
|
+
`postgresql://\${Username}:\${Password}@\${Host}:\${Port}/\${Database}`,
|
|
294
|
+
{
|
|
295
|
+
Username: `{{resolve:secretsmanager:${secretRef}:SecretString:username}}`,
|
|
296
|
+
Password: `{{resolve:secretsmanager:${secretRef}:SecretString:password}}`,
|
|
297
|
+
Host: host,
|
|
298
|
+
Port: port,
|
|
299
|
+
Database: database,
|
|
300
|
+
},
|
|
301
|
+
],
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
module.exports = { AuroraBuilder };
|
|
307
|
+
|