Skip to content

Commit

Permalink
fix(lambda): compare Runtimes by value instead of identity (#2543)
Browse files Browse the repository at this point in the history
Different Runtime objects that represent the same runtime now compare as equal. This is important when using Layers, which declare compatible runtimes.
  • Loading branch information
Simon-Pierre Gingras authored and rix0rrr committed May 20, 2019
1 parent 553577a commit 584579e
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 2 deletions.
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-lambda/lib/function.ts
Expand Up @@ -479,7 +479,7 @@ export class Function extends FunctionBase {
if (this.layers.length === 5) {
throw new Error('Unable to add layer: this lambda function already uses 5 layers.');
}
if (layer.compatibleRuntimes && layer.compatibleRuntimes.indexOf(this.runtime) === -1) {
if (layer.compatibleRuntimes && !layer.compatibleRuntimes.find(runtime => runtime.equals(this.runtime))) {
const runtimes = layer.compatibleRuntimes.map(runtime => runtime.name).join(', ');
throw new Error(`This lambda function uses a runtime that is incompatible with this layer (${this.runtime.name} is not in [${runtimes}])`);
}
Expand Down
6 changes: 6 additions & 0 deletions packages/@aws-cdk/aws-lambda/lib/runtime.ts
Expand Up @@ -69,4 +69,10 @@ export class Runtime {
public toString(): string {
return this.name;
}

public equals(other: Runtime): boolean {
return other.name === this.name &&
other.family === this.family &&
other.supportsInlineCode === this.supportsInlineCode;
}
}
6 changes: 6 additions & 0 deletions packages/@aws-cdk/aws-lambda/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion packages/@aws-cdk/aws-lambda/package.json
Expand Up @@ -66,14 +66,16 @@
"@types/aws-lambda": "^8.10.24",
"@types/nock": "^9.3.1",
"@types/sinon": "^7.0.11",
"@types/lodash": "^4.14.128",
"aws-sdk": "^2.438.0",
"aws-sdk-mock": "^4.4.0",
"cdk-build-tools": "^0.31.0",
"cdk-integ-tools": "^0.31.0",
"cfn2ts": "^0.31.0",
"nock": "^10.0.6",
"pkglint": "^0.31.0",
"sinon": "^7.3.1"
"sinon": "^7.3.1",
"lodash": "^4.17.11"
},
"dependencies": {
"@aws-cdk/assets": "^0.31.0",
Expand Down
76 changes: 76 additions & 0 deletions packages/@aws-cdk/aws-lambda/test/test.function.ts
@@ -0,0 +1,76 @@
import s3 = require('@aws-cdk/aws-s3');
import cdk = require('@aws-cdk/cdk');
import _ = require('lodash');
import {Test, testCase} from 'nodeunit';
import lambda = require('../lib');

export = testCase({
'add incompatible layer'(test: Test) {
// GIVEN
const stack = new cdk.Stack(undefined, 'TestStack');
const bucket = new s3.Bucket(stack, 'Bucket');
const code = new lambda.S3Code(bucket, 'ObjectKey');

const func = new lambda.Function(stack, 'myFunc', {
runtime: lambda.Runtime.Python37,
handler: 'index.handler',
code,
});
const layer = new lambda.LayerVersion(stack, 'myLayer', {
code,
compatibleRuntimes: [lambda.Runtime.NodeJS]
});

// THEN
test.throws(() => func.addLayer(layer),
/This lambda function uses a runtime that is incompatible with this layer/);

test.done();
},
'add compatible layer'(test: Test) {
// GIVEN
const stack = new cdk.Stack(undefined, 'TestStack');
const bucket = new s3.Bucket(stack, 'Bucket');
const code = new lambda.S3Code(bucket, 'ObjectKey');

const func = new lambda.Function(stack, 'myFunc', {
runtime: lambda.Runtime.Python37,
handler: 'index.handler',
code,
});
const layer = new lambda.LayerVersion(stack, 'myLayer', {
code,
compatibleRuntimes: [lambda.Runtime.Python37]
});

// THEN
// should not throw
func.addLayer(layer);

test.done();
},
'add compatible layer for deep clone'(test: Test) {
// GIVEN
const stack = new cdk.Stack(undefined, 'TestStack');
const bucket = new s3.Bucket(stack, 'Bucket');
const code = new lambda.S3Code(bucket, 'ObjectKey');

const runtime = lambda.Runtime.Python37;
const func = new lambda.Function(stack, 'myFunc', {
runtime,
handler: 'index.handler',
code,
});
const clone = _.cloneDeep(runtime);
const layer = new lambda.LayerVersion(stack, 'myLayer', {
code,
compatibleRuntimes: [clone]
});

// THEN
// should not throw
func.addLayer(layer);

test.done();
},
});
70 changes: 70 additions & 0 deletions packages/@aws-cdk/aws-lambda/test/test.runtime.ts
@@ -0,0 +1,70 @@
import {Test, testCase} from 'nodeunit';
import {RuntimeFamily} from "../lib";
import lambda = require('../lib');

export = testCase({
'runtimes are equal for different instances'(test: Test) {
// GIVEN
const runtime1 = new lambda.Runtime('python3.7', RuntimeFamily.Python, {supportsInlineCode: true});
const runtime2 = new lambda.Runtime('python3.7', RuntimeFamily.Python, {supportsInlineCode: true});

// WHEN
const result = runtime1.equals(runtime2);

// THEN
test.strictEqual(result, true, 'Runtimes should be equal');

test.done();
},
'runtimes are equal for same instance'(test: Test) {
// GIVEN
const runtime = new lambda.Runtime('python3.7', RuntimeFamily.Python, {supportsInlineCode: true});

// WHEN
const result = runtime.equals(runtime);

// THEN
test.strictEqual(result, true, 'Runtimes should be equal');

test.done();
},
'unequal when name changes'(test: Test) {
// GIVEN
const runtime1 = new lambda.Runtime('python3.7', RuntimeFamily.Python, {supportsInlineCode: true});
const runtime2 = new lambda.Runtime('python3.6', RuntimeFamily.Python, {supportsInlineCode: true});

// WHEN
const result = runtime1.equals(runtime2);

// THEN
test.strictEqual(result, false, 'Runtimes should be unequal when name changes');

test.done();
},
'unequal when family changes'(test: Test) {
// GIVEN
const runtime1 = new lambda.Runtime('python3.7', RuntimeFamily.Python, {supportsInlineCode: true});
const runtime2 = new lambda.Runtime('python3.7', RuntimeFamily.Java, {supportsInlineCode: true});

// WHEN
const result = runtime1.equals(runtime2);

// THEN
test.strictEqual(result, false, 'Runtimes should be unequal when family changes');

test.done();
},
'unequal when supportsInlineCode changes'(test: Test) {
// GIVEN
const runtime1 = new lambda.Runtime('python3.7', RuntimeFamily.Python, {supportsInlineCode: true});
const runtime2 = new lambda.Runtime('python3.7', RuntimeFamily.Python, {supportsInlineCode: false});

// WHEN
const result = runtime1.equals(runtime2);

// THEN
test.strictEqual(result, false, 'Runtimes should be unequal when supportsInlineCode changes');

test.done();
},
});

0 comments on commit 584579e

Please sign in to comment.