Skip to content

Commit

Permalink
feat(lambda): add Code.fromAssetConstruct API for creating Code objec…
Browse files Browse the repository at this point in the history
…ts from Asset Constructs
  • Loading branch information
madeline-k committed Sep 7, 2022
1 parent 9f26e8a commit 217a199
Show file tree
Hide file tree
Showing 14 changed files with 721 additions and 3 deletions.
35 changes: 35 additions & 0 deletions packages/@aws-cdk/aws-lambda/lib/code.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ export abstract class Code {
return new AssetCode(path, options);
}

/**
* Loads the function code from an Asset construct.
*
* @param asset An Asset construct containing the Lambda code bundle or a .zip file
*/
public static fromAssetConstruct(asset: s3_assets.Asset): AssetConstructCode {
return new AssetConstructCode(asset);
}

/**
* Loads the function code from an asset created by a Docker build.
*
Expand Down Expand Up @@ -317,6 +326,32 @@ export interface ResourceBindOptions {
readonly resourceProperty?: string;
}

/**
* Lambda code from an Asset.
*/
export class AssetConstructCode extends Code {
public readonly isInline = false;
/**
* @param asset An Asset construct containing the Lambda code bundle or a .zip file.
*/
constructor(private readonly asset: s3_assets.Asset) {
super();
}

public bind(_scope: Construct): CodeConfig {
if (!this.asset.isZipArchive) {
throw new Error(`Asset must be a .zip file or a directory ${this.asset.assetPath}`);
}

return {
s3Location: {
bucketName: this.asset.s3BucketName,
objectKey: this.asset.s3ObjectKey,
},
};
}
}

/**
* Construction properties for {@link CfnParametersCode}.
*/
Expand Down
53 changes: 50 additions & 3 deletions packages/@aws-cdk/aws-lambda/test/code.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as path from 'path';
import { Match, Template } from '@aws-cdk/assertions';
import * as ecr from '@aws-cdk/aws-ecr';
import * as s3_assets from '@aws-cdk/aws-s3-assets';
import { testLegacyBehavior } from '@aws-cdk/cdk-build-tools';
import * as cdk from '@aws-cdk/core';
import * as cxapi from '@aws-cdk/cx-api';
Expand Down Expand Up @@ -101,6 +102,53 @@ describe('code', () => {
});
});

describe('lambda.Code.fromAssetConstruct', () => {
test('fails if a non-zip asset is used', () => {
// GIVEN
const stack = new cdk.Stack();
const fileAsset = new s3_assets.Asset(stack, 'CodeAsset', {
path: path.join(__dirname, 'my-lambda-handler', 'index.py'),
});
const code = lambda.Code.fromAssetConstruct(fileAsset);

// THEN
expect(() => defineFunction(code)).toThrow(/Asset must be a \.zip file or a directory/);
});

test('able to re-use one Asset object in multiple functions', () => {
// GIVEN
const app = new cdk.App({
context: {
[cxapi.NEW_STYLE_STACK_SYNTHESIS_CONTEXT]: false,
},
});
const stack = new cdk.Stack(app, 'MyStack');
const directoryAsset = new s3_assets.Asset(stack, 'CodeAsset', {
path: path.join(__dirname, 'my-lambda-handler'),
});
const code = lambda.Code.fromAssetConstruct(directoryAsset);

// WHEN
new lambda.Function(stack, 'Func1', {
handler: 'foom',
runtime: lambda.Runtime.NODEJS_14_X,
code,
});

new lambda.Function(stack, 'Func2', {
handler: 'foom',
runtime: lambda.Runtime.NODEJS_14_X,
code,
});

// THEN
const assembly = app.synth();
const synthesized = assembly.stacks[0];

expect(synthesized.assets.length).toEqual(1);
});
});

