Skip to content

Commit 36f29b6

Browse files
author
Elad Ben-Israel
authored
feat(aws-lambda): improvements to the code and runtime APIs (#945)
* Simplify usage of assets for Lambda code. Instead of `Code.directory` and `Code.file`, just use `Code.asset(path)` and we will determine if this is a directory. * If `Code.asset` (or the deprecated `Code.file`) references a non-zip file, an error will be thrown. * Simplify `lambda.Runtime` by deleting the interfaces `InlinableRuntime` and `InlinableJavaScriptRuntime`, which fixes #902 and fixes #188 * Remove `lambda.InlineJavaScriptLambda`. * Remove `lambda.Runtime.NodeJS43Edge` which fixes #947 * Add inlining support for NodeJS 8.10 (fixes #947) * No need to provide read permissions for asset (fixes #664) BREAKING CHANGE: The construct `lambda.InlineJavaScriptLambda` is no longer supported. Use `lambda.Code.inline` instead; `lambda.Runtime.NodeJS43Edge` runtime is removed. CloudFront docs [stipulate](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-requirements-limits.html#lambda-requirements-lambda-function-configuration) that you should use node6.10 or node8.10. It is always possible to use any value by instantiating a `lambda.Runtime` object.
1 parent e790db5 commit 36f29b6

17 files changed

+292
-699
lines changed

packages/@aws-cdk/aws-lambda/README.md

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import lambda = require('@aws-cdk/aws-lambda');
88
const fn = new lambda.Function(this, 'MyFunction', {
99
runtime: lambda.Runtime.NodeJS810,
1010
handler: 'index.handler',
11-
code: lambda.Code.inline('exports.handler = function(event, ctx, cb) { return cb(null, "hi"); }'),
11+
code: lambda.Code.asset('./lambda-handler'),
1212
});
1313
```
1414

@@ -17,18 +17,15 @@ const fn = new lambda.Function(this, 'MyFunction', {
1717
The `lambda.Code` class includes static convenience methods for various types of
1818
runtime code.
1919

20-
* `lambda.Code.bucket(bucket, key[, objectVersion])` - specify an S3 object that
21-
contains the archive of your runtime code.
20+
* `lambda.Code.bucket(bucket, key[, objectVersion])` - specify an S3 object
21+
that contains the archive of your runtime code.
2222
* `lambda.Code.inline(code)` - inline the handle code as a string. This is
23-
limited to 4KB. The class `InlineJavaScriptLambda` can be used to simplify
24-
inlining JavaScript functions.
25-
* `lambda.Code.directory(directory)` - specify a directory in the local filesystem
26-
which will be zipped and uploaded to S3 before deployment.
27-
* `lambda.Code.file(path)` - specify a file to be used for Lambda code. This can
28-
be, for example a JAR or a ZIP file, based on the runtime used.
29-
30-
The following example shows how to define a Python function and deploy the code from the
31-
local directory `my-lambda-handler` to it:
23+
limited to 4KB.
24+
* `lambda.Code.asset(path)` - specify a directory or a .zip file in the local
25+
filesystem which will be zipped and uploaded to S3 before deployment.
26+
27+
The following example shows how to define a Python function and deploy the code
28+
from the local directory `my-lambda-handler` to it:
3229

3330
[Example of Lambda Code from Local Assets](test/integ.assets.lit.ts)
3431

packages/@aws-cdk/aws-lambda/lib/code.ts

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import assets = require('@aws-cdk/assets');
22
import s3 = require('@aws-cdk/aws-s3');
3+
import fs = require('fs');
34
import { Function as Func } from './lambda';
45
import { cloudformation } from './lambda.generated';
56

@@ -22,10 +23,19 @@ export abstract class Code {
2223
return new InlineCode(code);
2324
}
2425

26+
/**
27+
* Loads the function code from a local disk asset.
28+
* @param path Either a directory with the Lambda code bundle or a .zip file
29+
*/
30+
public static asset(path: string) {
31+
return new AssetCode(path);
32+
}
33+
2534
/**
2635
* @returns Zip archives the contents of a directory on disk and uses this
2736
* as the lambda handler's code.
2837
* @param directoryToZip The directory to zip
38+
* @deprecated use `lambda.Code.asset(path)` (no need to specify if it's a file or a directory)
2939
*/
3040
public static directory(directoryToZip: string) {
3141
return new AssetCode(directoryToZip, assets.AssetPackaging.ZipDirectory);
@@ -34,6 +44,7 @@ export abstract class Code {
3444
/**
3545
* @returns Uses a file on disk as a lambda handler's code.
3646
* @param filePath The file path
47+
* @deprecated use `lambda.Code.asset(path)` (no need to specify if it's a file or a directory)
3748
*/
3849
public static file(filePath: string) {
3950
return new AssetCode(filePath, assets.AssetPackaging.File);
@@ -108,16 +119,27 @@ export class InlineCode extends Code {
108119
* Lambda code from a local directory.
109120
*/
110121
export class AssetCode extends Code {
122+
/**
123+
* The asset packaging.
124+
*/
125+
public readonly packaging: assets.AssetPackaging;
126+
111127
private asset?: assets.Asset;
112128

113129
/**
114130
* @param path The path to the asset file or directory.
115-
* @param packaging The asset packaging format
131+
* @param packaging The asset packaging format (optional, determined automatically)
116132
*/
117-
constructor(
118-
private readonly path: string,
119-
private readonly packaging: assets.AssetPackaging) {
133+
constructor(public readonly path: string, packaging?: assets.AssetPackaging) {
120134
super();
135+
136+
if (packaging !== undefined) {
137+
this.packaging = packaging;
138+
} else {
139+
this.packaging = fs.lstatSync(path).isDirectory()
140+
? assets.AssetPackaging.ZipDirectory
141+
: assets.AssetPackaging.File;
142+
}
121143
}
122144

123145
public bind(lambda: Func) {
@@ -126,7 +148,9 @@ export class AssetCode extends Code {
126148
packaging: this.packaging
127149
});
128150

129-
this.asset.grantRead(lambda.role);
151+
if (!this.asset.isZipArchive) {
152+
throw new Error(`Asset must be a .zip file or a directory (${this.path})`);
153+
}
130154
}
131155

132156
public toJSON(): cloudformation.FunctionResource.CodeProperty {

packages/@aws-cdk/aws-lambda/lib/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ export * from './permission';
55
export * from './pipeline-action';
66
export * from './runtime';
77
export * from './code';
8-
export * from './inline';
98
export * from './lambda-version';
109
export * from './singleton-lambda';
1110

packages/@aws-cdk/aws-lambda/lib/inline.ts

Lines changed: 0 additions & 129 deletions
This file was deleted.

packages/@aws-cdk/aws-lambda/lib/runtime.ts

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,58 +3,59 @@ export interface LambdaRuntimeProps {
33
* Whether the ``ZipFile`` (aka inline code) property can be used with this runtime.
44
* @default false
55
*/
6-
readonly supportsInlineCode?: boolean;
6+
supportsInlineCode?: boolean;
7+
}
8+
9+
export enum RuntimeFamily {
10+
NodeJS,
11+
Java,
12+
Python,
13+
DotNetCore,
14+
Go
715
}
816

917
/**
1018
* Lambda function runtime environment.
19+
*
20+
* If you need to use a runtime name that doesn't exist as a static member, you
21+
* can instantiate a `Runtime` object, e.g: `new Runtime('nodejs99.99')`.
1122
*/
12-
export class Runtime implements InlinableRuntime, InlinableJavaScriptRuntime {
13-
/* tslint:disable variable-name */
14-
public static readonly NodeJS = new Runtime('nodejs', { supportsInlineCode: true }) as InlinableJavaScriptRuntime;
15-
// Using ``as InlinableLambdaRuntime`` because that class cannot be defined just yet
16-
public static readonly NodeJS43 = new Runtime('nodejs4.3', { supportsInlineCode: true }) as InlinableJavaScriptRuntime;
17-
public static readonly NodeJS43Edge = new Runtime('nodejs4.3-edge');
18-
// Using ``as InlinableLambdaRuntime`` because that class cannot be defined just yet
19-
public static readonly NodeJS610 = new Runtime('nodejs6.10', { supportsInlineCode: true }) as InlinableJavaScriptRuntime;
20-
public static readonly NodeJS810 = new Runtime('nodejs8.10');
21-
public static readonly Java8 = new Runtime('java8');
22-
// Using ``as InlinableLambdaRuntime`` because that class cannot be defined just yet
23-
public static readonly Python27 = new Runtime('python2.7', { supportsInlineCode: true }) as InlinableRuntime;
24-
// Using ``as InlinableLambdaRuntime`` because that class cannot be defined just yet
25-
public static readonly Python36 = new Runtime('python3.6', { supportsInlineCode: true }) as InlinableRuntime;
26-
public static readonly DotNetCore1 = new Runtime('dotnetcore1.0');
27-
public static readonly DotNetCore2 = new Runtime('dotnetcore2.0');
28-
public static readonly DotNetCore21 = new Runtime('dotnetcore2.1');
29-
public static readonly Go1x = new Runtime('go1.x');
30-
/* tslint:enable variable-name */
23+
export class Runtime {
24+
public static readonly NodeJS = new Runtime('nodejs', RuntimeFamily.NodeJS, { supportsInlineCode: true });
25+
public static readonly NodeJS43 = new Runtime('nodejs4.3', RuntimeFamily.NodeJS, { supportsInlineCode: true });
26+
public static readonly NodeJS610 = new Runtime('nodejs6.10', RuntimeFamily.NodeJS, { supportsInlineCode: true });
27+
public static readonly NodeJS810 = new Runtime('nodejs8.10', RuntimeFamily.NodeJS, { supportsInlineCode: true });
28+
public static readonly Python27 = new Runtime('python2.7', RuntimeFamily.Python, { supportsInlineCode: true });
29+
public static readonly Python36 = new Runtime('python3.6', RuntimeFamily.Python, { supportsInlineCode: true });
30+
public static readonly Java8 = new Runtime('java8', RuntimeFamily.Java);
31+
public static readonly DotNetCore1 = new Runtime('dotnetcore1.0', RuntimeFamily.DotNetCore);
32+
public static readonly DotNetCore2 = new Runtime('dotnetcore2.0', RuntimeFamily.DotNetCore);
33+
public static readonly DotNetCore21 = new Runtime('dotnetcore2.1', RuntimeFamily.DotNetCore);
34+
public static readonly Go1x = new Runtime('go1.x', RuntimeFamily.Go);
3135

32-
/** The name of this runtime, as expected by the Lambda resource. */
36+
/**
37+
* The name of this runtime, as expected by the Lambda resource.
38+
*/
3339
public readonly name: string;
34-
/** Whether the ``ZipFile`` (aka inline code) property can be used with this runtime. */
40+
41+
/**
42+
* Whether the ``ZipFile`` (aka inline code) property can be used with this
43+
* runtime.
44+
*/
3545
public readonly supportsInlineCode: boolean;
3646

37-
constructor(name: string, props: LambdaRuntimeProps = {}) {
47+
/**
48+
* The runtime family.
49+
*/
50+
public readonly family?: RuntimeFamily;
51+
52+
constructor(name: string, family?: RuntimeFamily, props: LambdaRuntimeProps = { }) {
3853
this.name = name;
3954
this.supportsInlineCode = !!props.supportsInlineCode;
55+
this.family = family;
4056
}
4157

4258
public toString(): string {
4359
return this.name;
4460
}
4561
}
46-
47-
/**
48-
* A ``LambdaRuntime`` that can be used in conjunction with the ``ZipFile``
49-
* property of the ``AWS::Lambda::Function`` resource.
50-
*/
51-
export interface InlinableRuntime {
52-
readonly name: string;
53-
readonly supportsInlineCode: boolean;
54-
}
55-
56-
/**
57-
* A ``LambdaRuntime`` that can be used for inlining JavaScript.
58-
*/
59-
// tslint:disable-next-line:no-empty-interface this is a marker to allow type-safe declarations
60-
export interface InlinableJavaScriptRuntime extends InlinableRuntime {}

0 commit comments

Comments
 (0)