aws / aws-sam-cli

CLI tool to build, test, debug, and deploy Serverless applications using AWS SAM
https://aws.amazon.com/serverless/sam/
Apache License 2.0
6.52k stars 1.17k forks source link

Correct setup for multiple Lambda Functions using TypeScript/esbuild? #4357

Open Rabadash8820 opened 2 years ago

Rabadash8820 commented 2 years ago

This might be a bug report, but I think mainly its just a question: how can you set up a SAM CLI project for multiple Lambda Functions when using TypeScript/esbuild?

My Attempt

Folder structure: ```txt src/ LambdaEntrypoints/ Function1.ts Function2.ts SharedLib1/ index.ts SharedLib2/ index.ts test/ SharedLib1/ SharedLib2/ package.json tsconfig.json samconfig.toml template.yaml ```
tsconfig.json ```jsonc { "extends": "@tsconfig/node16/tsconfig.json", "include": [ "src/**/*.ts", "test/**/*.ts", ], "compilerOptions": { "outDir": "dist/", "incremental": true, "declaration": true, "declarationMap": true, "sourceMap": true, "composite": true, "noImplicitAny": true, "strictNullChecks": true, "strictFunctionTypes": true, "strictBindCallApply": true, "strictPropertyInitialization": true, "noImplicitThis": true, "alwaysStrict": true, "esModuleInterop": true, } } ```
template.yaml ```yml AWSTemplateFormatVersion: "2010-09-09" Transform: AWS::Serverless-2016-10-31 Globals: Function: Architectures: [arm64] Runtime: nodejs16.x CodeUri: . Timeout: 3 Tracing: Active Resources: Function1: Type: AWS::Serverless::Function Metadata: BuildMethod: esbuild BuildProperties: UseNpmCi: true Minify: true Sourcemap: true EntryPoints: [ src/LambdaEntrypoints/Function1.ts ] Properties: # FunctionName: Auto-generate Handler: Function1.handleEvent Function2: Type: AWS::Serverless::Function Metadata: BuildMethod: esbuild BuildProperties: UseNpmCi: true Minify: true Sourcemap: true EntryPoints: [ src/LambdaEntrypoints/Function2.ts ] Properties: # FunctionName: Auto-generate Handler: Function2.handleEvent ```
`src/LambdaEntrypoints/Function1.ts` (or `Function2.ts`) ```ts import { APIGatewayProxyEventV2, APIGatewayProxyResultV2 } from "aws-lambda"; // Other imports export async function handleEvent(event: APIGatewayProxyEventV2): Promise { // Do stuff } ```

Expected result

Running sam build Function1 && sam local invoke Function1 (or equivalent for Function2) would successfully build and run my Lambda Function locally.

Actual result

