Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions integration_tests/cdk/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ def __init__(
allocated_storage=app_config.db_allocated_storage,
instance_type=aws_ec2.InstanceType(app_config.db_instance_type),
add_pgbouncer=True,
pgbouncer_instance_props={
"instance_name": "test-name",
},
removal_policy=RemovalPolicy.DESTROY,
pgstac_version=PGSTAC_VERSION,
)
Expand Down
49 changes: 24 additions & 25 deletions lib/database/PgBouncer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,6 @@ export interface PgBouncerConfigProps {
}

export interface PgBouncerProps {
/**
* Name for the pgbouncer instance
*/
instanceName: string;

/**
* VPC to deploy PgBouncer into
*/
Expand All @@ -56,15 +51,14 @@ export interface PgBouncerProps {
usePublicSubnet?: boolean;

/**
* Instance type for PgBouncer
* @default t3.micro
* PgBouncer configuration options
*/
instanceType?: ec2.InstanceType;
pgBouncerConfig?: PgBouncerConfigProps;

/**
* PgBouncer configuration options
* EC2 instance options
*/
pgBouncerConfig?: PgBouncerConfigProps;
instanceProps?: Partial<ec2.InstanceProps>;
}

export class PgBouncer extends Construct {
Expand All @@ -78,7 +72,7 @@ export class PgBouncer extends Construct {
// be slightly smaller than the actual max_connections value on the RDS instance
// so we perform this calculation.

private getDefaultConfig(
private getDefaultPgbouncerConfig(
dbMaxConnections: number
): Required<PgBouncerConfigProps> {
// maxDbConnections (and maxUserConnections) are the only settings that need
Expand All @@ -99,17 +93,14 @@ export class PgBouncer extends Construct {
super(scope, id);

// Set defaults for optional props
const defaultInstanceType = ec2.InstanceType.of(
ec2.InstanceClass.T3,
ec2.InstanceSize.MICRO
);

const instanceType = props.instanceType ?? defaultInstanceType;
const defaultConfig = this.getDefaultConfig(props.dbMaxConnections);
const defaultPgbouncerConfig = this.getDefaultPgbouncerConfig(
props.dbMaxConnections
);

// Merge provided config with defaults
const pgBouncerConfig: Required<PgBouncerConfigProps> = {
...defaultConfig,
...defaultPgbouncerConfig,
...props.pgBouncerConfig,
};

Expand Down Expand Up @@ -144,21 +135,21 @@ export class PgBouncer extends Construct {
});

// Create PgBouncer instance
this.instance = new ec2.Instance(this, "Instance", {
vpc: props.vpc,
const defaultInstanceConfig: Omit<ec2.InstanceProps, "vpc"> = {
instanceName: "pgbouncer",
instanceType: ec2.InstanceType.of(
ec2.InstanceClass.T3,
ec2.InstanceSize.MICRO
),
vpcSubnets: {
subnetType: props.usePublicSubnet
? ec2.SubnetType.PUBLIC
: ec2.SubnetType.PRIVATE_WITH_EGRESS,
},
securityGroup: this.securityGroup,
instanceType,
instanceName: props.instanceName,
machineImage: ec2.MachineImage.fromSsmParameter(
"/aws/service/canonical/ubuntu/server/jammy/stable/current/amd64/hvm/ebs-gp2/ami-id",
{ os: ec2.OperatingSystemType.LINUX }
),
role,
blockDevices: [
{
deviceName: "/dev/xvda",
Expand All @@ -169,9 +160,17 @@ export class PgBouncer extends Construct {
}),
},
],
role,
securityGroup: this.securityGroup,
userData: this.loadUserDataScript(pgBouncerConfig, props.database),
userDataCausesReplacement: true,
associatePublicIpAddress: props.usePublicSubnet,
};

this.instance = new ec2.Instance(this, "Instance", {
...defaultInstanceConfig,
...props.instanceProps,
vpc: props.vpc,
});

// Allow PgBouncer to connect to RDS
Expand All @@ -183,7 +182,7 @@ export class PgBouncer extends Construct {

// Create a new secret for pgbouncer connection credentials
this.pgbouncerSecret = new secretsmanager.Secret(this, "PgBouncerSecret", {
description: `Connection information for PgBouncer instance ${props.instanceName}`,
description: "Connection information for PgBouncer instance",
generateSecretString: {
generateStringKey: "dummy",
secretStringTemplate: "{}",
Expand Down
23 changes: 18 additions & 5 deletions lib/database/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,14 +144,20 @@ export class PgStacDatabase extends Construct {
});

// PgBouncer: connection poolercustomresource trigger on redeploy
const defaultPgbouncerInstanceProps: Partial<ec2.InstanceProps> = {
instanceName: `${Stack.of(this).stackName}-pgbouncer`,
instanceType: ec2.InstanceType.of(
ec2.InstanceClass.T3,
ec2.InstanceSize.MICRO
),
};
const addPgbouncer = props.addPgbouncer ?? true;
if (addPgbouncer) {
this._pgBouncerServer = new PgBouncer(this, "pgbouncer", {
instanceName: `${Stack.of(this).stackName}-pgbouncer`,
instanceType: ec2.InstanceType.of(
ec2.InstanceClass.T3,
ec2.InstanceSize.MICRO
),
instanceProps: {
...defaultPgbouncerInstanceProps,
...props.pgbouncerInstanceProps,
},
vpc: props.vpc,
database: {
connections: this.db.connections,
Expand Down Expand Up @@ -258,6 +264,13 @@ export interface PgStacDatabaseProps extends rds.DatabaseInstanceProps {
*/
readonly addPgbouncer?: boolean;
Comment thread
hrodmn marked this conversation as resolved.

/**
* Properties for the pgbouncer ec2 instance
*
* @default - defined in the construct
*/
readonly pgbouncerInstanceProps?: ec2.InstanceProps | any;
Comment thread
hrodmn marked this conversation as resolved.

/**
* Lambda function Custom Resource properties. A custom resource property is going to be created
* to trigger the boostrapping lambda function. This parameter allows the user to specify additional properties
Expand Down
Loading