Skip to content

Commit

Permalink
chore(lambda): current version for singleton functions (#9892)
Browse files Browse the repository at this point in the history
Add `currentVersion` for singleton functions. This makes it possible to
use them for Lambda@Edge.

To achieve this, make `ensureLambda()` return a `Function` and not an `IFunction`
(which now allows to remove the default implementation of `_checkEdgeCompatibilty()`
in `FunctionBase`).

Also remove deprecated calls to `addVersion()` introduced in #9562.


----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
jogold committed Aug 26, 2020
1 parent 71c60f2 commit e6db2a0
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 25 deletions.
36 changes: 36 additions & 0 deletions packages/@aws-cdk/aws-cloudfront/test/distribution.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,42 @@ describe('with Lambda@Edge functions', () => {

expect(() => app.synth()).toThrow(/KEY/);
});

test('with singleton function', () => {
const singleton = new lambda.SingletonFunction(stack, 'Singleton', {
uuid: 'singleton-for-cloudfront',
runtime: lambda.Runtime.NODEJS_12_X,
code: lambda.Code.fromInline('code'),
handler: 'index.handler',
});

new Distribution(stack, 'MyDist', {
defaultBehavior: {
origin,
edgeLambdas: [
{
functionVersion: singleton.currentVersion,
eventType: LambdaEdgeEventType.ORIGIN_REQUEST,
},
],
},
});

expect(stack).toHaveResourceLike('AWS::CloudFront::Distribution', {
DistributionConfig: {
DefaultCacheBehavior: {
LambdaFunctionAssociations: [
{
EventType: 'origin-request',
LambdaFunctionARN: {
Ref: 'SingletonLambdasingletonforcloudfrontCurrentVersion0078406348a0962a52448a200cd0dbc0e22edb2a',
},
},
],
},
},
});
});
});

test('price class is included if provided', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ nodeunitShim({
isDefaultBehavior: true,
lambdaFunctionAssociations: [{
eventType: LambdaEdgeEventType.ORIGIN_REQUEST,
lambdaFunction: lambdaFunction.addVersion('1'),
lambdaFunction: lambdaFunction.currentVersion,
}],
},
],
Expand All @@ -458,7 +458,7 @@ nodeunitShim({
{
'EventType': 'origin-request',
'LambdaFunctionARN': {
'Ref': 'LambdaVersion1BB7548E1',
'Ref': 'LambdaCurrentVersionDF706F6A97fb843e9bd06fcd2bb15eeace80e13e',
},
},
],
Expand Down Expand Up @@ -492,7 +492,7 @@ nodeunitShim({
isDefaultBehavior: true,
lambdaFunctionAssociations: [{
eventType: LambdaEdgeEventType.ORIGIN_REQUEST,
lambdaFunction: lambdaFunction.addVersion('1'),
lambdaFunction: lambdaFunction.currentVersion,
}],
},
],
Expand Down Expand Up @@ -532,7 +532,7 @@ nodeunitShim({
isDefaultBehavior: true,
lambdaFunctionAssociations: [{
eventType: LambdaEdgeEventType.ORIGIN_REQUEST,
lambdaFunction: lambdaFunction.addVersion('1'),
lambdaFunction: lambdaFunction.currentVersion,
}],
},
],
Expand Down
9 changes: 0 additions & 9 deletions packages/@aws-cdk/aws-lambda/lib/function-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,15 +324,6 @@ export abstract class FunctionBase extends Resource implements IFunction {
});
}

/**
* Checks whether this function is compatible for Lambda@Edge.
*
* @internal
*/
public _checkEdgeCompatibility(): void {
return;
}

