Skip to content

Commit

Permalink
fixup! feat(aws-rds): make serverless-cluster vpc optional
Browse files Browse the repository at this point in the history
  • Loading branch information
CorentinDoue committed Nov 10, 2021
1 parent 26a1c5f commit 45687af
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 101 deletions.
6 changes: 3 additions & 3 deletions packages/@aws-cdk/aws-rds/lib/serverless-cluster.ts
Expand Up @@ -108,8 +108,6 @@ export interface ServerlessClusterProps {
* The VPC that this Aurora Serverless cluster has been created in.
*
* @default - No VPC related construct will be created:
* - If subnetGroup is not provided, no DB subnet group will be associated with the DB cluster.
* - If securityGroups is not provided, no VPC security groups will be associated with the DB cluster.
*/
readonly vpc?: ec2.IVpc;

Expand Down Expand Up @@ -141,6 +139,7 @@ export interface ServerlessClusterProps {
* Security group.
*
* @default - a new security group is created if a vpc is provided.
* If vpc is not provided, no VPC security groups will be associated with the DB cluster.
*/
readonly securityGroups?: ec2.ISecurityGroup[];

Expand All @@ -162,6 +161,7 @@ export interface ServerlessClusterProps {
* Existing subnet group for the cluster.
*
* @default - a new subnet group will be created if a vpc is provided.
* If vpc is not provided, no DB subnet group will be associated with the DB cluster.
*/
readonly subnetGroup?: ISubnetGroup;
}
Expand Down Expand Up @@ -394,7 +394,6 @@ export class ServerlessCluster extends ServerlessClusterBase {
this.vpc = props.vpc;
this.vpcSubnets = props.vpcSubnets;
this.subnetGroup = props.subnetGroup;
let securityGroups: ec2.ISecurityGroup[] | undefined = props.securityGroups;

this.singleUserRotationApplication = props.engine.singleUserRotationApplication;
this.multiUserRotationApplication = props.engine.multiUserRotationApplication;
Expand All @@ -405,6 +404,7 @@ export class ServerlessCluster extends ServerlessClusterBase {
throw new Error('A vpc is required to use vpcSubnets in ServerlessCluster. Please add a vpc or remove vpcSubnets');
}

let securityGroups: ec2.ISecurityGroup[] | undefined = props.securityGroups;
if (this.vpc !== undefined) {
const { subnetIds } = this.vpc.selectSubnets(this.vpcSubnets);

Expand Down
@@ -0,0 +1,17 @@
{
"Resources": {
"ServerlessDatabaseWithoutVPC93F9A752": {
"Type": "AWS::RDS::DBCluster",
"Properties": {
"Engine": "aurora-mysql",
"DBClusterParameterGroupName": "default.aurora-mysql5.7",
"EngineMode": "serverless",
"MasterUsername": "admin",
"MasterUserPassword": "7959866cacc02c2d243ecfe177464fe6",
"StorageEncrypted": true
},
"UpdateReplacePolicy": "Delete",
"DeletionPolicy": "Delete"
}
}
}
17 changes: 17 additions & 0 deletions packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-no-vpc.ts
@@ -0,0 +1,17 @@
import * as cdk from '@aws-cdk/core';
import * as rds from '../lib';

const app = new cdk.App();
const stack = new cdk.Stack(app, 'aws-cdk-sls-cluster-no-vpc-integ');

const cluster = new rds.ServerlessCluster(stack, 'Serverless Database Without VPC', {
engine: rds.DatabaseClusterEngine.AURORA_MYSQL,
credentials: {
username: 'admin',
password: cdk.SecretValue.plainText('7959866cacc02c2d243ecfe177464fe6'),
},
removalPolicy: cdk.RemovalPolicy.DESTROY,
});
cluster.connections.allowDefaultPortFromAnyIpv4('Open to the world');

app.synth();
148 changes: 50 additions & 98 deletions packages/@aws-cdk/aws-rds/test/serverless-cluster.test.ts
Expand Up @@ -392,13 +392,30 @@ describe('serverless cluster', () => {
// WHEN
const cluster = new ServerlessCluster(stack, 'Database', {
engine: DatabaseClusterEngine.AURORA_MYSQL,
credentials: { username: 'admin' },
});

// THEN
expect(() => cluster.addRotationSingleUser()).toThrow(/Cannot add single user rotation for a cluster without vpc/);
expect(() => {
cluster.addRotationSingleUser();
}).toThrow(/Cannot add single user rotation for a cluster without vpc/);
});

test('throws when trying to add rotation to a serverless cluster without vpc', () => {
// GIVEN
const stack = new cdk.Stack();
const secret = new DatabaseSecret(stack, 'Secret', {
username: 'admin',
});

// WHEN
const cluster = new ServerlessCluster(stack, 'Database', {
engine: DatabaseClusterEngine.AURORA_MYSQL,
});

// THEN
expect(() => {
cluster.addRotationMultiUser('someId', { secret });
}).toThrow(/Cannot add multi user rotation for a cluster without vpc/);
});

test('can set deletion protection', () => {
Expand Down Expand Up @@ -853,39 +870,21 @@ describe('serverless cluster', () => {

// WHEN
new ServerlessCluster(stack, 'Database', {
engine: DatabaseClusterEngine.AURORA_POSTGRESQL,
parameterGroup: ParameterGroup.fromParameterGroupName(stack, 'ParameterGroup', 'default.aurora-postgresql10'),
engine: DatabaseClusterEngine.AURORA_MYSQL,
});

// THEN
expect(stack).toHaveResource('AWS::RDS::DBCluster', {
Engine: 'aurora-postgresql',
DBClusterParameterGroupName: 'default.aurora-postgresql10',
expect(stack).toHaveResourceLike('AWS::RDS::DBCluster', {
Engine: 'aurora-mysql',
EngineMode: 'serverless',
MasterUsername: {
'Fn::Join': [
'',
[
'{{resolve:secretsmanager:',
{
Ref: 'DatabaseSecret3B817195',
},
':SecretString:username::}}',
],
],
},
MasterUserPassword: {
'Fn::Join': [
'',
[
'{{resolve:secretsmanager:',
{
Ref: 'DatabaseSecret3B817195',
},
':SecretString:password::}}',
],
],
},
});
// Expect DbSubnetGroupName and VpcSecurityGroupIds are not defined.
// It can't be done with toHaveResourceLike("", { DbSubnetGroupName: undefined })
expect(stack).not.toHaveResourceLike('AWS::RDS::DBCluster', {
DbSubnetGroupName: expect.anything(),
});
expect(stack).not.toHaveResourceLike('AWS::RDS::DBCluster', {
VpcSecurityGroupIds: expect.anything(),
});


Expand All @@ -898,91 +897,45 @@ describe('serverless cluster', () => {

// WHEN
new ServerlessCluster(stack, 'Database', {
engine: DatabaseClusterEngine.AURORA_POSTGRESQL,
engine: DatabaseClusterEngine.AURORA_MYSQL,
securityGroups: [sg],
parameterGroup: ParameterGroup.fromParameterGroupName(stack, 'ParameterGroup', 'default.aurora-postgresql10'),
});

// THEN
expect(stack).toHaveResource('AWS::RDS::DBCluster', {
Engine: 'aurora-postgresql',
DBClusterParameterGroupName: 'default.aurora-postgresql10',
EngineMode: 'serverless',
MasterUsername: {
'Fn::Join': [
'',
[
'{{resolve:secretsmanager:',
{
Ref: 'DatabaseSecret3B817195',
},
':SecretString:username::}}',
],
],
},
MasterUserPassword: {
'Fn::Join': [
'',
[
'{{resolve:secretsmanager:',
{
Ref: 'DatabaseSecret3B817195',
},
':SecretString:password::}}',
],
],
},
expect(stack).toHaveResourceLike('AWS::RDS::DBCluster', {
VpcSecurityGroupIds: ['SecurityGroupId12345'],
});
// Expect DbSubnetGroupName is not defined.
// It can't be done with toHaveResourceLike("", { DbSubnetGroupName: undefined })
expect(stack).not.toHaveResourceLike('AWS::RDS::DBCluster', {
DbSubnetGroupName: expect.anything(),
});
});

test('can create a Serverless cluster without vpc but with imported subnet group', () => {
// GIVEN
const stack = testStack();
const subnetGroup = SubnetGroup.fromSubnetGroupName(stack, 'SubnetGroup12345', 'SubnetGroupId12345');
const SubnetGroupName = 'SubnetGroupId12345';
const subnetGroup = SubnetGroup.fromSubnetGroupName(stack, 'SubnetGroup12345', SubnetGroupName);

// WHEN
new ServerlessCluster(stack, 'Database', {
engine: DatabaseClusterEngine.AURORA_POSTGRESQL,
parameterGroup: ParameterGroup.fromParameterGroupName(stack, 'ParameterGroup', 'default.aurora-postgresql10'),
engine: DatabaseClusterEngine.AURORA_MYSQL,
subnetGroup,
});

// THEN
expect(stack).toHaveResource('AWS::RDS::DBCluster', {
Engine: 'aurora-postgresql',
DBClusterParameterGroupName: 'default.aurora-postgresql10',
EngineMode: 'serverless',
DBSubnetGroupName: { Ref: 'SubnetGroup12345' },
MasterUsername: {
'Fn::Join': [
'',
[
'{{resolve:secretsmanager:',
{
Ref: 'DatabaseSecret3B817195',
},
':SecretString:username::}}',
],
],
},
MasterUserPassword: {
'Fn::Join': [
'',
[
'{{resolve:secretsmanager:',
{
Ref: 'DatabaseSecret3B817195',
},
':SecretString:password::}}',
],
],
},
VpcSecurityGroupIds: ['SecurityGroupId12345'],
expect(stack).toHaveResourceLike('AWS::RDS::DBCluster', {
DBSubnetGroupName: SubnetGroupName,
});
// Expect VpcSecurityGroupIds is not defined.
// It can't be done with toHaveResourceLike("", { VpcSecurityGroupIds: undefined })
expect(stack).not.toHaveResourceLike('AWS::RDS::DBCluster', {
VpcSecurityGroupIds: expect.anything(),
});
});

test('can\'t create a Serverless cluster without vpc but with imported vpc subnets', () => {
test("can't create a Serverless cluster without VPC but with imported VPC subnets", () => {
// GIVEN
const stack = testStack();

Expand All @@ -993,10 +946,9 @@ describe('serverless cluster', () => {

// THEN
expect(() => new ServerlessCluster(stack, 'Database', {
engine: DatabaseClusterEngine.AURORA_POSTGRESQL,
parameterGroup: ParameterGroup.fromParameterGroupName(stack, 'ParameterGroup', 'default.aurora-postgresql10'),
engine: DatabaseClusterEngine.AURORA_MYSQL,
vpcSubnets,
})).toThrow(/vpc is required/);
})).toThrow(/A vpc is required to use vpcSubnets in ServerlessCluster. Please add a vpc or remove vpcSubnets/);
});
});

Expand Down

0 comments on commit 45687af

Please sign in to comment.