Skip to content

Commit

Permalink
fix(deadline): lock down DocDC engine to version 3.6.0 (#230)
Browse files Browse the repository at this point in the history
  • Loading branch information
ddneilson authored Nov 20, 2020
1 parent eb1f7a9 commit 2f46944
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ def __init__(self, scope: Construct, stack_id: str, *, props: StorageTierDocDBPr
# It is recommended that when creating your render farm you use at least 2 instances for redundancy.
instances=1,
master_user=Login(username='adminuser'),
engine_version='3.6.0',
backup=BackupProps(
# We recommend setting the retention of your backups to 15 days
# for security reasons. The default retention is just one day.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ export class StorageTierDocDB extends StorageTier {
masterUser: {
username: 'adminuser',
},
engineVersion: '3.6.0',
backup: {
// We recommend setting the retention of your backups to 15 days
// for security reasons. The default retention is just one day.
Expand Down
1 change: 1 addition & 0 deletions integ/lib/storage-struct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export class StorageStruct extends Construct {
masterUser: {
username: 'DocDBUser',
},
engineVersion: '3.6.0',
backup: {
retention: Duration.days(15),
},
Expand Down
28 changes: 27 additions & 1 deletion packages/aws-rfdk/lib/deadline/lib/database-connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import * as path from 'path';
import {
CfnDBCluster,
CfnDBInstance,
IDatabaseCluster,
} from '@aws-cdk/aws-docdb';
Expand All @@ -22,6 +23,7 @@ import {
ISecret,
} from '@aws-cdk/aws-secretsmanager';
import {
Annotations,
IConstruct,
Stack,
} from '@aws-cdk/core';
Expand All @@ -42,7 +44,8 @@ import {
export interface DocDBConnectionOptions {

/**
* The Document DB Cluster this connection is for
* The Document DB Cluster this connection is for.
* Note: Deadline officially supports only databases that are compatible with MongoDB 3.6.
*/
readonly database: IDatabaseCluster;

Expand All @@ -59,6 +62,7 @@ export interface DocDBConnectionOptions {
export interface MongoDbInstanceConnectionOptions {
/**
* The MongoDB database to connect to.
* Note: Deadline officially supports only databases that are compatible with MongoDB 3.6.
*/
readonly database: IMongoDb;

Expand All @@ -80,6 +84,7 @@ export interface MongoDbInstanceConnectionOptions {
export abstract class DatabaseConnection {
/**
* Creates a DatabaseConnection which allows Deadline to connect to Amazon DocumentDB.
* Note: Deadline officially supports only databases that are compatible with MongoDB 3.6.
*
* Resources Deployed
* ------------------------
Expand All @@ -91,6 +96,7 @@ export abstract class DatabaseConnection {

/**
* Creates a DatabaseConnection which allows Deadline to connect to MongoDB.
* Note: Deadline officially supports only databases that are compatible with MongoDB 3.6.
*
* Resources Deployed
* ------------------------
Expand Down Expand Up @@ -163,6 +169,10 @@ class DocDBDatabaseConnection extends DatabaseConnection {
constructor(private readonly props: DocDBConnectionOptions) {
super();

if (!this.isCompatibleDocDBVersion()) {
Annotations.of(props.database).addError('engineVersion must be 3.6.0 to be compatible with Deadline');
}

this.containerEnvironment = {
// The container must fetch the credentials from Secrets Manager
DB_CREDENTIALS_URI: this.props.login.secretArn,
Expand Down Expand Up @@ -256,6 +266,22 @@ class DocDBDatabaseConnection extends DatabaseConnection {
throw new Error('The internal implementation of the AWS CDK\'s DocumentDB cluster construct may have changed. Please update to a newer RFDK for an updated implementation, or file a ticket if this is the latest release.');
}
}

/**
* Deadline is only compatible with MongoDB 3.6. This function attempts to determine whether
* the given DocDB version is compatible.
*/
protected isCompatibleDocDBVersion(): boolean {
// The defaultChild of a DocDB DatabaseCluster is a CfnDBCluster, but we only have this
// child if the customer didn't import from attributes. We can check the DB version by
// checking the value of the engineVersion property of that object.
if (this.props.database.node.defaultChild) {
const cluster = this.props.database.node.defaultChild! as CfnDBCluster;
return cluster.engineVersion?.startsWith('3.6') ?? false;
}

return true; // No information, assume it's compatible.
}
}

/**
Expand Down
2 changes: 2 additions & 0 deletions packages/aws-rfdk/lib/deadline/lib/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ export interface RepositoryProps {

/**
* Specify the database where the deadline schema needs to be initialized.
* Note that Deadline supports only databases that are compatible with MongoDB 3.6.
*
* @default A Document DB Cluster will be created with a single db.r5.large instance.
*/
Expand Down Expand Up @@ -490,6 +491,7 @@ export class Repository extends Construct implements IRepository {
const instances = props.documentDbInstanceCount ?? Repository.DEFAULT_NUM_DOCDB_INSTANCES;
const dbCluster = new DatabaseCluster(this, 'DocumentDatabase', {
masterUser: {username: 'DocDBUser'},
engineVersion: '3.6.0',
instanceProps: {
instanceType: InstanceType.of(InstanceClass.R5, InstanceSize.LARGE),
vpc: props.vpc,
Expand Down
137 changes: 137 additions & 0 deletions packages/aws-rfdk/lib/deadline/test/database-connection.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
import {
PrivateHostedZone,
} from '@aws-cdk/aws-route53';
import { Secret } from '@aws-cdk/aws-secretsmanager';
import {
Duration,
Stack,
Expand Down Expand Up @@ -77,6 +78,7 @@ describe('DocumentDB', () => {
backup: {
retention: Duration.days(15),
},
engineVersion: '3.6.0',
});

if (!database.secret) {
Expand Down Expand Up @@ -264,6 +266,141 @@ describe('DocumentDB', () => {

});

describe('DocumentDB Version Checks', () => {
let stack: Stack;
let vpc: Vpc;
beforeEach(() => {
stack = new Stack();
vpc = new Vpc(stack, 'VPC');
});

test('Compatible version', () => {
// GIVEN
const database = new DatabaseCluster(stack, 'DbCluster', {
masterUser: {
username: 'master',
},
instanceProps: {
instanceType: InstanceType.of(
InstanceClass.R5,
InstanceSize.XLARGE,
),
vpc,
vpcSubnets: {
onePerAz: true,
subnetType: SubnetType.PRIVATE,
},
},
backup: {
retention: Duration.days(15),
},
engineVersion: '3.6.0',
});

// WHEN
DatabaseConnection.forDocDB({database, login: database.secret!});

// THEN
expect(database.node.metadata.length).toBe(0);
});

test('When from attributes', () => {
// GIVEN
const sg = new SecurityGroup(stack, 'SG', {
vpc,
});
const secret = new Secret(stack, 'Secret');
const database = DatabaseCluster.fromDatabaseClusterAttributes(stack, 'DbCluster', {
clusterEndpointAddress: '1.2.3.4',
clusterIdentifier: 'foo',
instanceEndpointAddresses: [ '1.2.3.5' ],
instanceIdentifiers: [ 'i0' ],
port: 27001,
readerEndpointAddress: '1.2.3.6',
securityGroup: sg,
});

// WHEN
DatabaseConnection.forDocDB({database, login: secret});

// THEN
expect(database.node.metadata.length).toBe(0);
});

test('No engineVersion given', () => {
// GIVEN
const database = new DatabaseCluster(stack, 'DbCluster', {
masterUser: {
username: 'master',
},
instanceProps: {
instanceType: InstanceType.of(
InstanceClass.R5,
InstanceSize.XLARGE,
),
vpc,
vpcSubnets: {
onePerAz: true,
subnetType: SubnetType.PRIVATE,
},
},
backup: {
retention: Duration.days(15),
},
});

// WHEN
DatabaseConnection.forDocDB({database, login: database.secret!});

// THEN
expect(database.node.metadata).toEqual(
expect.arrayContaining([
expect.objectContaining({
type: 'aws:cdk:error',
data: 'engineVersion must be 3.6.0 to be compatible with Deadline',
}),
]),
);
});

test('engineVersion not 3.6.0', () => {
// GIVEN
const database = new DatabaseCluster(stack, 'DbCluster', {
masterUser: {
username: 'master',
},
instanceProps: {
instanceType: InstanceType.of(
InstanceClass.R5,
InstanceSize.XLARGE,
),
vpc,
vpcSubnets: {
onePerAz: true,
subnetType: SubnetType.PRIVATE,
},
},
backup: {
retention: Duration.days(15),
},
engineVersion: '4.0.0',
});

// WHEN
DatabaseConnection.forDocDB({database, login: database.secret!});

// THEN
expect(database.node.metadata).toEqual(
expect.arrayContaining([
expect.objectContaining({
type: 'aws:cdk:error',
data: 'engineVersion must be 3.6.0 to be compatible with Deadline',
}),
]),
);
});
});

describe('MongoDB', () => {
let stack: Stack;
let vpc: Vpc;
Expand Down

0 comments on commit 2f46944

Please sign in to comment.