-
Notifications
You must be signed in to change notification settings - Fork 1
feat: Migrate database to v2 #71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 4 commits
e68f718
e768f7b
e35d75b
02aa9f5
d12e7ed
f615a9f
974a125
2aca530
570ff03
dda467d
d043740
004c29f
a737feb
c8701a4
c412da9
0af86e6
e8d0efa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,309 @@ | ||
| import * as aws from '@pulumi/aws'; | ||
| import * as pulumi from '@pulumi/pulumi'; | ||
| import { Password } from '../../../components/password'; | ||
| import { commonTags } from '../../../constants'; | ||
|
|
||
| export namespace Database { | ||
| export type Args = { | ||
| /** | ||
| * The name of the database to create when the DB instance is created. | ||
| */ | ||
| dbName: pulumi.Input<string>; | ||
| /** | ||
| * Username for the master DB user. | ||
| */ | ||
| username: pulumi.Input<string>; | ||
| vpcId: pulumi.Input<string>; | ||
| isolatedSubnetIds: pulumi.Input<pulumi.Input<string>[]>; | ||
| /** | ||
| * The IPv4 CIDR block for the VPC. | ||
| */ | ||
| vpcCidrBlock: pulumi.Input<string>; | ||
| /** | ||
| * Specifies if the RDS instance is multi-AZ. Defaults to false. | ||
| */ | ||
| multiAz?: pulumi.Input<boolean>; | ||
| /** | ||
| * Password for the master DB user. If not specified it will be autogenerated. | ||
| * The value will be stored as a secret in AWS Secret Manager. | ||
| */ | ||
| password?: pulumi.Input<string>; | ||
| /** | ||
| * Specifies whether any database modifications are applied immediately, | ||
| * or during the next maintenance window. Default is false. | ||
| */ | ||
| applyImmediately?: pulumi.Input<boolean>; | ||
| /** | ||
| * Determines whether a final DB snapshot is created before the DB | ||
| * instance is deleted. Defaults to false. | ||
| */ | ||
| skipFinalSnapshot?: pulumi.Input<boolean>; | ||
| /** | ||
| * The allocated storage in gibibytes. Defaults to 20GB. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. gibibyte, I like it. 👌 😂 On a serious note, we can drop comments where the name of the parameter is self-explanatory.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct abbreviation for gibibyte is Sorry for barging in, I get notified for all activity and couldn't resist on this one 😄 |
||
| */ | ||
| allocatedStorage?: pulumi.Input<number>; | ||
| /** | ||
| * The upper limit to which Amazon RDS can automatically scale | ||
| * the storage of the DB instance. Defaults to 100GB. | ||
| */ | ||
| maxAllocatedStorage?: pulumi.Input<number>; | ||
| /** | ||
| * The instance type of the RDS instance. Defaults to 'db.t4g.micro'. | ||
| */ | ||
| instanceClass?: pulumi.Input<string>; | ||
| /** | ||
| * Set this to true to enable database monitoring. Defaults to false. | ||
| */ | ||
| enableMonitoring?: pulumi.Input<boolean>; | ||
| /** | ||
| * Set this to true to allow major version upgrades, for example when creating | ||
| * db from the snapshot. Defaults to false. | ||
| */ | ||
| allowMajorVersionUpgrade?: pulumi.Input<boolean>; | ||
| /** | ||
| * Set this to false to disallow automatic minor version updates to the | ||
| * DB instance during the maintenance window. Defaults to true. | ||
| */ | ||
| autoMinorVersionUpgrade?: pulumi.Input<boolean>; | ||
| /** | ||
| * The name of custom aws.rds.ParameterGroup. Setting this param will apply custom | ||
| * DB parameters to this instance. | ||
| */ | ||
| parameterGroupName?: pulumi.Input<string>; | ||
| /** | ||
| * Set this to `{ enabled: true }` to enable low-downtime updates using RDS Blue/Green deployments. | ||
| * Defaults to `{ enabled: false }`. | ||
| */ | ||
| blueGreenUpdate?: pulumi.Input<aws.types.input.rds.InstanceBlueGreenUpdate>; | ||
| /** | ||
| * Specifies whether to create this database from a snapshot. | ||
| * This correlates to the snapshot ID you'd find in the RDS console, | ||
| * e.g: rds:production-2015-06-26-06-05. | ||
| */ | ||
| snapshotIdentifier?: pulumi.Input<string>; | ||
| /** | ||
| * The DB engine version. Defaults to '17.2'. | ||
| */ | ||
| engineVersion?: pulumi.Input<string>; | ||
| /** | ||
| * A map of tags to assign to the resource. | ||
| */ | ||
| tags?: pulumi.Input<{ | ||
| [key: string]: pulumi.Input<string>; | ||
| }>; | ||
| }; | ||
| } | ||
|
|
||
| const defaults = { | ||
| multiAz: false, | ||
| applyImmediately: false, | ||
| skipFinalSnapshot: false, | ||
| allocatedStorage: 20, | ||
| maxAllocatedStorage: 100, | ||
| instanceClass: 'db.t4g.micro', | ||
| enableMonitoring: false, | ||
| allowMajorVersionUpgrade: false, | ||
| autoMinorVersionUpgrade: true, | ||
| engineVersion: '17.2', | ||
| blueGreenUpdate: { | ||
| enabled: false, | ||
| }, | ||
| }; | ||
|
|
||
| export class Database extends pulumi.ComponentResource { | ||
| name: string; | ||
| instance: aws.rds.Instance; | ||
| kms: aws.kms.Key; | ||
| dbSubnetGroup: aws.rds.SubnetGroup; | ||
| dbSecurityGroup: aws.ec2.SecurityGroup; | ||
| password: Password; | ||
| encryptedSnapshotCopy?: aws.rds.SnapshotCopy; | ||
| monitoringRole?: aws.iam.Role; | ||
|
|
||
| constructor( | ||
| name: string, | ||
| args: Database.Args, | ||
| opts: pulumi.ComponentResourceOptions = {}, | ||
| ) { | ||
| super('studion:Database', name, {}, opts); | ||
|
|
||
| this.name = name; | ||
|
|
||
| const argsWithDefaults = Object.assign({}, defaults, args); | ||
| const { | ||
| vpcId, | ||
| isolatedSubnetIds, | ||
| vpcCidrBlock, | ||
| enableMonitoring, | ||
| snapshotIdentifier, | ||
| } = argsWithDefaults; | ||
| this.dbSubnetGroup = this.createSubnetGroup({ isolatedSubnetIds }); | ||
| this.dbSecurityGroup = this.createSecurityGroup({ vpcId, vpcCidrBlock }); | ||
| this.kms = this.createEncryptionKey(); | ||
| this.password = new Password( | ||
| `${this.name}-database-password`, | ||
| { value: args.password }, | ||
| { parent: this }, | ||
| ); | ||
| if (enableMonitoring) { | ||
| this.monitoringRole = this.createMonitoringRole(); | ||
| } | ||
| if (snapshotIdentifier) { | ||
| this.encryptedSnapshotCopy = | ||
| this.createEncryptedSnapshotCopy(snapshotIdentifier); | ||
| } | ||
| this.instance = this.createDatabaseInstance(args); | ||
|
|
||
| this.registerOutputs(); | ||
| } | ||
|
|
||
| private createSubnetGroup({ | ||
| isolatedSubnetIds, | ||
| }: Pick<Database.Args, 'isolatedSubnetIds'>) { | ||
| const dbSubnetGroup = new aws.rds.SubnetGroup( | ||
| `${this.name}-subnet-group`, | ||
| { | ||
| subnetIds: isolatedSubnetIds, | ||
| tags: commonTags, | ||
| }, | ||
| { parent: this }, | ||
| ); | ||
| return dbSubnetGroup; | ||
| } | ||
|
|
||
| private createSecurityGroup({ | ||
| vpcId, | ||
| vpcCidrBlock, | ||
| }: Pick<Database.Args, 'vpcId' | 'vpcCidrBlock'>) { | ||
| const dbSecurityGroup = new aws.ec2.SecurityGroup( | ||
| `${this.name}-security-group`, | ||
| { | ||
| vpcId, | ||
| ingress: [ | ||
| { | ||
| protocol: 'tcp', | ||
| fromPort: 5432, | ||
| toPort: 5432, | ||
| cidrBlocks: [vpcCidrBlock], | ||
| }, | ||
| ], | ||
| tags: commonTags, | ||
| }, | ||
| { parent: this }, | ||
| ); | ||
| return dbSecurityGroup; | ||
| } | ||
|
|
||
| private createEncryptionKey() { | ||
| const kms = new aws.kms.Key( | ||
| `${this.name}-rds-key`, | ||
| { | ||
| description: `${this.name} RDS encryption key`, | ||
| customerMasterKeySpec: 'SYMMETRIC_DEFAULT', | ||
| isEnabled: true, | ||
| keyUsage: 'ENCRYPT_DECRYPT', | ||
| multiRegion: false, | ||
| enableKeyRotation: true, | ||
| tags: commonTags, | ||
| }, | ||
| { parent: this }, | ||
| ); | ||
| return kms; | ||
| } | ||
|
|
||
| private createMonitoringRole() { | ||
| const monitoringRole = new aws.iam.Role(`${this.name}-rds-monitoring`, { | ||
| assumeRolePolicy: { | ||
| Version: '2012-10-17', | ||
| Statement: [ | ||
| { | ||
| Action: 'sts:AssumeRole', | ||
| Effect: 'Allow', | ||
| Principal: { | ||
| Service: 'monitoring.rds.amazonaws.com', | ||
| }, | ||
| }, | ||
| ], | ||
| }, | ||
| }); | ||
|
|
||
| new aws.iam.RolePolicyAttachment( | ||
| `${this.name}-rds-monitoring-role-attachment`, | ||
| { | ||
| role: monitoringRole.name, | ||
| policyArn: | ||
| 'arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole', | ||
| }, | ||
| ); | ||
|
|
||
| return monitoringRole; | ||
| } | ||
|
|
||
| private createEncryptedSnapshotCopy( | ||
| snapshotIdentifier: NonNullable<Database.Args['snapshotIdentifier']>, | ||
| ) { | ||
| const encryptedSnapshotCopy = new aws.rds.SnapshotCopy( | ||
| `${this.name}-encrypted-snapshot-copy`, | ||
| { | ||
| sourceDbSnapshotIdentifier: snapshotIdentifier, | ||
| targetDbSnapshotIdentifier: `${snapshotIdentifier}-encrypted-copy`, | ||
| kmsKeyId: this.kms.arn, | ||
| }, | ||
| { parent: this }, | ||
| ); | ||
| return encryptedSnapshotCopy; | ||
| } | ||
|
|
||
| private createDatabaseInstance(args: Database.Args) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's avoid passing the whole argument bag, and instead make the parameters of each method explicit. |
||
| const argsWithDefaults = Object.assign({}, defaults, args); | ||
| const stack = pulumi.getStack(); | ||
|
|
||
| const monitoringOptions = | ||
| argsWithDefaults.enableMonitoring && this.monitoringRole | ||
| ? { | ||
| monitoringInterval: 60, | ||
| monitoringRoleArn: this.monitoringRole.arn, | ||
| performanceInsightsEnabled: true, | ||
| performanceInsightsRetentionPeriod: 7, | ||
| } | ||
| : {}; | ||
|
|
||
| const instance = new aws.rds.Instance( | ||
| `${this.name}-rds`, | ||
| { | ||
| identifierPrefix: `${this.name}-`, | ||
| engine: 'postgres', | ||
| engineVersion: argsWithDefaults.engineVersion, | ||
| allocatedStorage: argsWithDefaults.allocatedStorage, | ||
| maxAllocatedStorage: argsWithDefaults.maxAllocatedStorage, | ||
| instanceClass: argsWithDefaults.instanceClass, | ||
| dbName: argsWithDefaults.dbName, | ||
| username: argsWithDefaults.username, | ||
| password: this.password.value, | ||
| dbSubnetGroupName: this.dbSubnetGroup.name, | ||
| vpcSecurityGroupIds: [this.dbSecurityGroup.id], | ||
| storageEncrypted: true, | ||
| kmsKeyId: this.kms.arn, | ||
| multiAz: argsWithDefaults.multiAz, | ||
| publiclyAccessible: false, | ||
| skipFinalSnapshot: argsWithDefaults.skipFinalSnapshot, | ||
| applyImmediately: argsWithDefaults.applyImmediately, | ||
| autoMinorVersionUpgrade: argsWithDefaults.autoMinorVersionUpgrade, | ||
| maintenanceWindow: 'Mon:07:00-Mon:07:30', | ||
| finalSnapshotIdentifier: `${this.name}-final-snapshot-${stack}`, | ||
| backupWindow: '06:00-06:30', | ||
| backupRetentionPeriod: 14, | ||
| caCertIdentifier: 'rds-ca-rsa2048-g1', | ||
| parameterGroupName: argsWithDefaults.parameterGroupName, | ||
| allowMajorVersionUpgrade: argsWithDefaults.allowMajorVersionUpgrade, | ||
| blueGreenUpdate: argsWithDefaults.blueGreenUpdate, | ||
| snapshotIdentifier: | ||
| this.encryptedSnapshotCopy?.targetDbSnapshotIdentifier, | ||
| ...monitoringOptions, | ||
| tags: { ...commonTags, ...argsWithDefaults.tags }, | ||
| }, | ||
| { parent: this, dependsOn: [this.password] }, | ||
| ); | ||
| return instance; | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this needed?