Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(deadline): adding version check for staging deadline #109

Merged
merged 17 commits into from
Sep 17, 2020
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/aws-rfdk/lib/core/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ export * from './mountable-filesystem';
export { RFDK_VERSION } from './runtime-info';
export * from './script-assets';
export * from './staticip-server';
export * from './utils';
export * from './x509-certificate';
54 changes: 54 additions & 0 deletions packages/aws-rfdk/lib/core/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

export class Utils {
/**
* This method compares two version strings
*
* @param versionFirst
* @param versionSecond
*
* @returns negative value if first version is smaller than second version;
* 0 if the versions matches, positive value if first version is greater
* than second version.
*/
public static versionCompare(versionFirst: string, versionSecond: string): number {
const regExStripZero = /(\.0+)+$/;
const versionArrayFirst = versionFirst.replace(regExStripZero, '').split('.');
const versionArraySecond = versionSecond.replace(regExStripZero, '').split('.');
const minLen = Math.min(versionArrayFirst.length, versionArraySecond.length);

for (let i = 0; i < minLen; i++) {
const diff = parseInt(versionArrayFirst[i], 10) - parseInt(versionArraySecond[i], 10);
if (diff) {
return diff;
}
}
return versionArrayFirst.length - versionArraySecond.length;
}

/**
* This method validates the given string for a sequence '.' separated numbers.
*
* @param version the string to be validated.
*
* @returns true if the format is correct, else false.
*/
public static validateVersionFormat(version: string): boolean {
/**
* Regex: ^\d+(?:\.\d+){3}$
* Matches a sequence of '.' separated numbers with exactly 4 digits.
* - ^ asserts position at start of a line.
* - \d+ Matches one or more digits.
* - (?:\.\d+) Matches a dot and the following one or more digits.
* - * Matches previous pattern zero or more times.
* - $ asserts position at the end of a line
*/
if (version.match(/^\d+(?:\.\d+)*$/g)) {
return true;
}
return false;
}
}
92 changes: 92 additions & 0 deletions packages/aws-rfdk/lib/core/test/utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

import { Utils } from '../lib';

describe('Utils', () => {
describe('.versionCompare', () => {
test.each<[string, { firstVersion: string, secondVersion: string, expectedValue: number }]>([
[
'equal version',
{
firstVersion: '1',
secondVersion: '1',
expectedValue: 0,
},
], [
'equal version',
{
firstVersion: '1',
secondVersion: '1.0',
expectedValue: 0,
},
], [
'equal version',
{
firstVersion: '1.0',
secondVersion: '1.0.0',
expectedValue: 0,
},
], [
'less than',
{
firstVersion: '1',
secondVersion: '2',
expectedValue: -1,
},
], [
'less than',
{
firstVersion: '1.2',
secondVersion: '2',
expectedValue: -1,
},
], [
'greater than',
{
firstVersion: '2.0.1',
secondVersion: '2.0',
expectedValue: 2,
},
],
])('%s', (_name, testcase) => {
const { firstVersion, secondVersion, expectedValue } = testcase;
// WHEN
const result = Utils.versionCompare(firstVersion, secondVersion);

expect(result).toEqual(expectedValue);
});
});

describe('.validateVersionFormat', () => {
test.each<[string, { version: string, expectedValue: boolean }]>([
[
'ending with .',
{
version: '10.1.9.',
expectedValue: false,
},
], [
'empty string',
{
version: '',
expectedValue: false,
},
], [
'correct version',
{
version: '10.1.9.2',
expectedValue: true,
},
],
])('%s', (_name, testcase) => {
const { version, expectedValue } = testcase;
// WHEN
const result = Utils.validateVersionFormat(version);

expect(result).toEqual(expectedValue);
});
});
});
11 changes: 11 additions & 0 deletions packages/aws-rfdk/lib/deadline/lib/stage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import * as path from 'path';
import { DockerImageAsset } from '@aws-cdk/aws-ecr-assets';
import { Construct } from '@aws-cdk/core';

import { Utils } from '../../core';
import { VersionQuery } from './version';