describe('lambda.Code.fromCfnParameters', () => {
test("automatically creates the Bucket and Key parameters when it's used in a Function", () => {
const stack = new cdk.Stack();
Expand Down Expand Up @@ -513,9 +561,8 @@ describe('code', () => {
});
});

function defineFunction(code: lambda.Code, runtime: lambda.Runtime = lambda.Runtime.NODEJS_14_X) {
const stack = new cdk.Stack();
return new lambda.Function(stack, 'Func', {
function defineFunction(code: lambda.Code, runtime: lambda.Runtime = lambda.Runtime.NODEJS_14_X, stack?: cdk.Stack) {
return new lambda.Function(stack ?? new cdk.Stack(), 'Func', {
handler: 'foom',
code,
runtime,
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"version":"21.0.0"}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"version": "21.0.0",
"testCases": {
"lambda-test-from-asset-construct/DefaultTest": {
"stacks": [
"lambda-test-from-asset-construct-stack"
],
"assertionStack": "lambda-test-from-asset-construct/DefaultTest/DeployAssert",
"assertionStackName": "lambdatestfromassetconstructDefaultTestDeployAssertF70D74A5"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"version": "21.0.0",
"files": {
"a37d3ef54c18e7738fe5dc008504591bd3b1f14c6a09ee91eac6d55f7ca5ba5f": {
"source": {
"path": "asset.a37d3ef54c18e7738fe5dc008504591bd3b1f14c6a09ee91eac6d55f7ca5ba5f.zip",
"packaging": "file"
},
"destinations": {
"current_account-current_region": {
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
"objectKey": "a37d3ef54c18e7738fe5dc008504591bd3b1f14c6a09ee91eac6d55f7ca5ba5f.zip",
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
}
}
},
"e363111b44d82e0bfe0be44fe813f2dd0883c834a1652d558de090ae83e22857": {
"source": {
"path": "lambda-test-assets-from-construct.template.json",
"packaging": "file"
},
"destinations": {
"current_account-current_region": {
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
"objectKey": "e363111b44d82e0bfe0be44fe813f2dd0883c834a1652d558de090ae83e22857.json",
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
}
}
}
},
"dockerImages": {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
{
"Resources": {
"MyLambdaServiceRole4539ECB6": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
}
}
],
"Version": "2012-10-17"
},
"ManagedPolicyArns": [
{
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
]
]
}
]
}
},
"MyLambdaCCE802FB": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Code": {
"S3Bucket": {
"Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}"
},
"S3Key": "a37d3ef54c18e7738fe5dc008504591bd3b1f14c6a09ee91eac6d55f7ca5ba5f.zip"
},
"Role": {
"Fn::GetAtt": [
"MyLambdaServiceRole4539ECB6",
"Arn"
]
},
"Handler": "index.main",
"Runtime": "python3.9"
},
"DependsOn": [
"MyLambdaServiceRole4539ECB6"
]
}
},
"Parameters": {
"BootstrapVersion": {
"Type": "AWS::SSM::Parameter::Value<String>",
"Default": "/cdk-bootstrap/hnb659fds/version",
"Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"
}
},
"Rules": {
"CheckBootstrapVersion": {
"Assertions": [
{
"Assert": {
"Fn::Not": [
{
"Fn::Contains": [
[
"1",
"2",
"3",
"4",
"5"
],
{
"Ref": "BootstrapVersion"
}
]
}
]
},
"AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI."
}
]
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"version": "21.0.0",
"files": {
"a37d3ef54c18e7738fe5dc008504591bd3b1f14c6a09ee91eac6d55f7ca5ba5f": {
"source": {
"path": "asset.a37d3ef54c18e7738fe5dc008504591bd3b1f14c6a09ee91eac6d55f7ca5ba5f.zip",
"packaging": "file"
},
"destinations": {
"current_account-current_region": {
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
"objectKey": "a37d3ef54c18e7738fe5dc008504591bd3b1f14c6a09ee91eac6d55f7ca5ba5f.zip",
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
}
}
},
"e363111b44d82e0bfe0be44fe813f2dd0883c834a1652d558de090ae83e22857": {
"source": {
"path": "lambda-test-from-asset-construct-stack.template.json",
"packaging": "file"
},
"destinations": {
"current_account-current_region": {
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
"objectKey": "e363111b44d82e0bfe0be44fe813f2dd0883c834a1652d558de090ae83e22857.json",
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
}
}
}
},
"dockerImages": {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
{
"Resources": {
"MyLambdaServiceRole4539ECB6": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
}
}
],
"Version": "2012-10-17"
},
"ManagedPolicyArns": [
{
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
]
]
}
]
}
},
"MyLambdaCCE802FB": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Code": {
"S3Bucket": {
"Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}"
},
"S3Key": "a37d3ef54c18e7738fe5dc008504591bd3b1f14c6a09ee91eac6d55f7ca5ba5f.zip"
},
"Role": {
"Fn::GetAtt": [
"MyLambdaServiceRole4539ECB6",
"Arn"
]
},
"Handler": "index.main",
"Runtime": "python3.9"
},
"DependsOn": [
"MyLambdaServiceRole4539ECB6"
]
}
},
"Parameters": {
"BootstrapVersion": {
"Type": "AWS::SSM::Parameter::Value<String>",
"Default": "/cdk-bootstrap/hnb659fds/version",
"Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"
}
},
"Rules": {
"CheckBootstrapVersion": {
"Assertions": [
{
"Assert": {
"Fn::Not": [
{
"Fn::Contains": [
[
"1",
"2",
"3",
"4",
"5"
],
{
"Ref": "BootstrapVersion"
}
]
}
]
},
"AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI."
}
]
}
}
}
Loading

0 comments on commit 217a199

Please sign in to comment.