From 193efd2de4d60fac62722dfa40dc33177014fcd9 Mon Sep 17 00:00:00 2001 From: Harold Hunt Date: Mon, 6 Mar 2023 12:08:33 -0500 Subject: [PATCH] fix(lambda-nodejs): Required auto prefix of `handler` with `index.` breaks custom non-`index` handler settings used by layers (#24406) Using `lambda-nodejs` makes it very easy to bundle functions with `esbuild`, but the code currently *always* prefixes the `handler` value with `index.`, which makes it impossible to use some lambda extensions together with this module as they require setting `handler` to specific values and the `index.` prefixing breaks the ability to set the handler to those values. This PR avoids adding the `index.` prefix if the specified `handler` value contains a `.` already. Closes #24403 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/aws-lambda-nodejs/README.md | 4 + .../aws-lambda-nodejs/lib/function.ts | 5 +- .../aws-lambda-nodejs/test/function.test.ts | 32 ++ .../test/integ-handlers/ts-web-handler.ts | 12 + .../test/integ-handlers/ts-web-run.sh | 11 + .../index.js | 2 + .../index.js.map | 7 + .../ts-web-run.sh | 11 + .../cdk-integ-lambda-nodejs.assets.json | 19 +- .../cdk-integ-lambda-nodejs.template.json | 130 +++++++ .../test/integ.function.js.snapshot/cdk.out | 2 +- .../integ.function.js.snapshot/integ.json | 2 +- .../integ.function.js.snapshot/manifest.json | 40 +- .../test/integ.function.js.snapshot/tree.json | 362 ++++++++++++++++-- .../aws-lambda-nodejs/test/integ.function.ts | 45 ++- 15 files changed, 643 insertions(+), 41 deletions(-) create mode 100644 packages/@aws-cdk/aws-lambda-nodejs/test/integ-handlers/ts-web-handler.ts create mode 100755 packages/@aws-cdk/aws-lambda-nodejs/test/integ-handlers/ts-web-run.sh create mode 100644 packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/asset.a33898f49e24c41ff9be236439c418d30e576c5f57763097162d9ec4245216ce/index.js create mode 100644 packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/asset.a33898f49e24c41ff9be236439c418d30e576c5f57763097162d9ec4245216ce/index.js.map create mode 100755 packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/asset.a33898f49e24c41ff9be236439c418d30e576c5f57763097162d9ec4245216ce/ts-web-run.sh diff --git a/packages/@aws-cdk/aws-lambda-nodejs/README.md b/packages/@aws-cdk/aws-lambda-nodejs/README.md index a895188db5206..35cb80d44b9a2 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/README.md +++ b/packages/@aws-cdk/aws-lambda-nodejs/README.md @@ -53,6 +53,10 @@ new nodejs.NodejsFunction(this, 'MyFunction', { }); ``` +The handler value will be automatically prefixed with the bundled output file name, `index.`, +unless the handler value contains a `.` character, in which case the handler value is used as-is to +allow for values needed by some Lambda extensions. + For monorepos, the reference architecture becomes: ```plaintext diff --git a/packages/@aws-cdk/aws-lambda-nodejs/lib/function.ts b/packages/@aws-cdk/aws-lambda-nodejs/lib/function.ts index 202be464b16da..0af7a63ce7d02 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/lib/function.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/lib/function.ts @@ -25,6 +25,9 @@ export interface NodejsFunctionProps extends lambda.FunctionOptions { /** * The name of the exported handler in the entry file. * + * The handler is prefixed with `index.` unless the specified handler value contains a `.`, + * in which case it is used as-is. + * * @default handler */ readonly handler?: string; @@ -108,7 +111,7 @@ export class NodejsFunction extends lambda.Function { depsLockFilePath, projectRoot, }), - handler: `index.${handler}`, + handler: handler.indexOf('.') !== -1 ? `${handler}` : `index.${handler}`, }); // Enable connection reuse for aws-sdk diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/function.test.ts b/packages/@aws-cdk/aws-lambda-nodejs/test/function.test.ts index f197bb34b60da..0bc5e25917cfa 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/test/function.test.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/function.test.ts @@ -45,6 +45,38 @@ test('NodejsFunction with .ts handler', () => { }); }); +test('NodejsFunction with overridden handler - no dots', () => { + // WHEN + new NodejsFunction(stack, 'handler1', { + handler: 'myHandler', + }); + + expect(Bundling.bundle).toHaveBeenCalledWith(expect.objectContaining({ + entry: expect.stringContaining('function.test.handler1.ts'), // Automatically finds .ts handler file + })); + + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { + Handler: 'index.myHandler', // automatic index. prefix + Runtime: 'nodejs14.x', + }); +}); + +test('NodejsFunction with overridden handler - with dots', () => { + // WHEN + new NodejsFunction(stack, 'handler1', { + handler: 'run.sh', + }); + + expect(Bundling.bundle).toHaveBeenCalledWith(expect.objectContaining({ + entry: expect.stringContaining('function.test.handler1.ts'), // Automatically finds .ts handler file + })); + + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { + Handler: 'run.sh', // No index. prefix + Runtime: 'nodejs14.x', + }); +}); + test('NodejsFunction with .js handler', () => { // WHEN new NodejsFunction(stack, 'handler2'); diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/integ-handlers/ts-web-handler.ts b/packages/@aws-cdk/aws-lambda-nodejs/test/integ-handlers/ts-web-handler.ts new file mode 100644 index 0000000000000..bb0b3187a74ed --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/integ-handlers/ts-web-handler.ts @@ -0,0 +1,12 @@ +import { Server } from 'http'; +import { mult } from './util'; + +// Create simple http server +const server = new Server((_req, res) => { + res.writeHead(200, { 'Content-Type': 'text/plain' }); + res.end(`${mult(3, 4)}`); + console.log(mult(3, 4)); // eslint-disable-line no-console +}); + +const port = parseInt(process.env.PORT || '3001', 10); +server.listen(port); diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/integ-handlers/ts-web-run.sh b/packages/@aws-cdk/aws-lambda-nodejs/test/integ-handlers/ts-web-run.sh new file mode 100755 index 0000000000000..def03845104ba --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/integ-handlers/ts-web-run.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +# For AWS Lambda Adapter +# https://github.com/awslabs/aws-lambda-web-adapter +export READINESS_CHECK_PATH="${READINESS_CHECK_PATH:-/health}" +export AWS_LAMBDA_EXEC_WRAPPER="${AWS_LAMBDA_EXEC_WRAPPER:-/opt/bootstrap}" +export RUST_LOG="${RUST_LOG:-info}" +export AWS_LWA_ENABLE_COMPRESSION="${AWS_LWA_ENABLE_COMPRESSION:-true}" +export PORT="${PORT:-3001}" + +exec node index.js diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/asset.a33898f49e24c41ff9be236439c418d30e576c5f57763097162d9ec4245216ce/index.js b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/asset.a33898f49e24c41ff9be236439c418d30e576c5f57763097162d9ec4245216ce/index.js new file mode 100644 index 0000000000000..70a6e7f17eb64 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/asset.a33898f49e24c41ff9be236439c418d30e576c5f57763097162d9ec4245216ce/index.js @@ -0,0 +1,2 @@ +"use strict";var t=require("http");function r(n,e){return n*e}var o=new t.Server((n,e)=>{e.writeHead(200,{"Content-Type":"text/plain"}),e.end(`${r(3,4)}`),console.log(r(3,4))}),m=parseInt(process.env.PORT||"3001",10);o.listen(m); +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vaW50ZWctaGFuZGxlcnMvdHMtd2ViLWhhbmRsZXIudHMiLCAiLi4vLi4vaW50ZWctaGFuZGxlcnMvdXRpbC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiaW1wb3J0IHsgU2VydmVyIH0gZnJvbSAnaHR0cCc7XG5pbXBvcnQgeyBtdWx0IH0gZnJvbSAnLi91dGlsJztcblxuLy8gQ3JlYXRlIHNpbXBsZSBodHRwIHNlcnZlclxuY29uc3Qgc2VydmVyID0gbmV3IFNlcnZlcigoX3JlcSwgcmVzKSA9PiB7XG4gIHJlcy53cml0ZUhlYWQoMjAwLCB7ICdDb250ZW50LVR5cGUnOiAndGV4dC9wbGFpbicgfSk7XG4gIHJlcy5lbmQoYCR7bXVsdCgzLCA0KX1gKTtcbiAgY29uc29sZS5sb2cobXVsdCgzLCA0KSk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tY29uc29sZVxufSk7XG5cbmNvbnN0IHBvcnQgPSBwYXJzZUludChwcm9jZXNzLmVudi5QT1JUIHx8ICczMDAxJywgMTApO1xuc2VydmVyLmxpc3Rlbihwb3J0KTtcbiIsICJleHBvcnQgZnVuY3Rpb24gYWRkKGE6IG51bWJlciwgYjogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIGEgKyBiO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbXVsdChhOiBudW1iZXIsIGI6IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiBhICogYjtcbn1cbiJdLAogICJtYXBwaW5ncyI6ICJhQUFBLElBQUFBLEVBQXVCLGdCQ0loQixTQUFTQyxFQUFLQyxFQUFXQyxFQUFtQixDQUNqRCxPQUFPRCxFQUFJQyxDQUNiLENERkEsSUFBTUMsRUFBUyxJQUFJLFNBQU8sQ0FBQ0MsRUFBTUMsSUFBUSxDQUN2Q0EsRUFBSSxVQUFVLElBQUssQ0FBRSxlQUFnQixZQUFhLENBQUMsRUFDbkRBLEVBQUksSUFBSSxHQUFHQyxFQUFLLEVBQUcsQ0FBQyxHQUFHLEVBQ3ZCLFFBQVEsSUFBSUEsRUFBSyxFQUFHLENBQUMsQ0FBQyxDQUN4QixDQUFDLEVBRUtDLEVBQU8sU0FBUyxRQUFRLElBQUksTUFBUSxPQUFRLEVBQUUsRUFDcERKLEVBQU8sT0FBT0ksQ0FBSSIsCiAgIm5hbWVzIjogWyJpbXBvcnRfaHR0cCIsICJtdWx0IiwgImEiLCAiYiIsICJzZXJ2ZXIiLCAiX3JlcSIsICJyZXMiLCAibXVsdCIsICJwb3J0Il0KfQo= diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/asset.a33898f49e24c41ff9be236439c418d30e576c5f57763097162d9ec4245216ce/index.js.map b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/asset.a33898f49e24c41ff9be236439c418d30e576c5f57763097162d9ec4245216ce/index.js.map new file mode 100644 index 0000000000000..1466fdadbee8c --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/asset.a33898f49e24c41ff9be236439c418d30e576c5f57763097162d9ec4245216ce/index.js.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "sources": ["../../integ-handlers/ts-web-handler.ts", "../../integ-handlers/util.ts"], + "sourcesContent": ["import { Server } from 'http';\nimport { mult } from './util';\n\n// Create simple http server\nconst server = new Server((_req, res) => {\n res.writeHead(200, { 'Content-Type': 'text/plain' });\n res.end(`${mult(3, 4)}`);\n console.log(mult(3, 4)); // eslint-disable-line no-console\n});\n\nconst port = parseInt(process.env.PORT || '3001', 10);\nserver.listen(port);\n", "export function add(a: number, b: number): number {\n return a + b;\n}\n\nexport function mult(a: number, b: number): number {\n return a * b;\n}\n"], + "mappings": "aAAA,IAAAA,EAAuB,gBCIhB,SAASC,EAAKC,EAAWC,EAAmB,CACjD,OAAOD,EAAIC,CACb,CDFA,IAAMC,EAAS,IAAI,SAAO,CAACC,EAAMC,IAAQ,CACvCA,EAAI,UAAU,IAAK,CAAE,eAAgB,YAAa,CAAC,EACnDA,EAAI,IAAI,GAAGC,EAAK,EAAG,CAAC,GAAG,EACvB,QAAQ,IAAIA,EAAK,EAAG,CAAC,CAAC,CACxB,CAAC,EAEKC,EAAO,SAAS,QAAQ,IAAI,MAAQ,OAAQ,EAAE,EACpDJ,EAAO,OAAOI,CAAI", + "names": ["import_http", "mult", "a", "b", "server", "_req", "res", "mult", "port"] +} diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/asset.a33898f49e24c41ff9be236439c418d30e576c5f57763097162d9ec4245216ce/ts-web-run.sh b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/asset.a33898f49e24c41ff9be236439c418d30e576c5f57763097162d9ec4245216ce/ts-web-run.sh new file mode 100755 index 0000000000000..def03845104ba --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/asset.a33898f49e24c41ff9be236439c418d30e576c5f57763097162d9ec4245216ce/ts-web-run.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +# For AWS Lambda Adapter +# https://github.com/awslabs/aws-lambda-web-adapter +export READINESS_CHECK_PATH="${READINESS_CHECK_PATH:-/health}" +export AWS_LAMBDA_EXEC_WRAPPER="${AWS_LAMBDA_EXEC_WRAPPER:-/opt/bootstrap}" +export RUST_LOG="${RUST_LOG:-info}" +export AWS_LWA_ENABLE_COMPRESSION="${AWS_LWA_ENABLE_COMPRESSION:-true}" +export PORT="${PORT:-3001}" + +exec node index.js diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/cdk-integ-lambda-nodejs.assets.json b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/cdk-integ-lambda-nodejs.assets.json index 5d852f260508e..9130aa4703d05 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/cdk-integ-lambda-nodejs.assets.json +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/cdk-integ-lambda-nodejs.assets.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "30.1.0", "files": { "5017e4b2e278e32bc634202d075b7ed8961b0d784f75450f7918a6a4f6f7df4a": { "source": { @@ -40,7 +40,20 @@ } } }, - "90cb9162c12b37a3990ecbde27ea037907171ccb64eeb60f046f098a9ae069cd": { + "a33898f49e24c41ff9be236439c418d30e576c5f57763097162d9ec4245216ce": { + "source": { + "path": "asset.a33898f49e24c41ff9be236439c418d30e576c5f57763097162d9ec4245216ce", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "a33898f49e24c41ff9be236439c418d30e576c5f57763097162d9ec4245216ce.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "76dea8b92881f37d669c02f0271a5aa08e02b115b3fbe57063dbb99c5acb1932": { "source": { "path": "cdk-integ-lambda-nodejs.template.json", "packaging": "file" @@ -48,7 +61,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "90cb9162c12b37a3990ecbde27ea037907171ccb64eeb60f046f098a9ae069cd.json", + "objectKey": "76dea8b92881f37d669c02f0271a5aa08e02b115b3fbe57063dbb99c5acb1932.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/cdk-integ-lambda-nodejs.template.json b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/cdk-integ-lambda-nodejs.template.json index f72cbf8df949d..eb052475e4bfd 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/cdk-integ-lambda-nodejs.template.json +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/cdk-integ-lambda-nodejs.template.json @@ -626,6 +626,136 @@ "VpcPrivateSubnet2DefaultRoute060D2087", "VpcPrivateSubnet2RouteTableAssociationA89CAD56" ] + }, + "tshandlercustomhandlernodotsServiceRole1775E15E": { + "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" + ] + ] + } + ] + } + }, + "tshandlercustomhandlernodots381F62EE": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "5017e4b2e278e32bc634202d075b7ed8961b0d784f75450f7918a6a4f6f7df4a.zip" + }, + "Role": { + "Fn::GetAtt": [ + "tshandlercustomhandlernodotsServiceRole1775E15E", + "Arn" + ] + }, + "Environment": { + "Variables": { + "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" + } + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "tshandlercustomhandlernodotsServiceRole1775E15E" + ] + }, + "tshandlercustomhandlerdotsServiceRole0575D3CB": { + "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" + ] + ] + } + ] + } + }, + "tshandlercustomhandlerdots2695F653": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "a33898f49e24c41ff9be236439c418d30e576c5f57763097162d9ec4245216ce.zip" + }, + "Role": { + "Fn::GetAtt": [ + "tshandlercustomhandlerdotsServiceRole0575D3CB", + "Arn" + ] + }, + "Environment": { + "Variables": { + "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" + } + }, + "Handler": "ts-web.run.sh", + "Layers": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:lambda:", + { + "Ref": "AWS::Region" + }, + ":753240598075:layer:LambdaAdapterLayerX86:13" + ] + ] + } + ], + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "tshandlercustomhandlerdotsServiceRole0575D3CB" + ] } }, "Parameters": { diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/cdk.out b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/cdk.out index 588d7b269d34f..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/integ.json b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/integ.json index e9f051c1b0d53..c76a9db715ffb 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "30.1.0", "testCases": { "integ.function": { "stacks": [ diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/manifest.json b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/manifest.json index d868041e21916..6ba270bef70dd 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "20.0.0", + "version": "30.1.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "cdk-integ-lambda-nodejs.assets": { "type": "cdk:asset-manifest", "properties": { @@ -23,7 +17,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/90cb9162c12b37a3990ecbde27ea037907171ccb64eeb60f046f098a9ae069cd.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/76dea8b92881f37d669c02f0271a5aa08e02b115b3fbe57063dbb99c5acb1932.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -219,6 +213,30 @@ "data": "tshandlervpcA502E26A" } ], + "/cdk-integ-lambda-nodejs/ts-handler-custom-handler-no-dots/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "tshandlercustomhandlernodotsServiceRole1775E15E" + } + ], + "/cdk-integ-lambda-nodejs/ts-handler-custom-handler-no-dots/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "tshandlercustomhandlernodots381F62EE" + } + ], + "/cdk-integ-lambda-nodejs/ts-handler-custom-handler-dots/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "tshandlercustomhandlerdotsServiceRole0575D3CB" + } + ], + "/cdk-integ-lambda-nodejs/ts-handler-custom-handler-dots/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "tshandlercustomhandlerdots2695F653" + } + ], "/cdk-integ-lambda-nodejs/BootstrapVersion": [ { "type": "aws:cdk:logicalId", @@ -233,6 +251,12 @@ ] }, "displayName": "cdk-integ-lambda-nodejs" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/tree.json b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/tree.json index 0c03f93bc762b..56f5b3601ae24 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, "cdk-integ-lambda-nodejs": { "id": "cdk-integ-lambda-nodejs", "path": "cdk-integ-lambda-nodejs", @@ -24,6 +16,14 @@ "id": "ServiceRole", "path": "cdk-integ-lambda-nodejs/ts-handler/ServiceRole", "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "cdk-integ-lambda-nodejs/ts-handler/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "cdk-integ-lambda-nodejs/ts-handler/ServiceRole/Resource", @@ -77,8 +77,8 @@ "id": "Stage", "path": "cdk-integ-lambda-nodejs/ts-handler/Code/Stage", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" } }, "AssetBucket": { @@ -141,6 +141,14 @@ "id": "ServiceRole", "path": "cdk-integ-lambda-nodejs/js-handler/ServiceRole", "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "cdk-integ-lambda-nodejs/js-handler/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "cdk-integ-lambda-nodejs/js-handler/ServiceRole/Resource", @@ -194,8 +202,8 @@ "id": "Stage", "path": "cdk-integ-lambda-nodejs/js-handler/Code/Stage", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" } }, "AssetBucket": { @@ -325,8 +333,8 @@ "id": "Acl", "path": "cdk-integ-lambda-nodejs/Vpc/PublicSubnet1/Acl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } }, "RouteTable": { @@ -492,8 +500,8 @@ "id": "Acl", "path": "cdk-integ-lambda-nodejs/Vpc/PublicSubnet2/Acl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } }, "RouteTable": { @@ -659,8 +667,8 @@ "id": "Acl", "path": "cdk-integ-lambda-nodejs/Vpc/PrivateSubnet1/Acl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } }, "RouteTable": { @@ -778,8 +786,8 @@ "id": "Acl", "path": "cdk-integ-lambda-nodejs/Vpc/PrivateSubnet2/Acl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } }, "RouteTable": { @@ -901,6 +909,14 @@ "id": "ServiceRole", "path": "cdk-integ-lambda-nodejs/ts-handler-vpc/ServiceRole", "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "cdk-integ-lambda-nodejs/ts-handler-vpc/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "cdk-integ-lambda-nodejs/ts-handler-vpc/ServiceRole/Resource", @@ -966,8 +982,8 @@ "id": "Stage", "path": "cdk-integ-lambda-nodejs/ts-handler-vpc/Code/Stage", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" } }, "AssetBucket": { @@ -1073,17 +1089,313 @@ "fqn": "@aws-cdk/aws-lambda-nodejs.NodejsFunction", "version": "0.0.0" } + }, + "ts-handler-custom-handler-no-dots": { + "id": "ts-handler-custom-handler-no-dots", + "path": "cdk-integ-lambda-nodejs/ts-handler-custom-handler-no-dots", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "cdk-integ-lambda-nodejs/ts-handler-custom-handler-no-dots/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "cdk-integ-lambda-nodejs/ts-handler-custom-handler-no-dots/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "cdk-integ-lambda-nodejs/ts-handler-custom-handler-no-dots/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "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" + ] + ] + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Code": { + "id": "Code", + "path": "cdk-integ-lambda-nodejs/ts-handler-custom-handler-no-dots/Code", + "children": { + "Stage": { + "id": "Stage", + "path": "cdk-integ-lambda-nodejs/ts-handler-custom-handler-no-dots/Code/Stage", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "AssetBucket": { + "id": "AssetBucket", + "path": "cdk-integ-lambda-nodejs/ts-handler-custom-handler-no-dots/Code/AssetBucket", + "constructInfo": { + "fqn": "@aws-cdk/aws-s3.BucketBase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-s3-assets.Asset", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "cdk-integ-lambda-nodejs/ts-handler-custom-handler-no-dots/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "s3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "s3Key": "5017e4b2e278e32bc634202d075b7ed8961b0d784f75450f7918a6a4f6f7df4a.zip" + }, + "role": { + "Fn::GetAtt": [ + "tshandlercustomhandlernodotsServiceRole1775E15E", + "Arn" + ] + }, + "environment": { + "variables": { + "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" + } + }, + "handler": "index.handler", + "runtime": "nodejs14.x" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda-nodejs.NodejsFunction", + "version": "0.0.0" + } + }, + "lambda-adapter-layer": { + "id": "lambda-adapter-layer", + "path": "cdk-integ-lambda-nodejs/lambda-adapter-layer", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "ts-handler-custom-handler-dots": { + "id": "ts-handler-custom-handler-dots", + "path": "cdk-integ-lambda-nodejs/ts-handler-custom-handler-dots", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "cdk-integ-lambda-nodejs/ts-handler-custom-handler-dots/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "cdk-integ-lambda-nodejs/ts-handler-custom-handler-dots/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "cdk-integ-lambda-nodejs/ts-handler-custom-handler-dots/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "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" + ] + ] + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Code": { + "id": "Code", + "path": "cdk-integ-lambda-nodejs/ts-handler-custom-handler-dots/Code", + "children": { + "Stage": { + "id": "Stage", + "path": "cdk-integ-lambda-nodejs/ts-handler-custom-handler-dots/Code/Stage", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "AssetBucket": { + "id": "AssetBucket", + "path": "cdk-integ-lambda-nodejs/ts-handler-custom-handler-dots/Code/AssetBucket", + "constructInfo": { + "fqn": "@aws-cdk/aws-s3.BucketBase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-s3-assets.Asset", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "cdk-integ-lambda-nodejs/ts-handler-custom-handler-dots/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "s3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "s3Key": "a33898f49e24c41ff9be236439c418d30e576c5f57763097162d9ec4245216ce.zip" + }, + "role": { + "Fn::GetAtt": [ + "tshandlercustomhandlerdotsServiceRole0575D3CB", + "Arn" + ] + }, + "environment": { + "variables": { + "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" + } + }, + "handler": "ts-web.run.sh", + "layers": [ + { + "Fn::Join": [ + "", + [ + "arn:aws:lambda:", + { + "Ref": "AWS::Region" + }, + ":753240598075:layer:LambdaAdapterLayerX86:13" + ] + ] + } + ], + "runtime": "nodejs14.x" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda-nodejs.NodejsFunction", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "cdk-integ-lambda-nodejs/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "cdk-integ-lambda-nodejs/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } } }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.264" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.ts b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.ts index 2dc25ef3679dc..ba6e676e1b7fc 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.function.ts @@ -1,7 +1,8 @@ +import * as os from 'os'; import * as path from 'path'; import { Vpc } from '@aws-cdk/aws-ec2'; -import { Runtime } from '@aws-cdk/aws-lambda'; -import { App, Stack, StackProps } from '@aws-cdk/core'; +import { LayerVersion, Runtime } from '@aws-cdk/aws-lambda'; +import { Aws, App, Stack, StackProps } from '@aws-cdk/core'; import { Construct } from 'constructs'; import * as lambda from '../lib'; @@ -29,6 +30,46 @@ class TestStack extends Stack { runtime: Runtime.NODEJS_14_X, vpc: new Vpc(this, 'Vpc'), }); + + new lambda.NodejsFunction(this, 'ts-handler-custom-handler-no-dots', { + entry: path.join(__dirname, 'integ-handlers/ts-handler.ts'), + runtime: Runtime.NODEJS_14_X, + bundling: { + minify: true, + sourceMap: true, + sourceMapMode: lambda.SourceMapMode.BOTH, + }, + handler: 'handler', + }); + + new lambda.NodejsFunction(this, 'ts-handler-custom-handler-dots', { + entry: path.join(__dirname, 'integ-handlers/ts-web-handler.ts'), + runtime: Runtime.NODEJS_14_X, + bundling: { + minify: true, + sourceMap: true, + sourceMapMode: lambda.SourceMapMode.BOTH, + commandHooks: { + beforeBundling: () => [], + beforeInstall: () => [], + afterBundling: (_inputDir, outputDir) => [ + `${os.platform() === 'win32' ? 'copy' : 'cp'} ${path.join( + __dirname, + 'integ-handlers', + 'ts-web-run.sh', + )} ${outputDir}`, + ], + }, + }, + handler: 'ts-web.run.sh', + layers: [ + LayerVersion.fromLayerVersionArn( + this, + 'lambda-adapter-layer', + `arn:aws:lambda:${Aws.REGION}:753240598075:layer:LambdaAdapterLayerX86:13`, + ), + ], + }); } }