Build succeeds, generating this `.aws-sam` folder contents ```txt build/ Function1/ Function1.js Function1.js.map Function2/ Function2.js Function2.js.map template.yaml build.toml ```
But `sam local invoke Function1` fails with this output ```log Invoking Function1.handleEvent (nodejs16.x) Skip pulling image and use local one: public.ecr.aws/sam/emulation-nodejs16.x:rapid-1.61.0-arm64. Mounting /workspaces/Farmageddon/backend2/.aws-sam/build/Function1as /var/task:ro,delegated inside runtime container START RequestId: bcc02ecf-4892-4702-ab63-c22fe7698b25 Version: $LATEST 2022-10-29T05:42:00.806Z undefined ERROR Uncaught Exception {"errorType":"Runtime.ImportModuleError","errorMessage":"Error: Cannot find module 'Function1'\nRequire stack:\n- /var/runtime/index.mjs","stack":["Runtime.ImportModuleError: Error: Cannot find module 'Function1'","Require stack:","- /var/runtime/index.mjs"," at _loadUserApp (file:///var/runtime/index.mjs:1000:17)"," at async Object.UserFunction.js.module.exports.load (file:///var/runtime/index.mjs:1035:21)"," at async start (file:///var/runtime/index.mjs:1200:23)"," at async file:///var/runtime/index.mjs:1206:1"]} 29 Oct 2022 05:42:01,072 [ERROR] (rapid) Init failed error=Runtime exited with error: exit status 129 InvokeID= 2022-10-29T05:42:03.102Z undefined ERROR Uncaught Exception {"errorType":"Runtime.ImportModuleError","errorMessage":"Error: Cannot find module 'Function1'\nRequire stack:\n- /var/runtime/index.mjs","stack":["Runtime.ImportModuleError: Error: Cannot find module 'Function1'","Require stack:","- /var/runtime/index.mjs"," at _loadUserApp (file:///var/runtime/index.mjs:1000:17)"," at async Object.UserFunction.js.module.exports.load (file:///var/runtime/index.mjs:1035:21)"," at async start (file:///var/runtime/index.mjs:1200:23)"," at async file:///var/runtime/index.mjs:1206:1"]} END RequestId: ebb45e29-693a-46e1-ac8b-af1f3008cb4a REPORT RequestId: ebb45e29-693a-46e1-ac8b-af1f3008cb4a Init Duration: 2.94 ms Duration: 4545.67 ms Billed Duration: 4546 ms Memory Size: 128 MB Max Memory Used: 128 MB {"errorType":"Runtime.ImportModuleError","errorMessage":"Error: Cannot find module 'Function1'\nRequire stack:\n- /var/runtime/index.mjs","trace":["Runtime.ImportModuleError: Error: Cannot find module 'Function1'","Require stack:","- /var/runtime/index.mjs"," at _loadUserApp (file:///var/runtime/index.mjs:1000:17)"," at async Object.UserFunction.js.module.exports.load (file:///var/runtime/index.mjs:1035:21)"," at async start (file:///var/runtime/index.mjs:1200:23)"," at async file:///var/runtime/index.mjs:1206:1"]}vscode ```
mndeveci commented 2 years ago

Hi @Rabadash8820 thanks for reporting this issue. We've tried to re-produce it with following files, but sam local invoke worked without any issues. Can you help us to identify what is the difference between your setup and ours (an example GH repo could be helpful to re-produce the issue too)?

Folder structure ``` . ├── package.json ├── src │   ├── LambdaEntrypoints │   │   ├── Function1.ts │   │   └── Function2.ts │   └── SharedLib1 │   └── index.ts └── template.yaml ```
template.yaml ``` AWSTemplateFormatVersion: "2010-09-09" Transform: AWS::Serverless-2016-10-31 Globals: Function: Architectures: [arm64] Runtime: nodejs16.x CodeUri: . Timeout: 3 Tracing: Active Resources: Function1: Type: AWS::Serverless::Function Metadata: BuildMethod: esbuild BuildProperties: UseNpmCi: true Minify: true Sourcemap: true EntryPoints: [ src/LambdaEntrypoints/Function1.ts ] Properties: # FunctionName: Auto-generate Handler: Function1.handleEvent Function2: Type: AWS::Serverless::Function Metadata: BuildMethod: esbuild BuildProperties: UseNpmCi: true Minify: true Sourcemap: true EntryPoints: [ src/LambdaEntrypoints/Function2.ts ] Properties: # FunctionName: Auto-generate Handler: Function2.handleEvent ```
src/LambdaEntrypoints/Function1.ts ``` import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda'; import { getSomeValues } from '../SharedLib1'; export const handleEvent = async (event: APIGatewayProxyEvent): Promise => { let response: APIGatewayProxyResult; try { response = { statusCode: 200, body: JSON.stringify({ message: `Using shared lib values ${getSomeValues()}`, }), }; } catch (err) { console.log(err); response = { statusCode: 500, body: JSON.stringify({ message: 'some error happened', }), }; } return response; }; ```
Output of build folder ``` .aws-sam ├── build │   ├── Function1 │   │   ├── Function1.js │   │   └── Function1.js.map │   ├── Function2 │   │   ├── Function2.js │   │   └── Function2.js.map │   └── template.yaml └── build.toml ```
Output of sam local command ``` sam local invoke Function1 Invoking Function1.handleEvent (nodejs16.x) Skip pulling image and use local one: public.ecr.aws/sam/emulation-nodejs16.x:rapid-1.61.0-arm64. Mounting /Users/deveci/Downloads/test-app-esbuild/.aws-sam/build/Function1 as /var/task:ro,delegated inside runtime container START RequestId: d3e9c91b-9e8b-440b-9dd5-5ec0cb6fb164 Version: $LATEST END RequestId: d3e9c91b-9e8b-440b-9dd5-5ec0cb6fb164 REPORT RequestId: d3e9c91b-9e8b-440b-9dd5-5ec0cb6fb164 Init Duration: 3.29 ms Duration: 1929.41 ms Billed Duration: 1930 ms Memory Size: 128 MB Max Memory Used: 128 MB {"statusCode":200,"body":"{\"message\":\"Using shared lib values 8\"}"}% ```
Rabadash8820 commented 2 years ago