/**
* Returns the construct tree node that corresponds to the lambda function.
* For use internally for constructs, when the tree is set up in non-standard ways. Ex: SingletonFunction.
Expand Down
4 changes: 2 additions & 2 deletions packages/@aws-cdk/aws-lambda/lib/lambda-version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Construct, Fn, Lazy, RemovalPolicy } from '@aws-cdk/core';
import { Alias, AliasOptions } from './alias';
import { EventInvokeConfigOptions } from './event-invoke-config';
import { Function } from './function';
import { FunctionBase, IFunction, QualifiedFunctionBase } from './function-base';
import { IFunction, QualifiedFunctionBase } from './function-base';
import { CfnVersion } from './lambda.generated';
import { addAlias } from './util';

Expand Down Expand Up @@ -253,7 +253,7 @@ export class Version extends QualifiedFunctionBase implements IVersion {
return Lazy.stringValue({
produce: () => {
// Validate that the underlying function can be used for Lambda@Edge
if (this.lambda instanceof FunctionBase) {
if (this.lambda instanceof Function) {
this.lambda._checkEdgeCompatibility();
}

Expand Down
25 changes: 18 additions & 7 deletions packages/@aws-cdk/aws-lambda/lib/singleton-lambda.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import * as iam from '@aws-cdk/aws-iam';
import * as cdk from '@aws-cdk/core';
import { Function as LambdaFunction, FunctionProps } from './function';
import { FunctionBase, IFunction } from './function-base';
import { FunctionBase } from './function-base';
import { Version } from './lambda-version';
import { Permission } from './permission';

/**
Expand Down Expand Up @@ -45,7 +46,7 @@ export class SingletonFunction extends FunctionBase {
public readonly role?: iam.IRole;
public readonly permissionsNode: cdk.ConstructNode;
protected readonly canCreatePermissions: boolean;
private lambdaFunction: IFunction;
private lambdaFunction: LambdaFunction;

constructor(scope: cdk.Construct, id: string, props: SingletonFunctionProps) {
super(scope, id);
Expand All @@ -61,6 +62,18 @@ export class SingletonFunction extends FunctionBase {
this.canCreatePermissions = true; // Doesn't matter, addPermission is overriden anyway
}

/**
* Returns a `lambda.Version` which represents the current version of this
* singleton Lambda function. A new version will be created every time the
* function's configuration changes.
*
* You can specify options for this version using the `currentVersionOptions`
* prop when initializing the `lambda.SingletonFunction`.
*/
public get currentVersion(): Version {
return this.lambdaFunction.currentVersion;
}

public addPermission(name: string, permission: Permission) {
return this.lambdaFunction.addPermission(name, permission);
}
Expand All @@ -83,9 +96,7 @@ export class SingletonFunction extends FunctionBase {

/** @internal */
public _checkEdgeCompatibility() {
if (this.lambdaFunction instanceof FunctionBase) {
return this.lambdaFunction._checkEdgeCompatibility();
}
return this.lambdaFunction._checkEdgeCompatibility();
}

/**
Expand All @@ -96,12 +107,12 @@ export class SingletonFunction extends FunctionBase {
return this.lambdaFunction.node;
}

private ensureLambda(props: SingletonFunctionProps): IFunction {
private ensureLambda(props: SingletonFunctionProps): LambdaFunction {
const constructName = (props.lambdaPurpose || 'SingletonLambda') + slugify(props.uuid);
const existing = cdk.Stack.of(this).node.tryFindChild(constructName);
if (existing) {
// Just assume this is true
return existing as FunctionBase;
return existing as LambdaFunction;
}

return new LambdaFunction(cdk.Stack.of(this), constructName, props);
Expand Down
6 changes: 3 additions & 3 deletions packages/@aws-cdk/aws-lambda/test/test.lambda-version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,10 @@ export = {
handler: 'index.handler',
code: lambda.Code.fromInline('foo'),
});
const version = fn.addVersion('1');
const version = fn.currentVersion;

// THEN
test.deepEqual(stack.resolve(version.edgeArn), { Ref: 'FnVersion1C3F5F93D' });
test.deepEqual(stack.resolve(version.edgeArn), { Ref: 'FnCurrentVersion17A89ABB19ed45993ff69fd011ae9fd4ab6e2005' });

test.done();
},
Expand All @@ -179,7 +179,7 @@ export = {
handler: 'index.handler',
code: lambda.Code.fromInline('foo'),
});
const version = fn.addVersion('1');
const version = fn.currentVersion;

// WHEN
new lambda.Function(stack, 'OtherFn', {
Expand Down
24 changes: 24 additions & 0 deletions packages/@aws-cdk/aws-lambda/test/test.singleton-lambda.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,4 +160,28 @@ export = {

test.done();
},

'current version of a singleton function'(test: Test) {
// GIVEN
const stack = new cdk.Stack();
const singleton = new lambda.SingletonFunction(stack, 'Singleton', {
uuid: '84c0de93-353f-4217-9b0b-45b6c993251a',
code: new lambda.InlineCode('foo'),
runtime: lambda.Runtime.NODEJS_12_X,
handler: 'index.handler',
});

// WHEN
const version = singleton.currentVersion;
version.addAlias('foo');

// THEN
expect(stack).to(haveResource('AWS::Lambda::Version', {
FunctionName: {
Ref: 'SingletonLambda84c0de93353f42179b0b45b6c993251a840BCC38',
},
}));

test.done();
},
};

0 comments on commit e6db2a0

Please sign in to comment.