Skip to content

Commit

Permalink
feat(version-query): Created VersionQuery construct
Browse files Browse the repository at this point in the history
- Created a construct that contains a CustomResource that determines the
S3 URI's to the Deadline installers for either the requested version or
the latest.
- Integrated the VersionQuery construct into the Repository
  • Loading branch information
horsmand committed Oct 14, 2020
1 parent 479af57 commit e3ab9fa
Show file tree
Hide file tree
Showing 30 changed files with 1,089 additions and 823 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
ThinkboxDockerRecipes,
UsageBasedLicense,
UsageBasedLicensing,
VersionQuery,
)


Expand Down Expand Up @@ -117,11 +118,13 @@ def __init__(self, scope: Construct, stack_id: str, *, props: ServiceTierProps,
stage=Stage.from_directory(props.docker_recipes_stage_path)
)

version_query = VersionQuery(self, 'VersionQuery')

repository = Repository(
self,
'Repository',
vpc=props.vpc,
version=recipes.version,
version=versionQuery,
database=props.database,
file_system=props.file_system,
repository_installation_timeout=Duration.minutes(20)
Expand All @@ -142,7 +145,6 @@ def __init__(self, scope: Construct, stack_id: str, *, props: ServiceTierProps,
self,
'RenderQueue',
vpc=props.vpc,
version=recipes.version,
images=recipes.render_queue_images,
repository=repository,
hostname=RenderQueueHostNameProps(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
IPrivateHostedZone,
} from '@aws-cdk/aws-route53';
import * as cdk from '@aws-cdk/core';
import {
import {
IMountableLinuxFilesystem,
X509CertificatePem,
} from 'aws-rfdk';
Expand All @@ -29,9 +29,10 @@ import {
ThinkboxDockerRecipes,
UsageBasedLicense,
UsageBasedLicensing,
VersionQuery,
} from 'aws-rfdk/deadline';
import {
Secret
import {
Secret,
} from '@aws-cdk/aws-secretsmanager';
import { Duration } from '@aws-cdk/core';

Expand Down Expand Up @@ -132,9 +133,12 @@ export class ServiceTier extends cdk.Stack {
stage: Stage.fromDirectory(props.dockerRecipesStagePath),
});

// By not specifying the version property, this will always pull the latest version
const versionQuery = new VersionQuery(this, 'VersionQuery');

const repository = new Repository(this, 'Repository', {
vpc: props.vpc,
version: recipes.version,
version: versionQuery,
database: props.database,
fileSystem: props.fileSystem,
repositoryInstallationTimeout: Duration.minutes(20),
Expand All @@ -150,7 +154,6 @@ export class ServiceTier extends cdk.Stack {
});
this.renderQueue = new RenderQueue(this, 'RenderQueue', {
vpc: props.vpc,
version: recipes.version,
images: recipes.renderQueueImages,
repository: repository,
hostname: {
Expand All @@ -170,7 +173,7 @@ export class ServiceTier extends cdk.Stack {
});
this.renderQueue.connections.allowDefaultPortFrom(this.bastion);

const ublCertSecret = Secret.fromSecretArn(this, 'UBLCertsSecret', props.ublCertsSecretArn);
const ublCertSecret = Secret.fromSecretArn(this, 'UBLCertsSecret', props.ublCertsSecretArn);
this.ublLicensing = new UsageBasedLicensing(this, 'UBLLicensing', {
vpc: props.vpc,
images: recipes.ublImages,
Expand Down
1 change: 0 additions & 1 deletion integ/lib/render-struct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ export class RenderStruct extends Construct {
vpc,
repository: props.repository,
images: recipes.renderQueueImages,
version: recipes.version,
logGroupProps: {
logGroupPrefix: Stack.of(this).stackName + '-' + id,
},
Expand Down
12 changes: 4 additions & 8 deletions integ/lib/storage-struct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { PrivateHostedZone } from '@aws-cdk/aws-route53';
import { ISecret } from '@aws-cdk/aws-secretsmanager';
import { Construct, Duration, RemovalPolicy, Stack } from '@aws-cdk/core';
import { MongoDbInstance, MongoDbPostInstallSetup, MongoDbSsplLicenseAcceptance, MongoDbVersion, MountableEfs, X509CertificatePem, X509CertificatePkcs12 } from 'aws-rfdk';
import { DatabaseConnection, Repository, Stage, ThinkboxDockerRecipes } from 'aws-rfdk/deadline';
import { DatabaseConnection, Repository, VersionQuery } from 'aws-rfdk/deadline';


// Interface for supplying database connection and accompanying secret for credentials
Expand Down Expand Up @@ -44,16 +44,12 @@ export class StorageStruct extends Construct {
userAcceptsSSPL === 'true' ? MongoDbSsplLicenseAcceptance.USER_ACCEPTS_SSPL : MongoDbSsplLicenseAcceptance.USER_REJECTS_SSPL;

const infrastructureStackName = 'RFDKIntegInfrastructure' + props.integStackTag;
const stagePath = process.env.DEADLINE_STAGING_PATH!.toString();

// Get farm VPC from lookup
const vpc = Vpc.fromLookup(this, 'Vpc', { tags: { StackName: infrastructureStackName }}) as Vpc;

// Create recipes object used to prepare the Deadline installers
const recipes = new ThinkboxDockerRecipes(this, 'DockerRecipes', {
stage: Stage.fromDirectory(stagePath),
});
const version = recipes.version;
// This will get the installers for the latest version of Deadline if the version property isn't specified
const versionQuery = new VersionQuery(this, 'VersionQuery');

let cacert;
let database;
Expand Down Expand Up @@ -188,7 +184,7 @@ export class StorageStruct extends Construct {
vpc,
database: databaseConnection,
fileSystem: deadlineMountableEfs,
version: version,
version: versionQuery,
repositoryInstallationTimeout: Duration.minutes(20),
logGroupProps: {
logGroupPrefix: Stack.of(this).stackName + '-' + id,
Expand Down
223 changes: 212 additions & 11 deletions packages/aws-rfdk/lib/core/lambdas/nodejs/version-provider/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,52 +7,253 @@

import { LambdaContext } from '../lib/aws-lambda';
import { CfnRequestEvent, SimpleCustomResource } from '../lib/custom-resource';
import { Version } from './version';
import {
VersionProvider,
IVersionProviderProperties,
IVersionedUris,
Platform,
Product,
VersionProvider,
} from './version-provider';

/**
* The input to this Custom Resource
*/
export interface IVersionProviderResourceProperties {
/**
* The version of Deadline to look up.
*/
readonly versionString?: string,
}

/**
* Output of this Custom Resource, it is all made up of a flat structure of strings to avoid issues with how the
* results are tokenized by CDK to be used in constructs.
*/
export interface FlatVersionedUriOutput {
/**
* The S3 bucket holding the installers. This makes the assumption they are all in the same bucket.
*/
readonly S3Bucket: string;

/**
* The major version for all the URI's in this structure.
*/
readonly MajorVersion: string;

/**
* The minor version for all the URI's in this structure.
*/
readonly MinorVersion: string;

/**
* The release version for all the URI's in this structure.
*/
readonly ReleaseVersion: string;

/**
* The full version of the Linux installers, saved as "major.minor.release.patch". For example: "10.1.10.6".
*/
readonly LinuxDeadlineVersion: string;

/**
* The full version of the Mac installers, saved as "major.minor.release.patch". For example: "10.1.10.6".
*/
readonly MacDeadlineVersion: string;

/**
* The full version of the Windows installers, saved as "major.minor.release.patch". For example: "10.1.10.6".
*/
readonly WindowsDeadlineVersion: string;

/**
* The URI of the bundled Deadline installers for Linux.
*/
readonly LinuxBundle: string;

/**
* The URI of the Deadline client installer for Linux.
*/
readonly LinuxClientInstaller: string;

/**
* The URI of the Deadline repository installer for Linux.
*/
readonly LinuxRepositoryInstaller: string;

/**
* The URI of the Deadline certificate installer for Linux.
* @default - No installer provided
*/
readonly LinuxCertificateInstaller?: string;

/**
* The URI of the bundled Deadline installers for Mac.
*/
readonly MacBundle: string;

/**
* The URI of the bundled Deadline installers for Windows.
*/
readonly WindowsBundle: string;

/**
* The URI of the Deadline client installer for Windows.
*/
readonly WindowsClientInstaller: string;

/**
* The URI of the Deadline repository installer for Windows.
*/
readonly WindowsRepositoryInstaller: string;

/**
* The URI of the Deadline certificate installer for Windows.
* @default - No installer provided
*/
readonly WindowsCertificateInstaller?: string;

/**
* The full version of the Deadline Docker recipes, saved as "major.minor.release.patch". For example: "10.1.10.6".
*/
readonly LinuxDeadlineDockerVersion: string;

/**
* The URI of the Deadline Docker recipes for Linux.
*/
readonly LinuxDockerRecipes: string;
}

/**
* This custom resource will parse and return the S3 URI's of the Deadline installers and Docker recipes for use in
* any constructs that need to install Deadline.
*/
export class VersionProviderResource extends SimpleCustomResource {
readonly versionProvider: VersionProvider;

constructor(indexFilePath?: string) {
constructor() {
super();
this.versionProvider = new VersionProvider(indexFilePath);
this.versionProvider = new VersionProvider();
}

/**
* @inheritdoc
*/
/* istanbul ignore next */ // @ts-ignore
public validateInput(data: object): boolean {
return this.versionProvider.implementsIVersionProviderProperties(data);
return this.implementsIVersionProviderResourceProperties(data);
}

/**
* @inheritdoc
*/
// @ts-ignore -- we do not use the physicalId
public async doCreate(physicalId: string, resourceProperties: IVersionProviderProperties): Promise<Map<Platform, IVersionedUris>> {
return await this.versionProvider.getVersionUris(resourceProperties);
public async doCreate(physicalId: string, resourceProperties: IVersionProviderResourceProperties): Promise<FlatVersionedUriOutput> {
const deadlinePlatFormVersionedUris = await this.versionProvider.getVersionUris({
versionString: resourceProperties.versionString,
product: Product.deadline,
});

const deadlineLinux = deadlinePlatFormVersionedUris.get(Platform.linux)!;
const deadlineLinuxUris = deadlineLinux.Uris;
const deadlineMac = deadlinePlatFormVersionedUris.get(Platform.mac)!;
const deadlineMacUris = deadlineMac.Uris;
const deadlineWindows = deadlinePlatFormVersionedUris.get(Platform.windows)!;
const deadlineWindowsUris = deadlineWindows.Uris;

const deadlineDockerPlatFormVersionedUris = await this.versionProvider.getVersionUris({
versionString: resourceProperties.versionString,
product: Product.deadlineDocker,
platform: Platform.linux,
});

const deadlineDockerLinux = deadlineDockerPlatFormVersionedUris.get(Platform.linux)!;
const deadlineDockerLinuxUris = deadlineDockerLinux.Uris;

const s3Bucket = this.parseS3BucketName(deadlineLinuxUris.bundle);

return {
S3Bucket: s3Bucket,
MajorVersion: deadlineLinux.MajorVersion,
MinorVersion: deadlineLinux.MinorVersion,
ReleaseVersion: deadlineLinux.ReleaseVersion,
LinuxDeadlineVersion: Version.convertToFullVersionString(
deadlineLinux.MajorVersion,
deadlineLinux.MinorVersion,
deadlineLinux.ReleaseVersion,
deadlineLinux.PatchVersion),
LinuxBundle: deadlineLinuxUris.bundle,
LinuxClientInstaller: deadlineLinuxUris.clientInstaller!,
LinuxRepositoryInstaller: deadlineLinuxUris.repositoryInstaller!,
LinuxCertificateInstaller: deadlineLinuxUris.certificateInstaller,
MacDeadlineVersion: Version.convertToFullVersionString(
deadlineMac.MajorVersion,
deadlineMac.MinorVersion,
deadlineMac.ReleaseVersion,
deadlineMac.PatchVersion),
MacBundle: deadlineMacUris.bundle,
WindowsDeadlineVersion: Version.convertToFullVersionString(
deadlineWindows.MajorVersion,
deadlineWindows.MinorVersion,
deadlineWindows.ReleaseVersion,
deadlineWindows.PatchVersion),
WindowsBundle: deadlineWindowsUris.bundle,
WindowsClientInstaller: deadlineWindowsUris.clientInstaller!,
WindowsRepositoryInstaller: deadlineWindowsUris.repositoryInstaller!,
WindowsCertificateInstaller: deadlineWindowsUris.certificateInstaller,
LinuxDeadlineDockerVersion: Version.convertToFullVersionString(
deadlineDockerLinux.MajorVersion,
deadlineDockerLinux.MinorVersion,
deadlineDockerLinux.ReleaseVersion,
deadlineDockerLinux.PatchVersion),
LinuxDockerRecipes: deadlineDockerLinuxUris.bundle,
};
}

/**
* @inheritdoc
*/
/* istanbul ignore next */ // @ts-ignore
public async doDelete(physicalId: string, resourceProperties: IVersionProviderProperties): Promise<void> {
public async doDelete(physicalId: string, resourceProperties: IVersionProviderResourceProperties): Promise<void> {
// Nothing to do -- we don't modify anything.
return;
}

private implementsIVersionProviderResourceProperties(value: any): boolean {
if (!value || typeof(value) !== 'object') { return false; }

if (value.versionString) {
if (!Version.validateVersionString(value.versionString)) { return false; }
}

return true;
}

/**
* Parses the S3 bucket name from an S3 URI.
*/
private parseS3BucketName(uri: string): string {
let bucketName;
try {
bucketName = this.findRegex(uri, /^s3:\/\/([A-Za-z0-9\-]+)\//)[1];
} catch (e) {
throw new Error(`Could not parse bucket name from ${uri}`);
}
return bucketName;
}

// Assumes a single capture is in the regex
private findRegex(str: string, re: RegExp): RegExpMatchArray {
const found = str.match(re);

if (found === null) {
throw new Error(`Couldn't find regular expression ${re} in ${str}`);
}

return found;
}
}

/**
* The handler used to provide the installer links for the requested version
*/
/* istanbul ignore next */
export async function handler(event: CfnRequestEvent, context: LambdaContext): Promise<string> {
const versionProvider = new VersionProviderResource();
return await versionProvider.handler(event, context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@

export * from './handler';
export * from './version-provider';
export * from './version';
Loading

0 comments on commit e3ab9fa

Please sign in to comment.