Skip to content

Commit 2541508

Browse files
authored
feat(aws-rds): add support for parameter groups (#729)
Now supports (Cluster) Parameter Groups. This is required to support Aurora 5.7 engines (in particular, PostgreSQL with Aurora). Fixes #719.
1 parent bba2e5b commit 2541508

File tree

8 files changed

+197
-6
lines changed

8 files changed

+197
-6
lines changed

packages/@aws-cdk/aws-neptune/lib/index.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,12 @@ export interface NeptuneDatabaseProps {
7474
*/
7575
preferredMaintenanceWindow?: string;
7676

77-
// Additional parameters to the database engine go here
77+
/**
78+
* Parameter group with Neptune settings
79+
*
80+
* @default No parameter group
81+
*/
82+
parameterGroup?: rds.ClusterParameterGroupRef;
7883
}
7984

8085
/**
@@ -125,8 +130,8 @@ export class NeptuneDatabase extends cdk.Construct implements ec2.IConnectable {
125130
instanceIdentifierBase: props.instanceIdentifierBase,
126131
defaultDatabaseName: props.defaultDatabaseName,
127132
kmsKeyArn: props.kmsKeyArn,
128-
parameters: {}, // Additional parameters go here
129133
preferredMaintenanceWindow: props.preferredMaintenanceWindow,
134+
parameterGroup: props.parameterGroup,
130135
});
131136

132137
this.clusterIdentifier = this.cluster.clusterIdentifier;
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import cdk = require('@aws-cdk/cdk');
2+
import { DBClusterParameterGroupName } from './rds.generated';
3+
4+
/**
5+
* A cluster parameter group
6+
*/
7+
export abstract class ClusterParameterGroupRef extends cdk.Construct {
8+
/**
9+
* Import a parameter group
10+
*/
11+
public static import(parent: cdk.Construct, id: string, props: ClusterParameterGroupRefProps): ClusterParameterGroupRef {
12+
return new ImportedClusterParameterGroup(parent, id, props);
13+
}
14+
15+
/**
16+
* Name of this parameter group
17+
*/
18+
public abstract readonly parameterGroupName: DBClusterParameterGroupName;
19+
20+
/**
21+
* Export this parameter group
22+
*/
23+
public export(): ClusterParameterGroupRefProps {
24+
return {
25+
parameterGroupName: new DBClusterParameterGroupName(
26+
new cdk.Output(this, 'ParameterGroupName', { value: this.parameterGroupName }).makeImportValue())
27+
};
28+
}
29+
}
30+
31+
/**
32+
* Properties to reference a cluster parameter group
33+
*/
34+
export interface ClusterParameterGroupRefProps {
35+
parameterGroupName: DBClusterParameterGroupName;
36+
}
37+
38+
/**
39+
* An imported cluster parameter group
40+
*/
41+
class ImportedClusterParameterGroup extends ClusterParameterGroupRef {
42+
public readonly parameterGroupName: DBClusterParameterGroupName;
43+
44+
constructor(parent: cdk.Construct, id: string, props: ClusterParameterGroupRefProps) {
45+
super(parent, id);
46+
this.parameterGroupName = props.parameterGroupName;
47+
}
48+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import cdk = require('@aws-cdk/cdk');
2+
import { ClusterParameterGroupRef } from './cluster-parameter-group-ref';
3+
import { Parameters } from './props';
4+
import { cloudformation, DBClusterParameterGroupName } from './rds.generated';
5+
6+
/**
7+
* Properties for a cluster parameter group
8+
*/
9+
export interface ClusterParameterGroupProps {
10+
/**
11+
* Database family of this parameter group
12+
*/
13+
family: string;
14+
15+
/**
16+
* Description for this parameter group
17+
*/
18+
description: string;
19+
20+
/**
21+
* The parameters in this parameter group
22+
*/
23+
parameters?: Parameters;
24+
}
25+
26+
/**
27+
* Defina a cluster parameter group
28+
*/
29+
export class ClusterParameterGroup extends ClusterParameterGroupRef {
30+
public readonly parameterGroupName: DBClusterParameterGroupName;
31+
private readonly parameters: Parameters = {};
32+
33+
constructor(parent: cdk.Construct, id: string, props: ClusterParameterGroupProps) {
34+
super(parent, id);
35+
36+
const resource = new cloudformation.DBClusterParameterGroupResource(this, 'Resource', {
37+
description: props.description,
38+
family: props.family,
39+
parameters: new cdk.Token(() => this.parameters),
40+
});
41+
42+
for (const [key, value] of Object.entries(props.parameters || {})) {
43+
this.setParameter(key, value);
44+
}
45+
46+
this.parameterGroupName = resource.ref;
47+
}
48+
49+
/**
50+
* Set a single parameter in this parameter group
51+
*/
52+
public setParameter(key: string, value: string | undefined) {
53+
if (value === undefined && key in this.parameters) {
54+
delete this.parameters[key];
55+
}
56+
if (value !== undefined) {
57+
this.parameters[key] = value;
58+
}
59+
}
60+
61+
/**
62+
* Remove a previously-set parameter from this parameter group
63+
*/
64+
public removeParameter(key: string) {
65+
this.setParameter(key, undefined);
66+
}
67+
68+
/**
69+
* Validate this construct
70+
*/
71+
public validate(): string[] {
72+
if (Object.keys(this.parameters).length === 0) {
73+
return ['At least one parameter required, call setParameter().'];
74+
}
75+
return [];
76+
}
77+
}

packages/@aws-cdk/aws-rds/lib/cluster.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import ec2 = require('@aws-cdk/aws-ec2');
22
import kms = require('@aws-cdk/aws-kms');
33
import cdk = require('@aws-cdk/cdk');
4+
import { ClusterParameterGroupRef } from './cluster-parameter-group-ref';
45
import { DatabaseClusterRef, Endpoint } from './cluster-ref';
5-
import { BackupProps, DatabaseClusterEngine, InstanceProps, Login, Parameters } from './props';
6+
import { BackupProps, DatabaseClusterEngine, InstanceProps, Login } from './props';
67
import { cloudformation, DBClusterEndpointAddress, DBClusterEndpointPort, DBClusterName, DBInstanceId } from './rds.generated';
78

89
/**
@@ -84,8 +85,10 @@ export interface DatabaseClusterProps {
8485

8586
/**
8687
* Additional parameters to pass to the database engine
88+
*
89+
* @default No parameter group
8790
*/
88-
parameters?: Parameters;
91+
parameterGroup?: ClusterParameterGroupRef;
8992
}
9093

9194
/**
@@ -155,6 +158,7 @@ export class DatabaseCluster extends DatabaseClusterRef {
155158
dbSubnetGroupName: subnetGroup.ref,
156159
vpcSecurityGroupIds: [this.securityGroupId],
157160
port: props.port,
161+
dbClusterParameterGroupName: props.parameterGroup && props.parameterGroup.parameterGroupName,
158162
// Admin
159163
masterUsername: props.masterUser.username,
160164
masterUserPassword: props.masterUser.password,

packages/@aws-cdk/aws-rds/lib/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ export * from './cluster';
22
export * from './cluster-ref';
33
export * from './instance';
44
export * from './props';
5+
export * from './cluster-parameter-group';
6+
export * from './cluster-parameter-group-ref';
57

68
// AWS::RDS CloudFormation Resources:
79
export * from './rds.generated';

packages/@aws-cdk/aws-rds/test/integ.cluster.expected.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,16 @@
305305
}
306306
}
307307
},
308+
"ParamsA8366201": {
309+
"Type": "AWS::RDS::DBClusterParameterGroup",
310+
"Properties": {
311+
"Description": "A nice parameter group",
312+
"Family": "aurora5.6",
313+
"Parameters": {
314+
"character_set_database": "utf8mb4"
315+
}
316+
}
317+
},
308318
"DatabaseSubnets56F17B9A": {
309319
"Type": "AWS::RDS::DBSubnetGroup",
310320
"Properties": {
@@ -360,6 +370,9 @@
360370
"Type": "AWS::RDS::DBCluster",
361371
"Properties": {
362372
"Engine": "aurora",
373+
"DBClusterParameterGroupName": {
374+
"Ref": "ParamsA8366201"
375+
},
363376
"DBSubnetGroupName": {
364377
"Ref": "DatabaseSubnets56F17B9A"
365378
},

packages/@aws-cdk/aws-rds/test/integ.cluster.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
import ec2 = require('@aws-cdk/aws-ec2');
22
import cdk = require('@aws-cdk/cdk');
33
import { DatabaseCluster, DatabaseClusterEngine, Password, Username } from '../lib';
4+
import { ClusterParameterGroup } from '../lib/cluster-parameter-group';
45

56
const app = new cdk.App(process.argv);
67
const stack = new cdk.Stack(app, 'aws-cdk-rds-integ');
78

89
const vpc = new ec2.VpcNetwork(stack, 'VPC', { maxAZs: 2 });
910

11+
const params = new ClusterParameterGroup(stack, 'Params', {
12+
family: 'aurora5.6',
13+
description: 'A nice parameter group',
14+
});
15+
params.setParameter('character_set_database', 'utf8mb4');
16+
1017
const cluster = new DatabaseCluster(stack, 'Database', {
1118
engine: DatabaseClusterEngine.Aurora,
1219
masterUser: {
@@ -17,7 +24,8 @@ const cluster = new DatabaseCluster(stack, 'Database', {
1724
instanceType: new ec2.InstanceTypePair(ec2.InstanceClass.Burstable2, ec2.InstanceSize.Small),
1825
vpcPlacement: { subnetsToUse: ec2.SubnetType.Public },
1926
vpc
20-
}
27+
},
28+
parameterGroup: params,
2129
});
2230

2331
cluster.connections.allowDefaultPortFromAnyIpv4('Open to the world');

packages/@aws-cdk/aws-rds/test/test.cluster.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { expect, haveResource } from '@aws-cdk/assert';
22
import ec2 = require('@aws-cdk/aws-ec2');
33
import cdk = require('@aws-cdk/cdk');
44
import { Test } from 'nodeunit';
5-
import { DatabaseCluster, DatabaseClusterEngine, DatabaseClusterRef, Password, Username } from '../lib';
5+
import { ClusterParameterGroup, DatabaseCluster, DatabaseClusterEngine, DatabaseClusterRef, Password, Username } from '../lib';
66

77
export = {
88
'check that instantiation works'(test: Test) {
@@ -88,6 +88,40 @@ export = {
8888

8989
test.done();
9090
},
91+
92+
'cluster with parameter group'(test: Test) {
93+
// GIVEN
94+
const stack = testStack();
95+
const vpc = new ec2.VpcNetwork(stack, 'VPC');
96+
97+
// WHEN
98+
const group = new ClusterParameterGroup(stack, 'Params', {
99+
family: 'hello',
100+
description: 'bye',
101+
parameters: {
102+
param: 'value'
103+
}
104+
});
105+
new DatabaseCluster(stack, 'Database', {
106+
engine: DatabaseClusterEngine.Aurora,
107+
masterUser: {
108+
username: new Username('admin'),
109+
password: new Password('tooshort'),
110+
},
111+
instanceProps: {
112+
instanceType: new ec2.InstanceTypePair(ec2.InstanceClass.Burstable2, ec2.InstanceSize.Small),
113+
vpc
114+
},
115+
parameterGroup: group
116+
});
117+
118+
// THEN
119+
expect(stack).to(haveResource('AWS::RDS::DBCluster', {
120+
DBClusterParameterGroupName: { Ref: 'ParamsA8366201' },
121+
}));
122+
123+
test.done();
124+
},
91125
};
92126

93127
function testStack() {

0 commit comments

Comments
 (0)