@mndeveci Thanks for getting back to me. I made that example by slashing my current repo down to a minimal project, but its possible that I left something lingering that's causing our setups to differ. This is a private repo so I can't provide a link, but I could share a zip of the repo through another channel.

hawflau commented 2 years ago

Hey @Rabadash8820, could you post a message on our Slack channel referencing this issue? I'll DM you to ask for the zip file. Thanks!

sultanimbayev commented 1 year ago

I'm having the same issue.

Steps to reproduce:

  1. run sam init
  2. choose the following setup:
    • Which template source would you like to use? 1 - AWS Quick Start Templates
    • Choose an AWS Quick Start application template 1 - Hello World Example
    • Use the most popular runtime and package type? N
    • Which runtime would you like to use? 11 - nodejs18.x
    • What package type would you like to use? 1 - Zip
    • Select your starter template 2 - Hello World Example TypeScript
    • Would you like to enable X-Ray tracing on the function(s) in your application? N
    • Would you like to enable monitoring using CloudWatch Application Insights? N
    • Project name [sam-app]: sam-app
  3. change directory to the app cd sam-app
  4. run sam build
  5. run sam local invoke HelloWorldFunction --event events/event.json

Observed result:

START RequestId: becf4508-21f7-4b85-b134-4d62e0cf0309 Version: $LATEST
2023-08-30T04:01:25.596Z        undefined       ERROR   Uncaught Exception      {"errorType":"Runtime.ImportModuleError","errorMessage":"Error: Cannot find module 'app'\nRequire stack:\n- /var/runtime/index.mjs","stack":["Runtime.ImportModuleError: Error: Cannot find module 'app'","Require stack:","- /var/runtime/index.mjs","    at _loadUserApp (file:///var/runtime/index.mjs:1061:17)","    at async UserFunction.js.module.exports.load (file:///var/runtime/index.mjs:1093:21)","    at async start (file:///var/runtime/index.mjs:1256:23)","    at async file:///var/runtime/index.mjs:1262:1"]} 
30 Aug 2023 04:01:25,608 [ERROR] (rapid) Init failed error=Runtime exited with error: exit status 129 InvokeID=
2023-08-30T04:01:25.724Z        undefined       ERROR   Uncaught Exception      {"errorType":"Runtime.ImportModuleError","errorMessage":"Error: Cannot find module 'app'\nRequire stack:\n- /var/runtime/index.mjs","stack":["Runtime.ImportModuleError: Error: Cannot find module 'app'","Require stack:","- /var/runtime/index.mjs","    at _loadUserApp (file:///var/runtime/index.mjs:1061:17)","    at async UserFunction.js.module.exports.load (file:///var/runtime/index.mjs:1093:21)","    at async start (file:///var/runtime/index.mjs:1256:23)","    at async file:///var/runtime/index.mjs:1262:1"]} 
END RequestId: 8e94412c-d8cf-4628-baa5-e777603f3e32
REPORT RequestId: 8e94412c-d8cf-4628-baa5-e777603f3e32  Init Duration: 0.66 ms  Duration: 287.99 mBilled Duration: 288 ms  Memory Size: 128 MB     Max Memory Used: 128 MB
{"errorType": "Runtime.ImportModuleError", "errorMessage": "Error: Cannot find module 'app'\nRequire stack:\n- /var/runtime/index.mjs", "trace": ["Runtime.ImportModuleError: Error: Cannot find module 'app'", "Require stack:", "- /var/runtime/index.mjs", "    at _loadUserApp (file:///var/runtime/index.mjs:1061:17)", "    at async UserFunction.js.module.exports.load (file:///var/runtime/index.mjs:1093:21)", "    at async start (file:///var/runtime/index.mjs:1256:23)", "    at async file:///var/runtime/index.mjs:1262:1"]}

