Skip to content

Commit 37d5944

Browse files
author
Rico Huijbers
committed
feat(aws-rds): add support for parameter groups
Now supports (Cluster) Parameter Groups. This is required to support Aurora 5.7 engines (in particular, PostgreSQL with Aurora). Fixes #719.
1 parent 815915e commit 37d5944

File tree

7 files changed

+195
-4
lines changed

7 files changed

+195
-4
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
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+
* Set a parameter on this parameter group
32+
*/
33+
public abstract setParameter(key: string, value: string | undefined): void;
34+
}
35+
36+
/**
37+
* Properties to reference a cluster parameter group
38+
*/
39+
export interface ClusterParameterGroupRefProps {
40+
parameterGroupName: DBClusterParameterGroupName;
41+
}
42+
43+
/**
44+
* An imported cluster parameter group
45+
*/
46+
class ImportedClusterParameterGroup extends ClusterParameterGroupRef {
47+
public readonly parameterGroupName: DBClusterParameterGroupName;
48+
49+
constructor(parent: cdk.Construct, id: string, props: ClusterParameterGroupRefProps) {
50+
super(parent, id);
51+
this.parameterGroupName = props.parameterGroupName;
52+
}
53+
54+
/**
55+
* Set a parameter on this parameter group
56+
*/
57+
public setParameter(_key: string, _value: string | undefined) {
58+
// FIXME: Add annotation that we're dropping this on the floor
59+
}
60+
}
+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
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+
* Validate this construct
63+
*/
64+
public validate(): string[] {
65+
if (Object.keys(this.parameters).length === 0) {
66+
return ['At least one parameter required, call setParameter().'];
67+
}
68+
return [];
69+
}
70+
}

Diff for: packages/@aws-cdk/aws-rds/lib/cluster.ts

+6-2
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,

Diff for: packages/@aws-cdk/aws-rds/lib/index.ts

+2
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';

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

+13
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
},

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

+9-1
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');

Diff for: packages/@aws-cdk/aws-rds/test/test.cluster.ts

+35-1
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)