/**
Expand Down Expand Up @@ -99,6 +100,8 @@ export interface StageProps {
* requires to deploy Deadline. It should contain a manifest file, the Deadline
* installers, and any supporting files required for building the Deadline
* container.
*
* Note: Current version of RFDK supports Deadline v10.1.9 and later.
*/
export class Stage {
/**
Expand Down Expand Up @@ -152,6 +155,14 @@ export class Stage {
throw new Error('Manifest contains no "version" key');
} else if (typeof version !== 'string') {
throw new TypeError(`Expected a string "version" but got: ${typeof version}`);
} else if (!Utils.validateVersionFormat(version)) {
throw new Error(`Invalid version format - ${version}`);
}

// Do minimum supported deadline version check
const minimumSupportedVersion = '10.1.9';
if (Utils.versionCompare(version, minimumSupportedVersion) < 0) {
throw new TypeError(`Staged Deadline Version (${version}) is less than the minimum supported version (${minimumSupportedVersion})`);
}

return true;
Expand Down
70 changes: 57 additions & 13 deletions packages/aws-rfdk/lib/deadline/test/stage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ describe('Stage', () => {
// GIVEN
const manifest: Manifest = {
schema: 1,
version: '1.2.3.4',
version: '10.1.9.2',
recipes: {},
};

Expand Down Expand Up @@ -77,10 +77,34 @@ describe('Stage', () => {
});
});

describe('.fromDirectory', () => {
test('not supported version failure', () => {
// GIVEN
const manifest: Manifest = {
schema: 1,
version: '10.1.8.0',
recipes: {},
};

// WHEN
const readFileSync = jest.spyOn(fs, 'readFileSync');
readFileSync.mockReturnValue(JSON.stringify(manifest));

// THEN
expect(() => {
require('../lib').Stage.fromDirectory(STAGE_PATH) // eslint-disable-line
}).toThrow('Staged Deadline Version (10.1.8.0) is less than the minimum supported version (10.1.9)');

readFileSync.mockRestore();
jest.resetModules();
});

});

test('has manifest', () => {
const manifest: Manifest = {
schema: 1,
version: '1.2.3.4',
version: '10.1.9.2',
recipes: {
a: {
title: 'a-title',
Expand Down Expand Up @@ -131,7 +155,7 @@ describe('Stage', () => {
'missing schema',
{
manifest: {
version: '1.2.3.4',
version: '10.1.9.2',
recipes: {},
},
expectedError: /Manifest contains no "schema" key/,
Expand All @@ -141,7 +165,7 @@ describe('Stage', () => {
'wrong schema type', {
manifest: {
schema: 'a',
version: '1.2.3.4',
version: '10.1.9.2',
recipes: {},
},
expectedError: /Expected a numeric "schema" but got:/,
Expand All @@ -156,6 +180,26 @@ describe('Stage', () => {
expectedError: /Manifest contains no "version" key/,
},
],
[
'incorrect version format', {
manifest: {
schema: 1,
version: '10.1.',
recipes: {},
},
expectedError: /Invalid version format/,
},
],
[
'version not supported', {
manifest: {
schema: 1,
version: '10.1',
recipes: {},
},
expectedError: 'Staged Deadline Version (10.1) is less than the minimum supported version (10.1.9)',
},
],
])('%s', (_name, testcase) => {
const { manifest, expectedError } = testcase;
// WHEN
Expand Down Expand Up @@ -225,7 +269,7 @@ describe('Stage', () => {
recipeName: recipe,
},
schema: 1,
version: '1.2.3.4',
version: '10.1.9.2',
};

// WHEN
Expand Down Expand Up @@ -287,7 +331,7 @@ describe('Stage', () => {
const stage = new ReloadedStageWithPublicConstructor({
path: STAGE_PATH,
manifest: {
version: '1.2.3.4',
version: '10.1.9.2',
schema: 1,
recipes: {
[recipeName]: recipe,
Expand Down Expand Up @@ -316,7 +360,7 @@ describe('Stage', () => {
// GIVEN
const manifest: Manifest = {
schema: 1,
version: '1.2.3.4',
version: '10.1.9.2',
recipes: {},
};
const invalidRecipeName = 'this-recipe-does-not-exist';
Expand All @@ -342,7 +386,7 @@ describe('Stage', () => {
const stack = new Stack(app, 'Stack');
const manifest: Manifest = {
schema: 1,
version: '1.2.3.4',
version: '10.1.9.2',
recipes: {},
};
const stage = new StageWithPulicConstructor({
Expand All @@ -355,15 +399,15 @@ describe('Stage', () => {
const linuxFullVersionString = version.linuxFullVersionString();

// THEN
expect(version.majorVersion).toEqual(1);
expect(version.minorVersion).toEqual(2);
expect(version.releaseVersion).toEqual(3);
expect(version.majorVersion).toEqual(10);
expect(version.minorVersion).toEqual(1);
expect(version.releaseVersion).toEqual(9);

expect(version.linuxInstallers).toBeDefined();
expect(version.linuxInstallers?.patchVersion).toEqual(4);
expect(version.linuxInstallers?.patchVersion).toEqual(2);

expect(linuxFullVersionString).toBeDefined();
expect(linuxFullVersionString).toEqual('1.2.3.4');
expect(linuxFullVersionString).toEqual('10.1.9.2');
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ describe('ThinkboxDockerRecipes', () => {

const MAJOR_VERSION = 10;
const MINOR_VERSION = 1;
const RELEASE_VERSION = 8;
const PATCH_VERSION = 5;
const RELEASE_VERSION = 9;
const PATCH_VERSION = 2;
const FULL_VERSION_STRING = `${MAJOR_VERSION}.${MINOR_VERSION}.${RELEASE_VERSION}.${PATCH_VERSION}`;

beforeEach(() => {
Expand Down