Skip to content

Commit

Permalink
Pulumi prod creates a a database cluster.
Browse files Browse the repository at this point in the history
  • Loading branch information
rizen committed Aug 3, 2024
1 parent 2313e85 commit ef50101
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 13 deletions.
12 changes: 7 additions & 5 deletions Pulumi.mjs
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import { createUploads } from './pulumi/uploads.mjs';
import { createVpc } from './pulumi/vpc.mjs';
import { createAurora } from './pulumi/aurora.mjs';
import { createThumbnails } from './pulumi/thumbnails.mjs';
import { createLambdaProcessUploads } from './pulumi/lambda-process-uploads.mjs';
import { updateEnv } from './pulumi/env.mjs';
import * as pulumi from "@pulumi/pulumi";

const stack = pulumi.getStack();
const { uploadsBucket, uploadsAccessKey } = createUploads();
const thumbnailsBucket = createThumbnails();
const processUploadsFunctionUrl = createLambdaProcessUploads(thumbnailsBucket);
const { uploadsBucket, uploadsAccessKey } = await createUploads();
const thumbnailsBucket = await createThumbnails();
const processUploadsFunctionUrl = await createLambdaProcessUploads(thumbnailsBucket);
if (stack != 'dev') {
const vpc = createVpc();
const { vpc, subnets } = await createVpc();
const { auroraCluster } = await createAurora(vpc, subnets)
}
updateEnv({
await updateEnv({
stack,
uploadsBucket,
uploadsAccessKey,
Expand Down
93 changes: 93 additions & 0 deletions pulumi/aurora.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import * as aws from "@pulumi/aws";
import { prefix, safeName } from './utils.mjs';

export const createAurora = async (vpc, subnets) => {

const clusterSecurityGroup = new aws.ec2.SecurityGroup(prefix("aurora-sg"), {
vpcId: vpc.id,
description: "Allow traffic to Aurora",
ingress: [
{ protocol: "tcp", fromPort: 3306, toPort: 3306, cidrBlocks: ["0.0.0.0/0"] },
],
egress: [
{ protocol: "-1", fromPort: 0, toPort: 0, cidrBlocks: ["0.0.0.0/0"] },
],
});

const clusterParameterGroup = new aws.rds.ClusterParameterGroup(prefix("aurora-mysql80-param-group"), {
family: "aurora-mysql8.0",
parameters: [
{
name: "character_set_server",
value: "utf8",
},
{
name: "collation_server",
value: "utf8_unicode_ci",
},
{
name: "innodb_ft_min_token_size",
value: 2,
applyMethod: "pending-reboot", // Apply this change during next reboot
},
{
name: "sql_mode",
value: "NO_ENGINE_SUBSTITUTION"
},
],
});

const clusterSubnetGroup = new aws.rds.SubnetGroup(prefix("aurora-subnet-group"), {
subnetIds: [subnets[0].id, subnets[1].id],
});

const databaseName = safeName();
const username = "root";
const password = "changeMeAfterTheFact";


const auroraCluster = new aws.rds.Cluster(prefix('aurora-cluster'), {
clusterIdentifier: prefix('aurora-cluster'),
engine: "aurora-mysql",
engineMode: "provisioned",
databaseName: databaseName,
masterUsername: username,
masterPassword: password,
serverlessv2ScalingConfiguration: {
maxCapacity: 1,
minCapacity: 0.5,
},
storageEncrypted: true,
finalSnapshotIdentifier: prefix("final-snap-shot"),
backupRetentionPeriod: 7,
vpcSecurityGroupIds: [clusterSecurityGroup.id],
dbClusterParameterGroupName: clusterParameterGroup,
dbSubnetGroupName: clusterSubnetGroup.name,
});

const region = await aws.getRegion({});

// Create a read instance
const readInstance = new aws.rds.ClusterInstance(prefix("aurora-read"), {
clusterIdentifier: auroraCluster.id,
identifierPrefix: prefix("aurora-read"),
instanceClass: "db.serverless",
engine: auroraCluster.engine,
engineVersion: auroraCluster.engineVersion,
availabilityZone: region.id + "b", // Distributing instances across AZs
});

// Create a write instance
const writeInstance = new aws.rds.ClusterInstance(prefix("aurora-write"), {
clusterIdentifier: auroraCluster.id,
identifierPrefix: prefix("aurora-write"),
instanceClass: "db.serverless",
engine: auroraCluster.engine,
engineVersion: auroraCluster.engineVersion,
preferredMaintenanceWindow: "sun:23:45-mon:00:15",
availabilityZone: region.id + "a", // Distributing instances across AZs
});


return { auroraCluster, clusterParameterGroup, clusterSecurityGroup };
}
2 changes: 1 addition & 1 deletion pulumi/env.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as pulumi from "@pulumi/pulumi";

// this has to be its own file rather than each function updating itself, because of the paralleization of pulumi causing a race condition for the .env file

export const updateEnv = (obj) => {
export const updateEnv = async (obj) => {
const env = new Env(obj.stack == 'dev' ? '.env' : '.env.' + obj.stack);
aws.getRegion({}).then(region => env.set('AWS_REGION', region.id));
obj.uploadsAccessKey.id.apply(id => env.set("VING_AWS_UPLOADS_KEY", id));
Expand Down
2 changes: 1 addition & 1 deletion pulumi/lambda-process-uploads.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as pulumi from "@pulumi/pulumi";
import { execSync } from 'child_process';


export const createLambdaProcessUploads = (thumbnailsBucket) => {
export const createLambdaProcessUploads = async (thumbnailsBucket) => {

execSync('./create.nodemods.layer.sh', { cwd: './pulumi/aws/lambda/layer/nodemods' });

Expand Down
2 changes: 1 addition & 1 deletion pulumi/thumbnails.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as aws from "@pulumi/aws";
import { prefix } from './utils.mjs';
import * as pulumi from "@pulumi/pulumi";

export const createThumbnails = () => {
export const createThumbnails = async () => {

const thumbnailsBucket = new aws.s3.BucketV2(prefix('thumbnails'), {});

Expand Down
2 changes: 1 addition & 1 deletion pulumi/uploads.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as aws from "@pulumi/aws";
import { prefix } from './utils.mjs';
import * as pulumi from "@pulumi/pulumi";

export const createUploads = () => {
export const createUploads = async () => {

const uploadsBucket = new aws.s3.BucketV2(prefix('uploads'), {});

Expand Down
8 changes: 7 additions & 1 deletion pulumi/utils.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import * as pulumi from "@pulumi/pulumi";

export const safeName = () => {
return `${pulumi.getProject()}${pulumi.getStack()}`.toLowerCase().replace(/\s+/g, '');
}

export const prefix = (name) => {
return `${pulumi.getProject()}-${pulumi.getStack()}-${name}`;
if (name)
return `${pulumi.getProject()}-${pulumi.getStack()}-${name}`;
return `${pulumi.getProject()}-${pulumi.getStack()}`;
}
18 changes: 16 additions & 2 deletions pulumi/vpc.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as aws from "@pulumi/aws";
import { prefix } from './utils.mjs';

export const createVpc = () => {
export const createVpc = async () => {

const vpc = new aws.ec2.Vpc(prefix('vpc'), {
cidrBlock: "10.0.0.0/16",
Expand All @@ -12,5 +12,19 @@ export const createVpc = () => {
},
});

return vpc;
const region = await aws.getRegion({});

const subnet1 = new aws.ec2.Subnet(prefix('subnet1'), {
vpcId: vpc.id,
cidrBlock: "10.0.1.0/24",
availabilityZone: region.id + "a",
});

const subnet2 = new aws.ec2.Subnet(prefix('subnet2'), {
vpcId: vpc.id,
cidrBlock: "10.0.2.0/24",
availabilityZone: region.id + "b",
});

return { vpc, subnets: [subnet1, subnet2] };
}
1 change: 1 addition & 0 deletions ving/docs/change-log.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ outline: deep
### 2024-08-02
* Added Pulumi prod.
* Pulumi prod creates a VPC.
* Pulumi prod creates a a database cluster.

## July 2024

Expand Down
11 changes: 10 additions & 1 deletion ving/docs/subsystems/pulumi.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,13 @@ Prod does the following things differently than dev:
- stores its AWS generated variables in .env.prod
- provisions a VPC
- provisions an Aurora Serverless database
- provisions an EC2 instance
- provisions an EC2 instance
### Deploying Prod (or other stacks)
After deploying prod, or other stacks, there are a few things you'll need to do to set it up:
#### Database
First by default it will create a database with the root user of `root` and the password `changeMeAfterTheFact`. You'll need to change this password in the AWS console. You can do this by going to the RDS console, clicking on the cluster, and then clicking on the "Modify" button. Then you can change the password.
Second, you may also want to change the minimum and maximum capacity units of the Aurora cluster. You can do this by going to the RDS console, clicking on the cluster, and then clicking on the "Modify" button. Then you can change the minimum and maximum capacity units.

0 comments on commit ef50101

Please sign in to comment.