Expected result:

START RequestId: 64bf7e54-5509-4762-a97c-3d740498d3df Version: $LATEST
END RequestId: 64bf7e54-5509-4762-a97c-3d740498d3df
REPORT RequestId: 64bf7e54-5509-4762-a97c-3d740498d3df  Init Duration: 1.09 ms  Duration: 608.42 ms       Billed Duration: 609 ms Memory Size: 128 MB     Max Memory Used: 128 MB
{"statusCode": 200, "body": "{\"message\": \"hello world\"}"}

Additional environment details

  1. OS: Windows 11 Pro 22621.2134
  2. If using SAM CLI, sam --version: SAM CLI, version 1.96.0
  3. AWS region: eu-north-1 (Stockholm)
When running `sam local invoke HelloWorldFunction --event events/event.json --debug` ``` 2023-08-30 10:20:12,724 | Config file location: C:\Users\Sultan_Imbayev\source\repos\allcity\samconfig.toml 2023-08-30 10:20:12,728 | Loading configuration values from [default.['local', 'invoke'].parameters] (env.command_name.section) in config file at 'C:\Users\Sultan_Imbayev\source\repos\allcity\samconfig.toml'... 2023-08-30 10:20:12,729 | Configuration values successfully loaded. 2023-08-30 10:20:12,730 | Configuration values are: {'stack_name': 'allcity'} 2023-08-30 10:20:12,737 | Using SAM Template at C:\Users\Sultan_Imbayev\source\repos\allcity\.aws-sam\build\template.yaml 2023-08-30 10:20:12,770 | Using config file: samconfig.toml, config environment: default 2023-08-30 10:20:12,771 | Expand command line arguments to: 2023-08-30 10:20:12,772 | --template_file=C:\Users\Sultan_Imbayev\source\repos\allcity\.aws-sam\build\template.yaml --event=events/event.json --function_logical_id=HelloWorldFunction --no_event --layer_cache_basedir=C:\Users\Sultan_Imbayev\AppData\Roaming\AWS SAM\layers-pkg --container_host=localhost --container_host_interface=127.0.0.1 2023-08-30 10:20:12,774 | local invoke command is called 2023-08-30 10:20:12,783 | No Parameters detected in the template 2023-08-30 10:20:12,817 | Sam customer defined id is more priority than other IDs. Customer defined id for resource HelloWorldFunction is HelloWorldFunction 2023-08-30 10:20:12,819 | There is no customer defined id or cdk path defined for resource ApplicationResourceGroup, so we will use the resource logical id as the resource id 2023-08-30 10:20:12,822 | There is no customer defined id or cdk path defined for resource ApplicationInsightsMonitoring, so we will use the resource logical id as the resource id 2023-08-30 10:20:12,825 | There is no customer defined id or cdk path defined for resource ServerlessRestApi, so we will use the resource logical id as the resource id 2023-08-30 10:20:12,827 | 0 stacks found in the template 2023-08-30 10:20:12,829 | No Parameters detected in the template 2023-08-30 10:20:12,848 | Sam customer defined id is more priority than other IDs. Customer defined id for resource HelloWorldFunction is HelloWorldFunction 2023-08-30 10:20:12,849 | There is no customer defined id or cdk path defined for resource ApplicationResourceGroup, so we will use the resource logical id as the resource id 2023-08-30 10:20:12,851 | There is no customer defined id or cdk path defined for resource ApplicationInsightsMonitoring, so we will use the resource logical id as the resource id 2023-08-30 10:20:12,853 | There is no customer defined id or cdk path defined for resource ServerlessRestApi, so we will use the resource logical id as the resource id 2023-08-30 10:20:12,855 | 4 resources found in the stack 2023-08-30 10:20:12,857 | Found Serverless function with name='HelloWorldFunction' and CodeUri='HelloWorldFunction' 2023-08-30 10:20:12,858 | --base-dir is not presented, adjusting uri HelloWorldFunction relative to C:\Users\Sultan_Imbayev\source\repos\allcity\.aws-sam\build\template.yaml 2023-08-30 10:20:12,867 | Found one Lambda function with name 'HelloWorldFunction' 2023-08-30 10:20:12,869 | Invoking app.lambdaHandler (nodejs18.x) 2023-08-30 10:20:12,870 | Loading AWS credentials from session with profile 'None' 2023-08-30 10:20:13,810 | Resolving code path. Cwd=C:\Users\Sultan_Imbayev\source\repos\allcity\.aws-sam\build, CodeUri=C:\Users\Sultan_Imbayev\source\repos\allcity\.aws-sam\build\HelloWorldFunction 2023-08-30 10:20:13,812 | Resolved absolute path to code is C:\Users\Sultan_Imbayev\source\repos\allcity\.aws-sam\build\HelloWorldFunction 2023-08-30 10:20:13,815 | Code C:\Users\Sultan_Imbayev\source\repos\allcity\.aws-sam\build\HelloWorldFunction is not a zip/jar file 2023-08-30 10:20:18,078 | Local image is up-to-date 2023-08-30 10:20:18,099 | Using local image: public.ecr.aws/lambda/nodejs:18-rapid-x86_64. 2023-08-30 10:20:18,103 | Mounting C:\Users\Sultan_Imbayev\source\repos\allcity\.aws-sam\build\HelloWorldFunction as /var/task:ro,delegated, inside runtime container 2023-08-30 10:20:18,961 | Starting a timer for 3 seconds for function 'HelloWorldFunction' START RequestId: bd632657-e9cc-4730-a347-9c77ab7ce567 Version: $LATEST 2023-08-30T04:20:20.143Z undefined ERROR Uncaught Exception {"errorType":"Runtime.ImportModuleError","errorMessage":"Error: Cannot find module 'app'\nRequire stack:\n- /var/runtime/index.mjs","stack":["Runtime.ImportModuleError: Error: Cannot find module 'app'","Require stack:","- /var/runtime/index.mjs"," at _loadUserApp (file:///var/runtime/index.mjs:1061:17)"," at async UserFunction.js.module.exports.load (file:///var/runtime/index.mjs:1093:21)"," at async start (file:///var/runtime/index.mjs:1256:23)"," at async file:///var/runtime/index.mjs:1262:1"]} 30 Aug 2023 04:20:20,154 [ERROR] (rapid) Init failed error=Runtime exited with error: exit status 129 InvokeID= 2023-08-30T04:20:20.258Z undefined ERROR Uncaught Exception {"errorType":"Runtime.ImportModuleError","errorMessage":"Error: Cannot find module 'app'\nRequire stack:\n- /var/runtime/index.mjs","stack":["Runtime.ImportModuleError: Error: Cannot find module 'app'","Require stack:","- /var/runtime/index.mjs"," at _loadUserApp (file:///var/runtime/index.mjs:1061:17)"," at async UserFunction.js.module.exports.load (file:///var/runtime/index.mjs:1093:21)"," at async start (file:///var/runtime/index.mjs:1256:23)"," at async file:///var/runtime/index.mjs:1262:1"]} END RequestId: 01b3c1a4-b863-4abb-9e16-52763cdee22e REPORT RequestId: 01b3c1a4-b863-4abb-9e16-52763cdee22e Init Duration: 0.09 ms Duration: 295.26 mBilled Duration: 296 ms Memory Size: 128 MB Max Memory Used: 128 MB {"errorType": "Runtime.ImportModuleError", "errorMessage": "Error: Cannot find module 'app'\nRequire stack:\n- /var/runtime/index.mjs", "trace": ["Runtime.ImportModuleError: Error: Cannot find module 'app'", "Require stack:", "- /var/runtime/index.mjs", " at _loadUserApp (file:///var/runtime/index.mjs:1061:17)", " at async UserFunction.js.module.exports.load (file:///var/runtime/index.mjs:1093:21)", " at async start (file:///var/runtime/index.mjs:1256:23)", " at async file:///var/runtime/index.mjs:1262:1"]}2023-08-30 10:20:21,627 | Cleaning all decompressed code dirs 2023-08-30 10:20:21,628 | Telemetry endpoint configured to be https://aws-serverless-tools-telemetry.us-west-2.amazonaws.com/metrics 2023-08-30 10:20:21,915 | Telemetry endpoint configured to be https://aws-serverless-tools-telemetry.us-west-2.amazonaws.com/metrics 2023-08-30 10:20:21,917 | Sending Telemetry: {'metrics': [{'commandRun': {'requestId': 'eb38407e-a369-42ae-8eee-4331ed83c8c7', 'installationId': '67bd8577-8793-4f4e-aede-a466558a3c18', 'sessionId': 'a81febc8-561a-425f-8b8a-1540dd4ec8c8', 'executionEnvironment': 'CLI', 'ci': False, 'pyversion': '3.8.8', 'samcliVersion': '1.96.0', 'awsProfileProvided': False, 'debugFlagProvided': True, 'region': '', 'commandName': 'sam local invoke', 'metricSpecificAttributes': {'projectType': 'CFN', 'gitOrigin': 'ee63885e6962db2a5d6af26170ec1edfc335eec4e787218fd9dfc6b3cbcd72a5', 'projectName': '5e662bccbf0227c69d4511aa1a7cc227a4d34a72cdffb1c7dc5a0d65df5706ee', 'initialCommit': '98db6c1a798861d77c6f678da5a542d8aeb40796b52c2203f43305405a76b66b'}, 'duration': 8858, 'exitReason': 'success', 'exitCode': 0}}]} 2023-08-30 10:20:21,917 | Unable to find Click Context for getting session_id. 2023-08-30 10:20:21,926 | Sending Telemetry: {'metrics': [{'events': {'requestId': '6f34eb47-b07a-419f-81d2-9f3dc94890ab', 'installationId': '67bd8577-8793-4f4e-aede-a466558a3c18', 'sessionId': 'a81febc8-561a-425f-8b8a-1540dd4ec8c8', 'executionEnvironment': 'CLI', 'ci': False, 'pyversion': '3.8.8', 'samcliVersion': '1.96.0', 'commandName': 'sam local invoke', 'metricSpecificAttributes': {'events': [{'event_name': 'SamConfigFileExtension', 'event_value': '.toml', 'thread_id': 'ee67df4f72a244b1b823b7fe6be43100', 'time_stamp': '2023-08-30 04:20:12.723', 'exception_name': None}]}}}]} 2023-08-30 10:20:22,810 | HTTPSConnectionPool(host='aws-serverless-tools-telemetry.us-west-2.amazonaws.com', port=443): Read timed out. (read timeout=0.1) 2023-08-30 10:20:22,888 | HTTPSConnectionPool(host='aws-serverless-tools-telemetry.us-west-2.amazonaws.com', port=443): Read timed out. (read timeout=0.1) 2023-08-30 10:20:22,891 | Telemetry endpoint configured to be https://aws-serverless-tools-telemetry.us-west-2.amazonaws.com/metrics 2023-08-30 10:20:22,893 | Sending Telemetry: {'metrics': [{'runtimeMetric': {'requestId': '270691f5-d554-4502-8882-9cb083e166fe', 'installationId': '67bd8577-8793-4f4e-aede-a466558a3c18', 'sessionId': 'a81febc8-561a-425f-8b8a-1540dd4ec8c8', 'executionEnvironment': 'CLI', 'ci': False, 'pyversion': '3.8.8', 'samcliVersion': '1.96.0', 'runtimes': ['nodejs18.x']}}]} 2023-08-30 10:20:23,745 | HTTPSConnectionPool(host='aws-serverless-tools-telemetry.us-west-2.amazonaws.com', port=443): Read timed out. (read timeout=0.1) ```
ceberttylertech commented 11 months ago

I do agree with this post here. There doesn't seem to be an example of how to structure a SAM application with multiple lambdas and maybe some shared dependencies (e.g. contracts for a crud application) between Lambdas. I think having an example of this would go a long way to benefit the community.