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

feat(cloudfront): define lambda@edge as resolvable resource #2861

Merged
merged 12 commits into from
Aug 21, 2019
Merged
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-cloudfront/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,4 @@
"node": ">= 8.10.0"
},
"stability": "experimental"
}
}
59 changes: 57 additions & 2 deletions packages/@aws-cdk/aws-cloudfront/test/test.basic.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { expect } from '@aws-cdk/assert';
import { expect, haveResourceLike } from '@aws-cdk/assert';
import * as lambda from '@aws-cdk/aws-lambda';
import s3 = require('@aws-cdk/aws-s3');
import cdk = require('@aws-cdk/core');
import { Test } from 'nodeunit';
import { CloudFrontWebDistribution, ViewerProtocolPolicy } from '../lib';
import { CloudFrontWebDistribution, LambdaEdgeEventType, ViewerProtocolPolicy } from '../lib';

// tslint:disable:object-literal-key-quotes

Expand Down Expand Up @@ -321,4 +322,58 @@ export = {
test.done();
},

'distribution with resolvable lambda-association'(test: Test) {
const stack = new cdk.Stack();
const sourceBucket = new s3.Bucket(stack, 'Bucket');

const lambdaFunction = new lambda.SingletonFunction(stack, 'Lambda', {
uuid: 'xxxx-xxxx-xxxx-xxxx',
code: lambda.Code.inline('foo'),
handler: 'index.handler',
runtime: lambda.Runtime.NODEJS_8_10
});

new CloudFrontWebDistribution(stack, 'AnAmazingWebsiteProbably', {
originConfigs: [
{
s3OriginSource: {
s3BucketSource: sourceBucket
},
behaviors: [
{
isDefaultBehavior: true,
lambdaFunctionAssociations: [{
eventType: LambdaEdgeEventType.ORIGIN_REQUEST,
lambdaFunction: lambdaFunction.latestVersion
}]
}
]
}
]
});

expect(stack).to(haveResourceLike('AWS::CloudFront::Distribution', {
"DistributionConfig": {
"DefaultCacheBehavior": {
"LambdaFunctionAssociations": [
{
"EventType": "origin-request",
"LambdaFunctionARN": {
"Fn::Join": [
"",
[
{ "Fn::GetAtt": [ "SingletonLambdaxxxxxxxxxxxxxxxx69D4268A", "Arn" ] },
":$LATEST"
]
]
}
}
],
},
}
}));

test.done();
},

};
44 changes: 43 additions & 1 deletion packages/@aws-cdk/aws-lambda/lib/lambda-version.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import cloudwatch = require('@aws-cdk/aws-cloudwatch');
import { Construct } from '@aws-cdk/core';
import { Construct, Fn } from '@aws-cdk/core';
import { Function } from './function';
import { IFunction, QualifiedFunctionBase } from './function-base';
import { CfnVersion } from './lambda.generated';

Expand Down Expand Up @@ -72,6 +73,30 @@ export interface VersionAttributes {
*/
export class Version extends QualifiedFunctionBase implements IVersion {

/**
* Construct a Version object from a Version ARN.
*
* @param scope The cdk scope creating this resource
KnisterPeter marked this conversation as resolved.
Show resolved Hide resolved
* @param id The cdk id of this resource
* @param versionArn The version ARN to create this version from
*/
public static fromVersionArn(scope: Construct, id: string, versionArn: string): IVersion {
const version = extractVersionFromArn(versionArn);
const lambda = Function.fromFunctionArn(scope, `${id}Function`, versionArn);

class Import extends QualifiedFunctionBase implements IVersion {
public readonly version = version;
public readonly lambda = lambda;
public readonly functionName = `${lambda.functionName}:${version}`;
public readonly functionArn = versionArn;
public readonly grantPrincipal = lambda.grantPrincipal;
public readonly role = lambda.role;

protected readonly canCreatePermissions = false;
}
return new Import(scope, id);
}

public static fromVersionAttributes(scope: Construct, id: string, attrs: VersionAttributes): IVersion {
class Import extends QualifiedFunctionBase implements IVersion {
public readonly version = attrs.version;
Expand Down Expand Up @@ -131,3 +156,20 @@ export class Version extends QualifiedFunctionBase implements IVersion {
});
}
}

/**
* Given an opaque (token) ARN, returns a CloudFormation expression that extracts the version
* name from the ARN.
*
* Version ARNs look like this:
*
* arn:aws:lambda:region:account-id:function:function-name:version
*
* ..which means that in order to extract the `version` component from the ARN, we can
* split the ARN using ":" and select the component in index 7.
*
* @returns `FnSelect(7, FnSplit(':', arn))`
*/
function extractVersionFromArn(arn: string) {
return Fn.select(7, Fn.split(':', arn));
}
33 changes: 33 additions & 0 deletions packages/@aws-cdk/aws-lambda/test/test.lambda-version.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { expect } from '@aws-cdk/assert';
import cdk = require('@aws-cdk/core');
import { Test } from 'nodeunit';
import lambda = require('../lib');

// tslint:disable:object-literal-key-quotes

export = {
'can import a Lambda version by ARN'(test: Test) {
// GIVEN
const stack = new cdk.Stack();

// WHEN
const version = lambda.Version.fromVersionArn(stack, 'Version', 'arn:aws:lambda:region:account-id:function:function-name:version');

new cdk.CfnOutput(stack, 'ARN', { value: version.functionArn });
new cdk.CfnOutput(stack, 'Name', { value: version.functionName });

// THEN
expect(stack).toMatch({
Outputs: {
ARN: {
Value: "arn:aws:lambda:region:account-id:function:function-name:version"
},
Name: {
Value: "function-name:version"
}
}
});

test.done();
},
};