Skip to content

Commit 01575e7

Browse files
committed
feat: use aurora rds with serverless v2 engine for production-like environments
1 parent 212cca1 commit 01575e7

4 files changed

Lines changed: 99 additions & 15 deletions

File tree

VirtualFinland.UsersAPI.Deployment/Common/Environments.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ public enum Environments
55
Dev,
66
Test,
77
Staging,
8-
Production
8+
MvpStaging,
9+
MvpProduction
910
}

VirtualFinland.UsersAPI.Deployment/Common/Models/StackSetup.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22

33
namespace VirtualFinland.UsersAPI.Deployment.Common.Models;
44

5-
public record StackSetup
5+
public class StackSetup
66
{
77
public InputMap<string> Tags = default!;
88
public bool IsProductionEnvironment;
99
public string Environment = default!;
1010
public string ProjectName = default!;
1111
public VpcSetup VpcSetup = default!;
12+
13+
public string CreateResourceName(string name) => $"{ProjectName}-{name}-{Environment}".ToLower();
1214
}

VirtualFinland.UsersAPI.Deployment/Features/PostgresDatabase.cs

Lines changed: 88 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using Pulumi;
2+
using Pulumi.Aws.Kms;
23
using Pulumi.Aws.Rds;
4+
using Pulumi.Aws.Rds.Inputs;
35
using Pulumi.Random;
46
using VirtualFinland.UsersAPI.Deployment.Common.Models;
57
using Instance = Pulumi.Aws.Rds.Instance;
@@ -13,7 +15,89 @@ public class PostgresDatabase
1315
{
1416
public PostgresDatabase(Config config, StackSetup stackSetup)
1517
{
16-
var dbSubNetGroup = new Pulumi.Aws.Rds.SubnetGroup("dbsubnets", new()
18+
if (stackSetup.IsProductionEnvironment)
19+
{
20+
SetupProductionPostgresDatabase(config, stackSetup);
21+
}
22+
else
23+
{
24+
SetupDevelopmentPostgresDatabase(config, stackSetup);
25+
}
26+
}
27+
28+
/// <summary>
29+
/// Setup AWS Aurora RDS Serverless V2 for postgresql
30+
/// </summary>
31+
public void SetupProductionPostgresDatabase(Config config, StackSetup stackSetup)
32+
{
33+
var dbSubNetGroup = new SubnetGroup(stackSetup.CreateResourceName("database-subnets"), new()
34+
{
35+
SubnetIds = stackSetup.VpcSetup.PrivateSubnetIds,
36+
});
37+
38+
var password = new RandomPassword(stackSetup.CreateResourceName("database-password"), new()
39+
{
40+
Length = 16,
41+
Special = false,
42+
OverrideSpecial = "_%@",
43+
});
44+
45+
// Encryption key (KMS)
46+
var encryptionKey = new Key(stackSetup.CreateResourceName("database-encryption-key"), new()
47+
{
48+
Description = "Encryption key for the database",
49+
Tags = stackSetup.Tags,
50+
DeletionWindowInDays = 30, // On deletion, the key will be retained for 30 days before being deleted permanently
51+
});
52+
53+
// AWS Aurora RDS Serverless V2 for postgresql
54+
var auroraCluster = new Cluster(stackSetup.CreateResourceName("database-cluster"), new ClusterArgs()
55+
{
56+
Engine = "aurora-postgresql",
57+
EngineVersion = "13.6",
58+
EngineMode = "provisioned", // serverless v2
59+
Serverlessv2ScalingConfiguration = new ClusterServerlessv2ScalingConfigurationArgs
60+
{
61+
MaxCapacity = 4,
62+
MinCapacity = 0.5,
63+
},
64+
65+
DatabaseName = config.Require("dbName"),
66+
MasterUsername = config.Require("dbAdmin"),
67+
MasterPassword = password.Result,
68+
69+
SkipFinalSnapshot = false,
70+
DeletionProtection = true,
71+
StorageEncrypted = true,
72+
KmsKeyId = encryptionKey.Arn,
73+
74+
DbSubnetGroupName = dbSubNetGroup.Name,
75+
Tags = stackSetup.Tags,
76+
});
77+
78+
var auroraInstance = new ClusterInstance(stackSetup.CreateResourceName("database-instance"), new()
79+
{
80+
ClusterIdentifier = auroraCluster.ClusterIdentifier,
81+
InstanceClass = "db.serverless",
82+
Engine = "aurora-postgresql",
83+
EngineVersion = auroraCluster.EngineVersion,
84+
Tags = stackSetup.Tags,
85+
});
86+
87+
var DbName = config.Require("dbName");
88+
var DbUsername = config.Require("dbAdmin");
89+
var DbHostName = auroraCluster.Endpoint;
90+
DBIdentifier = auroraInstance.Identifier;
91+
var DbPassword = password.Result;
92+
DbConnectionString = Output.Format($"Host={DbHostName};Database={DbName};Username={DbUsername};Password={DbPassword}");
93+
}
94+
95+
/// <summary>
96+
/// Setup AWS RDS for postgresql
97+
/// </summary>
98+
public void SetupDevelopmentPostgresDatabase(Config config, StackSetup stackSetup)
99+
{
100+
var dbSubNetGroup = new SubnetGroup("dbsubnets", new()
17101
{
18102
SubnetIds = stackSetup.VpcSetup.PrivateSubnetIds,
19103
});
@@ -25,7 +109,7 @@ public PostgresDatabase(Config config, StackSetup stackSetup)
25109
OverrideSpecial = "_%@",
26110
});
27111

28-
var rdsPostGreInstance = new Instance($"{stackSetup.ProjectName}-postgres-db-{stackSetup.Environment}", new InstanceArgs()
112+
var rdsPostGreInstance = new Instance(stackSetup.CreateResourceName("postgres-db"), new InstanceArgs()
29113
{
30114
Engine = "postgres",
31115
InstanceClass = "db.t3.micro",
@@ -36,9 +120,8 @@ public PostgresDatabase(Config config, StackSetup stackSetup)
36120
Username = config.Require("dbAdmin"),
37121
Password = password.Result,
38122
Tags = stackSetup.Tags,
39-
PubliclyAccessible = !stackSetup.IsProductionEnvironment, // DEV: For Production set to FALSE
40-
SkipFinalSnapshot = !stackSetup.IsProductionEnvironment, // DEV: For production set to FALSE to avoid accidental deletion of the cluster, data safety measure and is the default for AWS.
41-
//SnapshotIdentifier = "" // See README.database.md for more information
123+
PubliclyAccessible = false,
124+
SkipFinalSnapshot = true,
42125
});
43126

44127
var DbName = config.Require("dbName");

VirtualFinland.UsersAPI.Deployment/UsersAPIStack.cs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,16 +60,14 @@ public UsersApiStack()
6060
private bool IsProductionEnvironment()
6161
{
6262
var stackName = Pulumi.Deployment.Instance.StackName;
63-
switch (stackName)
63+
return stackName switch
6464
{
6565
// Cheers: https://stackoverflow.com/a/65642709
66-
case var value when value == Environments.Production.ToString().ToLowerInvariant():
67-
return true;
68-
case var value when value == Environments.Staging.ToString().ToLowerInvariant():
69-
return true;
70-
default:
71-
return false;
72-
}
66+
var value when value == Environments.MvpProduction.ToString().ToLowerInvariant() => true,
67+
var value when value == Environments.MvpStaging.ToString().ToLowerInvariant() => true,
68+
var value when value == Environments.Staging.ToString().ToLowerInvariant() => false,
69+
_ => false,
70+
};
7371
}
7472

7573
// Outputs for Pulumi service

0 commit comments

Comments
 (0)