From 8eb29dae49a57b79eafe5ce5a3c840c95e12e199 Mon Sep 17 00:00:00 2001 From: Garrett Beatty Date: Fri, 7 Feb 2025 13:03:03 -0500 Subject: [PATCH 1/9] start updating readme --- .../src/Amazon.Lambda.TestTool/README.md | 250 ++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/README.md diff --git a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/README.md b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/README.md new file mode 100644 index 000000000..ba2c096ad --- /dev/null +++ b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/README.md @@ -0,0 +1,250 @@ +# AWS Lambda Test Tool + +## Overview +The AWS Lambda Test Tool provides local testing capabilities for .NET Lambda functions with support for both Lambda emulation and API Gateway emulation. This tool allows developers to test their Lambda functions locally in three different modes: + +1. Lambda Emulator Mode +2. API Gateway Emulator Mode +3. Combined Mode (both emulators) + +# AWS Lambda Test Tool + +# AWS Lambda Test Tool + +- [Overview](#overview) +- [Getting help](#getting-help) +- [Installing](#installing) +- [Running the Test Tool](#running-the-test-tool) + - [Lambda Emulator Mode](#lambda-emulator-mode) + - [API Gateway Emulator Mode](#api-gateway-emulator-mode) + - [Required Configuration](#required-configuration) + - [Combined Mode](#combined-mode) +- [Command Line Options](#command-line-options) +- [API Gateway Configuration](#api-gateway-configuration) + - [Single Route Configuration](#single-route-configuration) + - [Multiple Routes Configuration](#multiple-routes-configuration) +- [Running the Test Tool Project via an IDE](#running-the-test-tool-project-via-an-ide) +- [Example Lambda Function Setup](#example-lambda-function-setup) + - [1. Lambda Function Code](#1-lambda-function-code) + - [2. Configuration Files](#2-configuration-files) + - [3. API Gateway Configuration](#3-api-gateway-configuration) + - [4. Testing the Function](#4-testing-the-function) + + +## Getting help + +This tool is currently in preview and there are some known limitations. For questions and problems please open a GitHub issue in this repository. + +## Installing + +The tool is distributed as .NET Global Tools via the NuGet packages. To install the tool execute the following command: + +``` +dotnet tool install -g amazon.lambda.testtool --prerelease +``` + +To update the tool run the following command: + +``` +dotnet tool update -g amazon.lambda.testtool --prerelease +``` + +## Running the Test Tool + +### Lambda Emulator Mode +Use this mode when you want to test Lambda functions directly without API Gateway integration. + +``` +# Start Lambda emulator on port 5050 +dotnet lambda-test-tool start --lambda-emulator-port 5050 +``` + +### API Gateway Emulator Mode +Use this mode when you want to test Lambda functions through API Gateway endpoints. This mode requires additional configuration through environment variables. + +``` +# Start API Gateway emulator on port 5051 in REST mode +dotnet lambda-test-tool start \ + --api-gateway-emulator-port 5051 \ + --api-gateway-emulator-mode Rest + +``` +#### Required Configuration +When running via command line, you must set the environment variable for API Gateway route configuration: + +Linux/macOS: +```bash +export APIGATEWAY_EMULATOR_ROUTE_CONFIG='{"LambdaResourceName":"AddLambdaFunction","HttpMethod":"Get","Path":"/add/{x}/{y}"}' +``` + +Windows (Command Prompt): + +``` +set APIGATEWAY_EMULATOR_ROUTE_CONFIG={"LambdaResourceName":"AddLambdaFunction","HttpMethod":"Get","Path":"/add/{x}/{y}"} +``` + +Windows (PowerShell): + +``` +$env:APIGATEWAY_EMULATOR_ROUTE_CONFIG='{"LambdaResourceName":"AddLambdaFunction","HttpMethod":"Get","Path":"/add/{x}/{y}"}' +``` + +### Combined Mode +Use this mode when you want to run both Lambda and API Gateway emulators simultaneously. + +``` +# Start both emulators +dotnet lambda-test-tool start \ + --lambda-emulator-port 5050 \ + --api-gateway-emulator-port 5051 \ + --api-gateway-emulator-mode Rest +``` + +## Command Line Options +| Option | Description | Required For | +|--------|-------------|--------------| +| `--lambda-emulator-port` | Port for Lambda emulator | Lambda Mode | +| `--lambda-emulator-host` | Host for Lambda emulator | Lambda Mode | +| `--api-gateway-emulator-port` | Port for API Gateway | API Gateway Mode | +| `--api-gateway-emulator-mode` | API Gateway mode (Rest/HttpV1/HttpV2) | API Gateway Mode | +| `--no-launch-window` | Disable auto-launching web interface | Optional | + + +## API Gateway Configuration +When using API Gateway mode, you need to configure the route mapping using the APIGATEWAY_EMULATOR_ROUTE_CONFIG environment variable. This can be a single route or an array of routes: + +### Single Route Configuration +``` +{ + "LambdaResourceName": "AddLambdaFunction", + "HttpMethod": "Get", + "Path": "/add/{x}/{y}" +} +``` + +### Multiple Routes Configuration + +``` +[ + { + "LambdaResourceName": "AddLambdaFunction", + "HttpMethod": "Get", + "Path": "/add/{x}/{y}" + }, + { + "LambdaResourceName": "SubtractLambdaFunction", + "HttpMethod": "Get", + "Path": "/minus/{x}/{y}" + } +] + +``` + +## Running the Test Tool Project via an IDE + +Download this repository and create/modify the launch settings `Properties/launchSettings.json` to startup the test tool + +```json +{ + "profiles": { + "Lambda Test Tool": { + "commandName": "Project", + "commandLineArgs": "start --lambda-emulator-port 5050 --api-gateway-emulator-port 5051 --api-gateway-emulator-mode Rest", + "environmentVariables": { + "APIGATEWAY_EMULATOR_ROUTE_CONFIG": { + "LambdaResourceName": "AddLambdaFunction", + "HttpMethod": "Get", + "Path": "/add/{x}/{y}" + } + } + } + } +} + +``` + +## Example Lambda Function Setup + +### 1. Lambda Function Code +Here's a simple Lambda function that adds two numbers together: + +```csharp +using Amazon.Lambda.APIGatewayEvents; +using Amazon.Lambda.Core; +using Amazon.Lambda.RuntimeSupport; +using Amazon.Lambda.Serialization.SystemTextJson; + +var Add = (APIGatewayHttpApiV2ProxyRequest request, ILambdaContext context) => +{ + // Parse x and y from the path parameters + var x = int.Parse(request.PathParameters["x"]); + var y = int.Parse(request.PathParameters["y"]); + return (x + y).ToString(); +}; + +await LambdaBootstrapBuilder.Create(Add, new CamelCaseLambdaJsonSerializer()) + .Build() + .RunAsync(); + +``` + +### 2. Configuration Files +**Properties/launchSettings.json** +Configure the Lambda function to use the test tool: + +``` +{ + "profiles": { + "AspireTestFunction": { + "commandName": "Project", + "environmentVariables": { + "AWS_LAMBDA_RUNTIME_API": "localhost:5050/AddLambdaFunction" + } + } + } +} +``` + +**aws-lambda-tools-defaults.json** +``` +{ + "profile": "default", + "region": "us-west-2", + "configuration": "Release", + "function-runtime": "dotnet8", + "function-memory-size": 512, + "function-timeout": 30, + "function-handler": "AddLambdaFunction" +} +``` + +### 3. API Gateway Configuration +To expose this Lambda function through API Gateway, set the APIGATEWAY_EMULATOR_ROUTE_CONFIG: + +``` +{ + "LambdaResourceName": "AddLambdaFunction", + "HttpMethod": "GET", + "Path": "/add/{x}/{y}" +} +``` + +### 4. Testing the Function +1. Start the test tool with both Lambda and API Gateway emulators: +``` +dotnet lambda-test-tool start \ + --lambda-emulator-port 5050 \ + --api-gateway-emulator-port 5051 \ + --api-gateway-emulator-mode HTTPV2 + +``` +2. Send a test request: +``` +curl -X GET "http://localhost:5051/add/5/3" -H "Content-Type: application/json" -d '"hello world"' + +``` + +Expected response: +``` +8 +``` From 3d1c8c1e5739fb4108508bf877993a93c04c90db Mon Sep 17 00:00:00 2001 From: Garrett Beatty Date: Fri, 7 Feb 2025 13:32:17 -0500 Subject: [PATCH 2/9] add readme to nuget --- .../src/Amazon.Lambda.TestTool/Amazon.Lambda.TestTool.csproj | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Amazon.Lambda.TestTool.csproj b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Amazon.Lambda.TestTool.csproj index aa251c944..4eb39b5e5 100644 --- a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Amazon.Lambda.TestTool.csproj +++ b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Amazon.Lambda.TestTool.csproj @@ -18,6 +18,7 @@ 0.0.3 NU5100 Major + README.md @@ -69,4 +70,8 @@ + + + + From aa4ad608e6e8f39ea55787adb5c5accc839aa47e Mon Sep 17 00:00:00 2001 From: Garrett Beatty Date: Fri, 7 Feb 2025 13:36:50 -0500 Subject: [PATCH 3/9] add differences --- .../src/Amazon.Lambda.TestTool/README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/README.md b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/README.md index ba2c096ad..a7180b02e 100644 --- a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/README.md +++ b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/README.md @@ -7,11 +7,18 @@ The AWS Lambda Test Tool provides local testing capabilities for .NET Lambda fun 2. API Gateway Emulator Mode 3. Combined Mode (both emulators) -# AWS Lambda Test Tool +## Comparison with Previous Test Tool + +The AWS Lambda Test Tool is an evolution of the previous AWS .NET Mock Lambda Test Tool, with several key improvements: + +### New Features +- **API Gateway Emulation**: Direct support for testing API Gateway integrations locally # AWS Lambda Test Tool - [Overview](#overview) +- [Comparison with Previous Test Tool](#comparison-with-previous-test-tool) + - [New Features](#new-features) - [Getting help](#getting-help) - [Installing](#installing) - [Running the Test Tool](#running-the-test-tool) From 962ca1a46d0bf975cff14060ba28e9180ef29fdc Mon Sep 17 00:00:00 2001 From: Garrett Beatty Date: Fri, 7 Feb 2025 13:43:50 -0500 Subject: [PATCH 4/9] Add class library defaults example --- .../src/Amazon.Lambda.TestTool/README.md | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/README.md b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/README.md index a7180b02e..5572dcd7d 100644 --- a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/README.md +++ b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/README.md @@ -172,9 +172,14 @@ Download this repository and create/modify the launch settings `Properties/launc ## Example Lambda Function Setup +Here's a simple Lambda function that adds two numbers together. This can be implemented in two ways: + ### 1. Lambda Function Code Here's a simple Lambda function that adds two numbers together: +#### Option 1: Using Top-Level Statements + + ```csharp using Amazon.Lambda.APIGatewayEvents; using Amazon.Lambda.Core; @@ -195,6 +200,24 @@ await LambdaBootstrapBuilder.Create(Add, new CamelCaseLambdaJsonSerializer()) ``` +#### Option 2: Using Class Library +``` +using Amazon.Lambda.APIGatewayEvents; +using Amazon.Lambda.Core; + +namespace MyLambdaFunction; + +public class Function +{ + public int Add(APIGatewayHttpApiV2ProxyRequest request, ILambdaContext context) + { + var x = int.Parse(request.PathParameters["x"]); + var y = int.Parse(request.PathParameters["y"]); + return x + y; + } +} +``` + ### 2. Configuration Files **Properties/launchSettings.json** Configure the Lambda function to use the test tool: @@ -213,6 +236,8 @@ Configure the Lambda function to use the test tool: ``` **aws-lambda-tools-defaults.json** + +For top-level statements, your `aws-lambda-tools-defaults.json` should be: ``` { "profile": "default", @@ -225,6 +250,22 @@ Configure the Lambda function to use the test tool: } ``` +For the class library approach, your `aws-lambda-tools-defaults.json` should be: + +``` +{ + "profile": "default", + "region": "us-west-2", + "configuration": "Release", + "function-runtime": "dotnet8", + "function-memory-size": 512, + "function-timeout": 30, + "function-handler": "MyLambdaFunction::MyLambdaFunction.Function::Add" +} + +``` + + ### 3. API Gateway Configuration To expose this Lambda function through API Gateway, set the APIGATEWAY_EMULATOR_ROUTE_CONFIG: From 9249fd407668d2e96b133268476e2cd65021c8b0 Mon Sep 17 00:00:00 2001 From: Garrett Beatty Date: Fri, 7 Feb 2025 13:45:03 -0500 Subject: [PATCH 5/9] add changefile --- .../changes/aeef605f-6fd5-4280-94c7-ddffa1a3d021.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .autover/changes/aeef605f-6fd5-4280-94c7-ddffa1a3d021.json diff --git a/.autover/changes/aeef605f-6fd5-4280-94c7-ddffa1a3d021.json b/.autover/changes/aeef605f-6fd5-4280-94c7-ddffa1a3d021.json new file mode 100644 index 000000000..1541f9688 --- /dev/null +++ b/.autover/changes/aeef605f-6fd5-4280-94c7-ddffa1a3d021.json @@ -0,0 +1,11 @@ +{ + "Projects": [ + { + "Name": "Amazon.Lambda.TestTool", + "Type": "Patch", + "ChangelogMessages": [ + "Add README" + ] + } + ] +} \ No newline at end of file From 29f37afb1e2ce1d562a5b8cfb5aa115ec6597425 Mon Sep 17 00:00:00 2001 From: Garrett Beatty Date: Mon, 10 Feb 2025 10:35:52 -0500 Subject: [PATCH 6/9] PR comments --- Tools/LambdaTestTool-v2/CONTRIBUTING.MD | 31 +++++ .../Amazon.Lambda.TestTool => }/README.md | 128 ++++++++---------- Tools/LambdaTestTool-v2/Resources/img.png | Bin 0 -> 69869 bytes 3 files changed, 90 insertions(+), 69 deletions(-) create mode 100644 Tools/LambdaTestTool-v2/CONTRIBUTING.MD rename Tools/LambdaTestTool-v2/{src/Amazon.Lambda.TestTool => }/README.md (64%) create mode 100644 Tools/LambdaTestTool-v2/Resources/img.png diff --git a/Tools/LambdaTestTool-v2/CONTRIBUTING.MD b/Tools/LambdaTestTool-v2/CONTRIBUTING.MD new file mode 100644 index 000000000..b780c3050 --- /dev/null +++ b/Tools/LambdaTestTool-v2/CONTRIBUTING.MD @@ -0,0 +1,31 @@ +# Contributing Guidelines + +Please follow our main contribution [guide](https://github.com/aws/aws-lambda-dotnet/blob/master/CONTRIBUTING.md) for high level details on how to contribute. + +## Lambda Test Tool Specific Contribution Details + +### Running the Test Tool Project via an IDE + +Download this repository and create/modify the launch settings `Properties/launchSettings.json` to startup the test tool + +```json +{ + "profiles": { + "Lambda Test Tool": { + "commandName": "Project", + "commandLineArgs": "start --lambda-emulator-port 5050 --api-gateway-emulator-port 5051 --api-gateway-emulator-mode Rest", + "environmentVariables": { + "APIGATEWAY_EMULATOR_ROUTE_CONFIG": { + "LambdaResourceName": "AddLambdaFunction", + "HttpMethod": "Get", + "Path": "/add/{x}/{y}" + } + } + } + } +} + +``` + +Follow the [README](README.md#example-lambda-function-setup) for setting up a local lambda function to pair with the emulator. + diff --git a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/README.md b/Tools/LambdaTestTool-v2/README.md similarity index 64% rename from Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/README.md rename to Tools/LambdaTestTool-v2/README.md index 5572dcd7d..dbdca3fae 100644 --- a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/README.md +++ b/Tools/LambdaTestTool-v2/README.md @@ -7,41 +7,52 @@ The AWS Lambda Test Tool provides local testing capabilities for .NET Lambda fun 2. API Gateway Emulator Mode 3. Combined Mode (both emulators) +![img.png](img.png) + ## Comparison with Previous Test Tool The AWS Lambda Test Tool is an evolution of the previous AWS .NET Mock Lambda Test Tool, with several key improvements: ### New Features - **API Gateway Emulation**: Direct support for testing API Gateway integrations locally +- New flow for loading Lambda functions that mimic's closer to the Lambda service. This solves many of the issues with the older tool when it came to loading dependencies. +- Ability to have multiple Lambda functions use the same instance of the test tool. +- UI refresh +- [Support for integration with .NET Aspire](https://github.com/aws/integrations-on-dotnet-aspire-for-aws/issues/17) # AWS Lambda Test Tool - [Overview](#overview) - [Comparison with Previous Test Tool](#comparison-with-previous-test-tool) - - [New Features](#new-features) + - [New Features](#new-features) - [Getting help](#getting-help) - [Installing](#installing) - [Running the Test Tool](#running-the-test-tool) - - [Lambda Emulator Mode](#lambda-emulator-mode) - - [API Gateway Emulator Mode](#api-gateway-emulator-mode) - - [Required Configuration](#required-configuration) - - [Combined Mode](#combined-mode) + - [Lambda Emulator Mode](#lambda-emulator-mode) + - [API Gateway Emulator Mode](#api-gateway-emulator-mode) + - [Required Configuration](#required-configuration) + - [Combined Mode](#combined-mode) - [Command Line Options](#command-line-options) - [API Gateway Configuration](#api-gateway-configuration) - - [Single Route Configuration](#single-route-configuration) - - [Multiple Routes Configuration](#multiple-routes-configuration) -- [Running the Test Tool Project via an IDE](#running-the-test-tool-project-via-an-ide) + - [Single Route Configuration](#single-route-configuration) + - [Multiple Routes Configuration](#multiple-routes-configuration) - [Example Lambda Function Setup](#example-lambda-function-setup) - - [1. Lambda Function Code](#1-lambda-function-code) - - [2. Configuration Files](#2-configuration-files) - - [3. API Gateway Configuration](#3-api-gateway-configuration) - - [4. Testing the Function](#4-testing-the-function) + - [1. Lambda Function Code](#1-lambda-function-code) + - [2. Configuration Files](#2-configuration-files) + - [3. AWS_LAMBDA_RUNTIME_API](#3-aws_lambda_runtime_api) + - [4. API Gateway Configuration](#4-api-gateway-configuration) + - [5. Testing the Function](#5-testing-the-function) ## Getting help This tool is currently in preview and there are some known limitations. For questions and problems please open a GitHub issue in this repository. +## .NET Aspire integration +The easiest way to get started using the features of the new test tool is with .NET Aspire. The integration takes care of installing the tool and provides .NET Aspire extension methods for configuring your Lambda functions and API Gateway emulator in the .NET Aspire AppHost. It avoids all steps list below for installing the tooling and setting up environment variables. + +Check out the following tracker issue for information on the .NET Aspire integration and steps for getting started. https://github.com/aws/integrations-on-dotnet-aspire-for-aws/issues/17 + ## Installing The tool is distributed as .NET Global Tools via the NuGet packages. To install the tool execute the following command: @@ -147,35 +158,12 @@ When using API Gateway mode, you need to configure the route mapping using the A ``` -## Running the Test Tool Project via an IDE - -Download this repository and create/modify the launch settings `Properties/launchSettings.json` to startup the test tool - -```json -{ - "profiles": { - "Lambda Test Tool": { - "commandName": "Project", - "commandLineArgs": "start --lambda-emulator-port 5050 --api-gateway-emulator-port 5051 --api-gateway-emulator-mode Rest", - "environmentVariables": { - "APIGATEWAY_EMULATOR_ROUTE_CONFIG": { - "LambdaResourceName": "AddLambdaFunction", - "HttpMethod": "Get", - "Path": "/add/{x}/{y}" - } - } - } - } -} - -``` - ## Example Lambda Function Setup -Here's a simple Lambda function that adds two numbers together. This can be implemented in two ways: +Here's a simple Lambda function that adds two numbers together. ### 1. Lambda Function Code -Here's a simple Lambda function that adds two numbers together: +This can be implemented in two ways: #### Option 1: Using Top-Level Statements @@ -200,6 +188,22 @@ await LambdaBootstrapBuilder.Create(Add, new CamelCaseLambdaJsonSerializer()) ``` +Configure the Lambda function to use the test tool: + +**Properties/launchSettings.json** +``` +{ + "profiles": { + "AspireTestFunction": { + "commandName": "Project", + "environmentVariables": { + "AWS_LAMBDA_RUNTIME_API": "localhost:5050/AddLambdaFunction" + } + } + } +} +``` + #### Option 2: Using Class Library ``` using Amazon.Lambda.APIGatewayEvents; @@ -218,15 +222,17 @@ public class Function } ``` -### 2. Configuration Files -**Properties/launchSettings.json** Configure the Lambda function to use the test tool: +**Properties/launchSettings.json** ``` { "profiles": { - "AspireTestFunction": { - "commandName": "Project", + "LambdaRuntimeClient_FunctionHandler": { + "workingDirectory": ".\\bin\\$(Configuration)\\net8.0", + "commandName": "Executable", + "commandLineArgs": "exec --depsfile ./MyLambdaFunction.deps.json --runtimeconfig ./MyLambdaFunction.runtimeconfig.json %USERPROFILE%/.dotnet/tools/.store/amazon.lambda.testtool/0.0.2-preview/amazon.lambda.testtool/0.0.2-preview/content/Amazon.Lambda.RuntimeSupport/net8.0/Amazon.Lambda.RuntimeSupport.dll MyLambdaFunction::MyLambdaFunction.Function::Add", + "executablePath": "dotnet", "environmentVariables": { "AWS_LAMBDA_RUNTIME_API": "localhost:5050/AddLambdaFunction" } @@ -235,38 +241,23 @@ Configure the Lambda function to use the test tool: } ``` -**aws-lambda-tools-defaults.json** +There are three variables you may need to replace: -For top-level statements, your `aws-lambda-tools-defaults.json` should be: -``` -{ - "profile": "default", - "region": "us-west-2", - "configuration": "Release", - "function-runtime": "dotnet8", - "function-memory-size": 512, - "function-timeout": 30, - "function-handler": "AddLambdaFunction" -} -``` +1. The test tool version `0.0.2-preview` in the above path to the `Amazon.Lambda.RuntimeSupport.dll` should be updated to the current test tool version. +2. The .net version `net8.0` should be the same version that your lambda project is using. +3. The function hanadler `MyLambdaFunction::MyLambdaFunction.Function::Add` needs to be in the format of `::.::` -For the class library approach, your `aws-lambda-tools-defaults.json` should be: +3. ### AWS_LAMBDA_RUNTIME_API -``` -{ - "profile": "default", - "region": "us-west-2", - "configuration": "Release", - "function-runtime": "dotnet8", - "function-memory-size": 512, - "function-timeout": 30, - "function-handler": "MyLambdaFunction::MyLambdaFunction.Function::Add" -} +The `AWS_LAMBDA_RUNTIME_API` environment variable tells the Lambda function where to find the Lambda runtime API endpoint. It has the following format: -``` +`host:port/functionName` -### 3. API Gateway Configuration +The host and port should match the port that the lambda emulator is running on. +In this example we will be running the lambda runtime api emulator on `localhost` on port `5050` and our function name will be `AddLambdaFunction`. + +### 4. API Gateway Configuration To expose this Lambda function through API Gateway, set the APIGATEWAY_EMULATOR_ROUTE_CONFIG: ``` @@ -277,7 +268,7 @@ To expose this Lambda function through API Gateway, set the APIGATEWAY_EMULATOR_ } ``` -### 4. Testing the Function +### 5. Testing the Function 1. Start the test tool with both Lambda and API Gateway emulators: ``` dotnet lambda-test-tool start \ @@ -289,7 +280,6 @@ dotnet lambda-test-tool start \ 2. Send a test request: ``` curl -X GET "http://localhost:5051/add/5/3" -H "Content-Type: application/json" -d '"hello world"' - ``` Expected response: diff --git a/Tools/LambdaTestTool-v2/Resources/img.png b/Tools/LambdaTestTool-v2/Resources/img.png new file mode 100644 index 0000000000000000000000000000000000000000..9ef56d54f0bcbc030ff9091ffc648f52a45c8a68 GIT binary patch literal 69869 zcmeFYcTkh<*Di`6pr~L&q@yTGS4xl?c~wBFbg4n5SLroG4V=2l!*2%>VqYIP56k$Uh@9b!O;41Ex}; zD1(1T=J8!(|BRlMYCD|!XLNf~^gqO%bXaOz^+wm#o%xTiJ23s{NB;Ya!r)ImYgZDdJWND;LqE(h?4Ol z)K5MT{z9zwx80wH%wG$HtYw1w72|9L7TElrO<`>uOin zIpN$`QES5-HF4k)?ae|U_NWKsA4y%a7*qb4g#}U~uWEn{R)`vVI5ge)-A8^~btx7| zr}hflup8%iK!(^aXq~a0^soHkDl=jgOUDm_9KBeWn8-^%__YwV+>!-P{EO%;`R!BcZJLp{aM(3T9o=e+||*7l@|Pu^5fihb}+f`}EAC zvCE#}mFl$iprGs&A*RjOXst+Xp)B)j(K4h`yx=oW`o>rl3HU%RI`v+0un&~N`sX6Q z$sYyC-$iuNDcEzcGI7tzyux>rKp*eph1KSwYLjNQqkdn_3lct<76MO0;O%bahb@`4 z0Ba2u-`~V&4w(#5*Hpn#QG=W|fSAO$GHna=!f#$7kkO zM(Cuj&Yv(v8JkNWde65ILGHnKQ^uy__Ykp4ONld8e7vQy?)4j`*QWa_R>@880YTcw ztBXbjFRH8+Lzu5Qjl>UO!@l>1Url#t{!B4=HD({Mg;2l`Cn`nTO12-kP{Ti{-dgYP zsQq&2{mevjXuQY>Axk(+T4JLTA@pE@g^8lMsim7)SACR)z@LzfnZ-DrLgTje(%i#U zg3`#?^z^G>yR3-1QQD#DS|(b{Drz7vRn1<5>sn>sMeb6S7!T;$_xqYlM_Es{X**ZC zCXoB%uzq|RZZ-Agw&_22zBiP5syMpI5>EWFnKy1Mh{;>l-;W^;4mkNkrLyhbWZ+Ze zxn~Ywiv+y9RV??6!2VDf%Ed-ysQ1e-iVN~H{!1g{4xfh*XA-X+j>zz;U7<;FoNvdW zMQNRr6#0CwC3P}Cy>3-F!r`h(>`CPV!uJp$dEbXlfC~pGHf^0a3NSrAbMjr*b-l&_ z#HbxgcuF#qI9$i4_WqeOBqoH+~;FcH`Sr582B{3DU)#18k_Mn zVEt1QCy8zmg>W^-E-RelH6EWT=_>M=-Cwcrpz4ZNXXJsHq2j}9HK+KaL%>xmLgwZp z!+BkW9PXu~>)}MYi41ivC9;jswnPO1Z|5Uf4uNzWaPOer-S~)+zpxC8dUZ)rr}cQT z**ypOR-uo?Y0_;MHUMmC;(L6^@cu+5>`J5f*_nmr&+4bB26eFHSQ_nEA@``|U%ug4 zT@HtPEM-He8$NAW>KCwfxZu;V)KZe04X~RJsb+ub)_m%U3J!#>iI$>O*jN zpT5Glp*=v#F;594Y3~z+7VnyOK@nX1e=j-bVopflSWikFir{v_X>0CBopkot-fw-7 zCFi1Yo0bQK3)E+T&vkcF4S6v$!C1VT11@jWq^-cluw=QA`%C>0_&%$m5n@z2&_blX z>1@ErsPQO&8iZ{fDP{i9QVv3phks_f>)w5~GJS~c@7n5Y!m-eGGM_>7Zm3>#1P%nMr z_aFghSd}PJ)fs05Bx7|a&~?gJ%ax`5n>-cb&-lfPNf*>8uvWAjMW^>F5`;nFb1S8F zX9 z*sx^mnGzGTwR9>iTsYEX%4=InFxa%M-2TSwY)0z}#UJHcb&jud4eTFNuP~efT?s7g zH&LYS7K&xKdIMYfg_W&!U79g-FZ{-LoW{oNb-R1;26DIyf$iEKODZPLU|hpZ))yWZ zdNeO+Tx$UbaJ~i+UiA880Ch2T-z4~zV$j}O$+6OJQOGkr%C4y84Vz}zEv~%X?g-cL zv3c#}CY(*|uHMFO&Km+CWB-Y?!M5$Z4QfxBc<@8uProqyeh=}{AY5!ruJd4#yL-?9 z^^{j5?_hRNaSoTfk=mcV4wuaJVSx^~TJ6vIk~W9L=yVU8;QrBgy*iN`a(G&m~`6j)|qAsz0(+vRBtLV$mHWe9DX$zJIjU#REFL?@i0tqL|pTM!EXL;zmpu~ zlbjXR_O$*^h@bbxXJ}0ae^c!rq&cw?&^HkSbT^Ze4YYiI2Mm|_8L`!RqvEw;MKC8~ zE_y_%3E_?tIB?U;TWt!b%#K}>mgGCT@n8=7FyrTs$Dt7wPB{OPh*#u; zraMy=W}(aA>0;*YPkSm;zmsl6HWC+;G_TQGu2J#p`n>3(Zcb0+I{3o+s((doK+T-X z+j^3wo@^CtvtRj7P0r#qwQvV&5X)@@)Xs_fG!KF-=Y}D1iruzFM6yOTZ-yAU%|ysA z4AEb?v9saAoqWvGJ3KTzV!1xpE)zR@NLG4jjc$jig>X3&Yap@HrlJK0fq=t+{DwHm z^e}2Mwr}~;QoTm}1ikqZ67ICCf~M#Wa6k3Ch^)5M7-MmVWpQ3%c3!OYeGa!fZ+7dF zcKq+g*SSv~-i_DEPFAl#uXXi)2O7Z)*|>m6Nxie0ZLY8))Y|Jc4SapX!AstImc~EN z`AJxRS`dqr{lIIRCB~m$Uv_m)#+MUm;gbw$&X&-2@LxIM9unZTH=cX#`|lY>ni*fy zoRTqjZ+w%iy8iTVMkW+A67Nb~ZF7W+s-u!CTufm}-C@uV1L_GyMJUl;*-K&?^C`#L zXEp+U3j(||6!KuCi#~7^C$N}A_zogz4#f>+&-J&a(SOD#MLzXkUmC(|dzX%8uSXip zYQi1vA61iQ_G@8=`gVK+8cjje4KQ6cZq$P=PhAJorFdG4#{PqBoCL$^PAcX{&X~nzez-JO=od9~J-3jm>)n$y_91Q@ zdF345IIA1;Iy$#(<8EgU5dyZ@hhwF&Cce`qu32v?+7v`Vhm z9~~+C4V4p&zYAdnV5eZPLMd%fx~o^3^H*RwK*`8%qV;vx`t#n@FQ6QiKwY7XP903U z%X6S^-5wUYmJJf#>!hp-17A;j*fxIF{lduo_K5DrrnfWEgIT!zFDmZF*d@7X)x$Cw z(ywUS$c?i4(#ekqK1Wp$Cx`D(gafPiNrD~}T?ziDeqm-oImZC1cw|{m@hwF&qQl`+ zdj9lwJ@z2?t6L~N<*S?+88aoO{Qj7yU|L#(ao7`!WJ2fxtNMeKlkcE?QTaHxq#2xj$8>T%)^ge zV6RO=VbZ>T+VmVpd@GM}SMU(Og-LlKv?iDvWq=n#GMssXWXw8;yVhF{?^3sV^IWai z1u33|ouw{kIi^j{tb(KHJgUn(_~5yjfTEkLZS}WZ=g6T2sC+``enkDV#{pgiN5f6c zSJGd1Imi7G>dc-?Iq9i|z85v*;LZg;TD1P@#^&rS?U$dJR6t*k*eeVMl-nylLR)!<5>YNWh7MrpTBN;C5<8vuKp zB{4|odVY6szPBwv`Dgj^U#94w49f4AO^fgtvJKDHFA#302#nkgD}yjY1APZ2{grF< z+$+4sQOCVY1OLz#hAZf+if{L*gg#u?I4m9{jf(DdLTWZ(r_%`bnQ*h080yFdxR$y<6$;NOu_yhM%t~dE%p1Xrhwpk}Xrw&{v%;H~ z>wwJA?o}pTYjCE8ic8h^bTkCeT0inrzI&o#Kl0YfLB8Ewg8~x^v>UGYnahw?iWVd> zjBfv1o2D1nU=Y#>kY?P2B!KC5-R`8A$)PFV%T&IZ!E?zI(SdO)j(!+Xd~@Z9LZv@K zC!P}F?hfDJ2G{}oPKfzMzXP4+A9~xNIXAl-m3idLV7t{0bFVTKNH zD^B<6*+6n;ZpXef;}V^$uO1C^H(O@}=W=UMOB;4evm2Tnb*8Lh+7T3Ibhs0E-k+v2 zK37@LBwd^ z;P=vV8*a+gbI6`)zI!)2sAN&%RR8xI%P9iXlKzu2&i$Ms>xqFo2?c6u3)?eOMXXUv z4+SC{wK#u|PBa3CJOIc*Q!h4T^ki>*b(*Y;{gmrQS9Pg=Xa&9@a4-C~ATn1JzBSq8 zWzMbJ74*c%&)5J>o#aeg-$}(;9Lq&Zf9?_qk3M>Ku;~ z$J_>m-53qsd3QVSt-o+dZy>nPH`_)lY+-|OCm-^lPRfbR4ejvz=Hv#{JUKg49^oLL z*`vtEnjvI%^5BWXcul1``R4nR06xJ*g;83?DwJXXA4Kxb2mq|sn~tJ;8Uy}7Jl+EL zYZ+HDbmUK@D;LBYH54LNvB37&0cSk>6T!g-fXsdu3MueqRl?^MK4t}oc2^0bjEG^Y zLro8tvc*60B4G>23 ziQ1VJ9h5{NChFV^3zK$t_Xpyp%c+@TEYad7&!4UXYb2S!GKzGR_NuHT^ z_Sa#!jzrez=Rpqs&4ae*j%KS)Nhk3p!DaJT+ut(x{)N$Y6{Rb4@A@Ow4E?jE)(QIe zpt@Y%nVJSy6|0Zigmsmi#ACYc7X9Qnax>nFR$BlbKKyI12E)?51(YP8UVJOWfTG@o zdX@>$Zp1l=rQHJV?D`>eK`Ycy<PpNEoOgrB&wJhmc&o-)Or`Y0j4&w%w1)<`mX_?rW31-iARY0fO zSBke@k*94*WE2mZBq+qh`6Bu&_H8*M+Lp_xQ8}hi2!Go@;?%&HOK^V_=3M{sft##w1GN>`-h2?&^J?gF zDWE#zSaVwC*R_Dcj^mzUK-o!dFW?;6jiRGo89A;?v8`&O3eMmjo;_@>QyuC#Fe?yfyOFB6FWLFmO9+ooG*P8zZSWRphYSwA7-8cv|Z z)a^vq2eyBN_}X7kWBKUdAHzcPzru!x?fGs!HIF`Sy{|5fPP&Gd@q=*1vF?ZuGPk zzhV71q(NT%=`>cD1FHv$%l86L(`PyuH_+45Dm^Qc5XZn(q?L8$8{wBoqCYscC|&FS z0c=ED$?C}m{fTN!k!s%l1#9TXKRI|VJQMMFYYA~`N$3gKD%QOcZa4>nXc}g}>1DRo zn^x^?Y%Ke|{F!Mc-dIFJ`i4SaS^E;!bTo{6XPHm?MW&dnFqh>k7MFY{@OiXa4Px)H zrPr5|oT*Ub>hY7!$+MNkWI(!U%fOy4dqH(OKcZ(QWXgE-gBIvA zNs@4&Wojk%JtstW%7HE&>mO_A+-w9aZc^N-mq`upCPr8Qs(A&l1ZBj>uUt~jAIn@H zJe^SpjR4mhVbhZ)Hk$eexxH#{s?ep8EfuHsl{kK{43|3QAfYtmC0@aAi1uIybW;J1 z?oqB)0&{~plhas}|f%Rt>A@qgh9O%)!*-riSx}<@vdB!Q1 zEao|HsYzoyKYl%JG6>#k?!=5rYvzt0!j%rY*5mn8N%0RsKW8uSMpCbP6u9p*fX-SE zBLDtcX3=Uw=0F{PBp*m`i{yOM`Gthh#=4FMSS^TwI!tc{Un=vPEePo?Ih{4#S z!kuc~y@vB!6`c|U#E~9|>x6E1STcaC(cmV;p`{t>U22vnzz1wL)fsx(sqMKO!$kD| z2sy~h2vYp&ncseBf8gi_p8Vb;XPP4WkI_r~LylR_L|c?IUXkttf^PpsTvXez;A5 z{;qZAmKF=YYhtalovnLyl@-W5ow8J@L{_M7(f@kU5J3TgJih|h;Sg1E*>2^lxLfEpzG}1YRI@v6nVUt~@(nU{x&Zd)xQ7 z7y;?nFL-UX9P*cQv15mb`^s~IY(NGIf?Hk1J2~Kf4<5W>yuFy_9`Lw5i{adEY3Zri zWJa1xzxIEyu|_wNtI$L0#4+QVM&kmvLz>!!V`DKVI;zrHv@!44i zeRG?_9P_$Qci`f5JcwS9?Xc&>0HVvO%+30hv?(3Q2Ucd(cz(wCPen8LnQ<%u@eIFg zXfai>-%Ot5nnzz{fo6{pekWMxXnZS*8hY!U_L|GEeueXm@c7dnc`d{um!agT>azD= z7!d<*(FV0dljbWEtMxV2hQaGs(8ds!obMBKRCHtIOal2J56nAbHZE+Kl=?>?$_pJbne)jdE|cDStEc=9qq*vnhMJ0>ZKB(PxcY=cn5f^&?zorVb~5&lJb2Xr z`g1QG94=lZ%DBdYCRf8=7z)fpd@vA#jS@#PDU4`BM!kAg>1>n%$_Gw61^H44KkS8M zC2xR!W&lfZiBgGIo41swKmpe`U86bL#_gZi{_|Me*m*A(O z)mE249V-&Qj5{x`V;=RZTCR%CSZ>3|wXHFz8>tM&MNQ+s)Q9(6e;dhP-~T`6lQ5Y- z|374&{6Q3P8H=Kkgj(kBD;gZ$zh9VODc=_ z`%2zEa};pma<$v#>RHjFaJf@IgJS-Xm%GBS33naF?>f|JAB%9}`?1UUkBr-2&-^o& z(?16kmgfZrc>Y??vp1^#QA7OBI$r)op7W5qtw?Fso(QZ^QZ$9AGd~dXv9PDctN8rp zTW0nX+)u6IfxQyfl{Z!4k)vNKm ztbmRu8a4ej!YPrsbl&#Eka}?Zjz-pk(X>qgb&boDGbOWC%!;xSIZKRd?7R*{DqmK$ zUl3^kUfh~#EY>*YS&1~&^@&rllmU%x_v6Bo@M}s~p@hYGrM`Mfj5X!yI3a)fd-H+- z-V&&EP5qd~njlov$rEgC-A?X|eEqJ2QAaAl?w2$RHK~@`Sqa-tTVw_Y>4Lq6RbZ{K zC$&DXw%J!(;X?ESuo#+g?o8Pbx->gbTx%EckM-@H^SjdOqwkgEBntxGOX8Cj>N z3}kRgAkt3A;6B9hOX6;Am2ITJj0}{RM%(3BCbj!}%-e_=WP$~8i$^jS*d996IoGO@ zOD&4BHY= zMQ@r^8ApYx+Hkkz#CWEt4nC_Bo5pVzA$+}fB$oPgGN$05*787uUdLeVC*NMSY(@<^ zS7F+nyoGmGNuhCGf2-R?CbD|9@?(6?8q49+fYrwAs4soJeKwfYROXv8j`QALZQU`B zF>_0pI~KW5g2PQ$q96e~f|MbVI8~-x_R&`4WE=^Tu$-<+L}+*%-4-elcEKVtgxx!R zcDeSu1;mSdS%1hB`yQ2F33x$zR5+wM;w9%@DcdO2&jQ);)X?P)l`QK!A0GZhQ*{g~o+LEi7(_G%b#Gy7!V0Q_!ibp2f??*deZ znkIzL1yub_=_v*Q3{S0Vd%~_R?Gg@25V0U)nCFZ=F#?SVaT?{AOmc!Y^O4`Dypb z5~Ft)Oh26qS69zPg%jVG+dcJ=b2XK>;zQn;GVMh!i3j$$mT3~3#F#DYssO3LLcWGZ zWLBz)fl-?}?^8e4^X`03bwW>lW0`Pcpr*-_t*tB}uWL=BszWQ?lwx#;o*UHK04viP z`8+z>*-RYdC%`&6kk3LbAzNyqI?Zjf)*H`d2j3SRjKbY0rHdk}2d!(nk_o*n$WIT& zs!J-bbqI8jm)3O`E7J09Uga=%69ehT)5T+kgkkv8mCvEJlQqE3h8wO7N76~We& zTCKO%`HL|F1xo3pzrA2r*JxGLQ05f10GuJ3Ermmog6r8y{5#88#tYd^cB;2ITa8-8?iCP=zC;b!T$a6;-a>sICvy+jg=nIhKTuX%Rs$TXA+@k2F(l3R&ClbJwU6w%( z^1OXWS;@iN=3#-MaEGLKic=+y8h8s@kju;RN#>!wfN}AOW7Bst4sX-#M|@;~oi0AY z_dkx{yPv6{Y{suZ8*ZcFoJ5_uzE{rD&7{h-4QGDmqkv$wMQFmz-*&cI+OE2T)jG5l3vFQ?eBs(XU82nBn5c~<#zayCc<0hv%kb&;Ou`h zAd z5$f23AjsbfJt@T~Pf3;PbV=|kC|qT^0EOM?oZdWgyqC1yyRc{-dDm?F*f*@#HzdmC z-MYUn+oUbYSSPMaPlH9WdW)=apX)i4lqkRrwTd6;PoXo45ckP#BDe|RtHtO4C{rxTD;P8LvBFa3B0t|mxn0t0uf*we4jN`2et$cXQ3ah0;8Y%Higej}Sm{<} zcaShY1z@fE$7Qo+ZgY4dpB63r%olTWU6N5Hq(Q?Jd0*X(R=Cf5S<2H@2L<55#-kDOk^$HEHvUuJ>A!r5psyudBi5yTW=4J#<$;mOsm;EuOKm z@$j~}ZQY^MSKLGnzj{KS)ut%c;&5nq{Y!8Pq6mqY$83K3wAAje)401}inRAya<_K( zg1DE?eWBb@{KJdRLkog3_k=)cwJ24aDR)zrGO*27fO2k!raBfog3Uuuw4 z>c^=P`!Lzgn^1@)g&Po{IIfxrk#L+j8 zxuX4$@Ow7lj2*^*Pr%5k5$cXOM;OB#jnj-YIR7bYoB3;7ADu1 z39~B%55zSMP&Zf7cU-f*;+Lgt;Q#X7ua|;Ypu=uLZSnV~zu&2SvLO@-?=a^}9Zuu# zjXjvIvh9)(z3o^U;9v^#vw+Ffvzv}0o4-HMid@(#7&`NNC^3C!zD>K)3!BV6G-P5E z4x5;;O&9%C~isMHuf)DFkX`K0G-sj-MjTh zdG2{F3fk^Huo2Ap@5EeMB2Rh_r)?~aK0gve)VX6vXxkoOmELE6EXRDea3N}l%Te2Z zKp{EvmkIROsJ`$04o*R`%?g6;WehH|dC= zYGtt=t{|Ca)RES-c)y&e<>4G|a#LwRJSmgtiXuh@c-bY|UehL}dMt7LOY*;kz=Is> zEQBjEuDwq?dAUXCaD(fMohbEAiE6aaFg(!#Z=WTODcpz>1(-xP|1`M_zu<*zpuQ zpCsV<>o$<`CqhXZJXboaY&G!qm>_N87BVu@>gI5bp*;?ej3l)MM^B_L@w+#<=PM1} zejK+ysqH{t&)zjD(=t(=Ld5=)XD&-kL!yShMAQ642VV|cp*Caj0EZNA5xMinJjs+& zJ>dpM93v#X>8CSA6Cr{9lASCb6h=f|Ve#%4*OFe%bb=CSWAzNP1U@~Z|4z&7NOQfK z3`|y+#<(EtJ8aUEEN-)?szQ6i3Y;=C2(`V-@Jcr<#H4v9LMUNn$y^fe0YeXq5=j#_ zr1@;eXH6c#b?>UDMo*n$PNZG89zmXx1CV8m#eyQClu$F+R1>=>K=x;jM#CO^?MPYM zY}CH0(^n+dO1<#HT=HSge_hr@nFQ0Qgp!KZ^;2Zbov~_p-g1*Lp6UV4(^t=Pc!srd z_2Z260nBHA`C+OxlhiSQwdM)=nFCCul`(%i$ZTo4o^aA2 z+3Y6qgb@qUHRN>Y^{d5pg~(Fl_Ask3H@CX&ykLXHrR!c4JlR*jv7&ua#oh^568xrK zRZ$Wzd^#kwqser8kes)0*v5+${EQ{2X4Xf=z4JD zKuGWTv1oYP-6=jNSJuPh|K!xeeqWiPFSb6V+Z03=(Hv+jkhM{GN4Vqsa2KX~oj6BV z6`Ek^Zu0TdTYl_-j{44m0^*NLv)^I8k+VfbHp<_`lT4UnqPG)|RDXd72`5Ic!+*12 z@@dqVtf~>dXHb(-TU8sHSR%^|adVDF{SQPcO z$4>2c6I06$`JL+Qg|J#q4fmmm^${KB`M*{8O^?;ysmlKVhAxP*Nah%IJh)Q5#n)06 z;D%pH;i??XM(vLW3I^_a2I<>Ciy~4~J0gNV?p9E@c2~m1^Hu+IwbY9Q~N@CRs_v%9Fk0+AJQF%n1-krX_4a#>?f#swn-CE((6c^E#`a-*RblJXN%^IR3B~gT zABJ=C6zty1x;tj%$hxmh;fCr^W3pEepSinC*%mwRTC_JaqOT+Y)Fhr^DQh}Rw;L1| zn>9}q?kv7Pn=4*a#SD$o^MDq3ZCp}LPxqTtP2*vtm9DL$^1pfvl56n%YoUs7jErEQ zG*BA%i5<5`Nton0f_m-9vAkXH*uvM+4}9duR;DjuTm1~E<>Bp`-9b&?oe2Nlur}E_C)`|EGMOT|bR}>X5O7P&)!pf# zJHOz+P|mQQ6U%?}c0DcpAMFYIuNc?A^I~H9ztDpA{}plen6C9)JvPMj%ZWavmtZ{x zAMIa&mFYm48)oJ^P#ZNQ8%d%kRY9JlGg{$N_DQn#*Ee$L^ga;GU*_+?nd$G35B|}- zacq-^zN9(zFQUwp+sUAtP3jmt&;0i*!}Sx4Mv9`s%*d&Qf8R2ZZ5W+O9nVaM%sssS z`t8Kt)WrQ*{336Vd3O2!Sfl%tA|aS{V$d3m+OQ5?mY}rRw=9Qcw3ZuK z=gZmL8n)j!`O|agsFi}Y5khgli!Y^zt!1%>Hj5!#-CjsSL6BdctVM;6$EwhkdHsB% z2U~}b>};IDvlmV`jAC7N;r1G7m-`@|T zo->%qhxb z%He$fr2TnEB7HRIxHpOx9td-t&>fq4sosG%G_ zMcK`dDBpmuLaP4?d zPV(P?oF^n)Mv=sqcfwB|bgdVR7Z^|Oxmfg<-#^z5AGzN0#dbsg>12ly1)ttOX&F$` zrQX0y-Z)}>CS`=jCEQpCDJPg~I~|fK;Z>C7q_#XSZrLFj1U9n+aq_-N*|i$l3%;L8 zgE+6X%1~aFc~w3Sk}m5QGIdV5`B1Fl!LCi4!ju64L2E?}1`a=ykgkg;tv=;9Q3l60 zMc(($oL*1M=Wvz*UFbQTs;Gx%3-pv#56oY~O$CK=_irQz+Tl;$hABUZ8ltt8I5Qf1 zNy(%OcVI#rX%HKM8xzBu*pf@H5V_qH_?0v|~xLbzLnbGf+1M~tH2Tj5!c zl%^@29F?u;_pO!>knqQ>m=f-9M6OqFN+aM0@Qyy4LKd?Gk9OVp5@edMqTgiO07$s_ zLb8_>ap|hdN=5>@bw~8x+hBnFU&PSVN3RF(&I-;`xNa9cFnMeX1g#Trl@6$Kbxr6`1Li;5Yoq ziy>?}4*u_LU?Y;QtkZd^fN@rkLDvdK0Mi~h`Ffw{Slqmod~ zo~qv`R0Y@FQDje>HYtz^I*maO4;ZcD?NAUS@Dy|ytjFnk`;X^KFaYbVG5^)pTGvBG zIXA0Y(syj?2Kn#>Yv;8`75G)E^q&U?^po?}V_~fy6&j*dh$x&`pM#}!2em{ky{N@5r#G2x9Y9oiIvBozIUwuM(=RrN*f4@4z`0VgQfzGg;a(^Qo*DuPq{chy%L{J&s zG78<7)~SInN45?3Z$4QoHBxUjdb#@nN&GfHKGB*Mq#lV1Yw`II48BV-MHLOxSJtXB z-{MDi4k3h$2G%)hJ9un`6pTcLg*G8dUq~1P!6p(zjm+O1TWRH|G^qfSt$3#xm=p3lbyMRD99XmZ4 zx|$h}j>sGSJy4HY;rj_McfYNvUSm>(Xy+BrR*lgd)_6c`%?gXZhr`p=Sd3|z@n_-~chak1 ze8h&)`>WgS7W!$IUSs_h(gp~0MJsd6=!Jh4#O;>9lACK1>b9svs}DV4%T{e6aW-edVxLmYW!wot=fYn0i+|; z$z(x9TPeFi^G@f-VLgN+Hom_4gLR8-YKWUH?(Po~i_!0&ic`k*+)nWiSkRr%4jF(X zai52EJ*c<5kUwPmXUNwXo`3u2aX-+agsh!?cgx@o6Sp!~3_^>v^{^K3Fc|Z5jAFCE z1v*c;l-P-}mW7yE-E+&C6e;^0Q`s+KQo^a$CZ>Y}*QK(Xp7wmm{c+kT%~E#41xeGz zK7FMU64v@=ssvzFpfYA(&5D z#AUXMVMaev*maZ@{u!+nZ!Bktf|&W>TWbrE2tD(hK)-QPkMJO#=WBoX=S-*FRdH|za%_36u{xO0x%?OAwT8R zyBN}f`}nLL$RT}iza{-=>pL`Tn*A8s5Zzu}VMxjUVXLi?hN&=yS`3(Cxk`^~<`g!4 zmbC zX{J@alAZE%;$_kjHFIQUw-duH3t*-EcY?cS?LchU@c}!ZBJ??+r*BF|TlPS(tn8Hr z<6c8NY&T-I|JZuOn` z!kS7u3eECBV1GJIL2H&gl35@0*~7HQecG8u5V`jW-53#Wqh{v|euq8riRuv>ENq}> zBej}goIun0un}G|T@b0S-Im%cyyo$j4J*fRw@m3XY}n>(-mE>b*=P3$sjN3;;L`S; zMZehTrM^wzt?lp+5p@I8-tupft@czhv7wK!b0L;A?#-liFwJZ;RA0B{E7hV3*7?B8 zg=^wL?_QCly*V15Gk(`}v=mnc6`2O_>Sf?>zQ@6nXX#3g73dv$8~QG${)kRs4>Q#2 zfE@+v3=Vy|7p|0f_YUM!`qL{Z1oq$Ru?w+JqPo^MCWa~&Td*gtv1V_Z{1E3T3{@K1 zvUH2JxcJ^(NjnsLA7gVNNAKXrrPfd6PTHudYV_y8dB>@y&m*6EI`FTLzgCl=)|3Q3 zb*O0%l+oh8?7N0@Ce*st?Z>%s8X<*i5Te!99vA_udo{D+_~(lBq0 zV&Zl?eLob-wJ#Yx5|%QZgZmtOIwNqqY9xO6Ny`E^-IoueG=K}qc7&gw+n9Eb9*(?x zW1FP=v-)PM#!&54Gp)D*F-6f2{7o=$wSDwaS7W5@7Or@>A=J%ag6O(d8pLUlEp7r@ zAm?$e*%_(d4NQFuZzbZ#a3isQQf&$lBk9cl)LpFUQOpW3yzH%iqUb(z9H^(L#{9`3xQpG43Ojrd>8 zz4tqu-TN+_L_`uq5JXQ%bViBM2Z+EBx`CLU&w01o{r}lPI<6jfBbf#`4>bf_Sg#bb~#!+=*f<( zo?HE9DqPHqmB4WZ`RXpEjlznE?cj6-w7goOH|2@cc9^RIRe*Oc#V^*szekKRoKvKf z=o)3Z|5#U|a-BKJBZA~~Obq3gUQFU{dd6s1+#a7lk(}qM6Y%__Z=41>|NP|k5zj0| z%kEB9TESXKkhoJ71wRq+?w};w0KbVZMOa0Y?XMT#+*-Cr-dp3(x<-r(zTVOAfzMwi zWxPuSSvv_A;)U(QU*5hdlcUd*GXPB?LUUnN8vpn*>xjt8)u!G0FpZBo`Iusq?hV{z zXP1wc#g^#E|6AQ`KEvt3d+>3w+&>IpSe?6nBV6bud&M|dJ4A7L`N~>hz^UE=d=}B{ zf2~&2c-r!LJ))sG>my(mzXMq197+KpQh!lr=TuW8JxXR6KDof!>&ZP9_oApkoStox zeq;ZzDRrJGsFI?%dd7MxXrhT>N{_0*i$(fk-|ylf1U#(EcR>_(kt)7$P))hM#!*2x zIZ{51?=jmwd#;nGl6ZKo5xLH@v8r9amU*C#9NV}I1_@l|twO$?$|X$=71>7Mb%#f_ z8F62PZhrFHQE&m}D(DKhrm!Re?{WR#6ZW5Xtj%gN8qUR0moyYkNB(YCzdMe5z)Vww zHF$-O#H@X{oqLe2Z|DkzgkOyiYF}oGkl(;a=4iaBtCw}S_vu$wMIC@p3jRI^mqceO>Jg&uBLAvPBstZ^;{UGzM(a|ftl`KIc^3+V*2*|2h+E@Q4m zC1npeEULhDENRuXQ-R2VDgj-nIQT&Ge?N&}_kTOxSJBYZ-5NzmjAF4#I{P zF$`>Fy1HFc$~MPH!P8;y&stRi>E8qU8~0Fkz2bsFSf^h&Z6NYcJ`uw27pH85b1`Y@H@q&uh*`l3_fC2^0>vqe*D^;0v@kAX#<1LMD z>H){HKlIByx&HJyILBq)oQsp}-~7?#UHshJs65~qwj*mpK0Wp|9dV$~8;&w-MV4|LcT3ocMIi&yNU$Yk(>)t(scGg8nzOWQ0DQCwVoW zARNIT>-;Y#=rx7^0hS>ZD9bS>ZC)pYPIF~9QyTH3ig!wARSR&$bX!OqnD`gXKBisQ zU#*V#HCn$)_ctD~#Q+DTKH%8L3CL?4q;FWkabXhEpb8Arh;H-Y@ONAwm6h^4LS}Ft!Z@USo zQ0g~BA%0v+MxL}!0F$t2A?Z!SNE^-+E%BK0>ofI>pyMZ_wFjb^w}0|>&ku_vk|J{l z+&{@;MS0RFPO3u%4gm$t(}+>ba9ZJV+$T7D73K(}cb3dIvL@YTrQ?w}Y-zI-hj+wU z#ot!I{IQ44#fbM%NTIJjAI{L1mNyWTL-@6y65n=hE7=T__2Q7}#g53W-){Y4+@Vn2 z-ssjU6Ozprx7h^OoPrT~{ zf>HfQDDCAs>L2;KTfYCob#c7(6EE^__*x##ARK=J#mlCP z=U7Z}z5haS)-)bte8po`&A#TfeKO4k;JbCUxZAEI%b$@IAl(kLo>yQM)i~1df6dkW zs#PxZ>ZnTHx}SLGv1%g* zt$KXm(Hi;sv+UZG$2Y=knrZI(yG2Lrl&i+8_TMhetPu{So2jOkvtS5-Rjl*r4fNRl zvjsgCGg_(lQD2`MIx#r)Ydz%{q?8JRe7nNOd9!l}KPEE(o6lB&vMN%-CnqeG9Jnth z{Wd+X{>XVC)m|JKsJoXM*rpYG!UA(-2r7%!HKfC$x415otBTzWwuUa-yLioF5+{qb zEhYe`3td#(6^h1ueG3l4@5eZh6`VgMMkd$7f!u=}it*gJBm*E&sTbqcg|L;D+n!NrB6+ZkPYrYl>gXru3!Qhl#4h z{tKl;QNXqVwf&lr3xa33zi}ZZcFRpsukP*che?TKtCb9!=PD-i3(s}JqRKYmxFgPW zsiOt6LG!2q&!MPtyBT4%HV>w+)bU87q(_A6+3t8uanb8;rY-WXdk0a_l!H&W|%(G6*UR z9LG;9s|VRi7~HUVc)h}!g*U7H(cS~^M92o$A2^FW>oO@$o(YB1d7p*^nJt}njyhc)S&$D~$!PO0r*j2F1u zXB#Q_EYoa@vbPkw4bHCa7*B}xoD5Z>;?3jZZnc{T4ZdK_5*o@mXIu(K$|}0wR~V6Y4U!xyZBKW-ngM*yeF)TevOPA#iHFjed(Yg_DWy<7j+;P3S6_38Djqa3m0 z({A< z$0NV~O6o~ia3vDd1J~X2ifCwZ$R1Qf9!`lJF31l#x;hl2)GT^M0cd8qWnol^&9BI2 z%=y}{Lru57LT`9wIkYhWSu8sFa((qQAo9=Co@PcelT>A{9|=HYbMreQC3(OtoG z@KN)fmmL=acbW>!fZ+U5U;Q@tx#fMYwFIUQL*Q(LpZjKy>WABMF-oENpl;N4@{(AC zs@6%J>cWYJ_IZyILtOmlfMxoq8Up* zK%hwzmSFNP~BXao0V+#~Ex-xuu8v)00LyRiGua0qJ+8JRWU6ByRLSj zt-f1P2{w5N_r0^ckr~}=OsQ5axsafAvzmO}Q^s3|&JQ`6wcZNO8iW_V81j5~GF3sG zL<8q5P2oi1IqQyz(N|ubyB6wpWl3~{{1g^mp?ns5vOuoiPrex^s6sv z`$9cRt-9Me=fCEhRe4e^SN{{*X;FMKyk5(NKTqVGfc0aC{vXCRuc|5bR9SNy0ZCFF zVq)%Wc=M3#mw;?)Zl8t)Sz%@@bb0WqzZkIQW}YK`cw6BLlF%k|Z8jpEihn79B&1~F zIXhx)h~S8l9Un1xmBGXkknu1u6USRnS?a);&IGU5`|+|Ww>plyt_9fQ)j+M!6%W#R zih_MIV^Zc$!}thMT~_$%vamC`qpe=mkY7`E?2$XX0m@Z5Eg8l(pAHSAEQ)BQsSj<8 zA(7Xo9t|Q^V&BWyn=vaXP5V#YA7lyNT_BZ%X=0mT2ntye6)mP8*HH<>(t;TGSt+Z# zTWcCPmo3{!*zTu6r;cE%=XAv#t7<+XT=OSlIAM?MybFFI;e- z4PHD2WixPQ*u~a?mlAxWcJpeg%N)AG!PN$7-7(**UI z6nRCP{N>q0%{4Ef-qMm2+1z0oz|x1vwl4`)j~pQWb{hfus5z0@+B;gPM-L;M+K z0r}VAzREG;-RgJYan;I6hhC}rjkZ^Vl~q!V%L29 zYa!Lz_*DA}_x_1ygdzJg=~KzBDPk$e%*4mBt`^GKiYtv%+%o+8CkV;ntC}7wCAC>l z=S6{6=-^BUgRLS}1kze9DG;?f`GmsI-1Jw*QLKpJFb6&|X*hM*hGIbqmKwbhTvtoI z#*6|0Ly6+@kY8EF=#Nbh3L~N> zt>qqLdQ8cOw~}O^^!f&?VZmQHg09}TxFrEH9qS{X>V`v%v3**0y%*j0pnCC@DDbR0 z9c#ohhz`f6Je!xARPkSIrvJZ2FB9u#e$Zcjlb6{G9ZV~a2PTB-N#e9?{C+}}7xu%o zf9XoXL2sP9Xa6@|>OV+m_)+ud)lZ*LYO|ulgcs+uyAMn-bXHToLnk`xd2?LREGt1wSzD)rDmtOl_r(scPulAeq3 zX3^3J(M+HqiI)(yITFarfK(A=Hq~bUO@}E?^NzX*_8K^tl+k4~N|T^7FoFnaYCr=E zLWz29a>A0}BAqvlhi@L1xEI$Q_N_m!e1fzSI5x|)S9h^c3>aR<0)K}=>OI|Y9l zgJ^luhXW&5(5i0RVFtsNzXYuy=6!T`PVgu6WB8wK0WljlDg2 zsdR2L*}#&@$(uU4WGpis|L)B#7s^zHujwj2#-FGpiYIGgh`q*LWVe+q_+FAqBvj2+ zo{KGCB#iAKdYA&AGUspf!E$(4phWhy@SGhWCO|7g%e`6p`2F=BbIV?T=q(@hU$79P zr4dE1n_u{#J~S-jCy%NmonCdaU)N4D?;<)sq8h|v*L=;T)18d8ZW}$ZueVh>f@Kv9 z6uPiw0f@XS8X~UvdK@RJaubj)msx1HeNnnYydfgZhTLI~r7yi@mf6c{bi+3QZo>JK zC8-G*AN|2$d!v5ZNvot>)3KfXho#uM)v1hu{pbD%ABIm$_XFl8<9rHG_pc@8Jld)T z?;vLR55%PZg&2Pr5fy1|=@>cC;#sf2Fz|!uAzKA{#tJ(7r2+YbD%!nB+^?v|!DW?0 zfYJ*RUTf`58SEZ~Wto$~w}^Ln8A@R{$As1C&rSF09kLX7Rx=MIrn<||lAXg(x?qq( zLIjFzbd?5eYO+u9oJ+=pue~4n%DM#MAjW6PlB%7qfs}l!c?_ScD~Oi3Kl%m=ANc7(wpZ9d%?<=4jN5bQS)rnbN7!~vsV=cJNRgd z4dIOEFR^nufH1OedGd-KzM^WrK`Sl%Qb7pgbn^EXRthnA3dN)?-s?+x)JeP|*_si* z4}igzDi;NN@5f72q(zUuDG3LfJQ5xF`rf3AhgMYv=ki#so*hubC9;025R)DU;9^#>M_QCQTBd>51dH22oD)c|g26P#2&^cNU0 zQBr8Px-+4P)0%vJevxoG9U4GyZj#GLF{&lUnfZ%Pt`?WVBzE)R#I zZ6iZ$aGV^DMN?jGoxg}0Ce#JRLc|~DU+07P%F~oGhleOGEo*x{d@i{H5;9EN7szSf&%-acUb|>1eRnn+j9)}cwh=J< zg3Iv94fb1bg!|UQ{P)iOa@j!@tvHuPxMnKlIUP6MA{za<);-@}w^;nK6`;0yMt2wi z1!NWPzo@DKC(JCLMeuyX=YqaAU2F9`wC1B~>@U;?>dgXEw~QWiXC*`VOw|iQf+kI0 zHaMb^(1h;obit2~o756T%J)5y_Tk`ufHWj>mncIJ5!? zaKm{vuG#r_BO+l9^l>b4h)zVQ?n%Pz+DscmaH)w}H!qD=cLhKh@5cqLmDW1kRzodC z$Z8z7$Sd1N#Ued_M}^81;zuE)FhDa=!9uoZ{1vUQdPb_bW|7lz>~7&?|| zn;Ymk%9R)1ywL2zqojh2?7@(coG)BiX|G-5#eWgn{GQfS`;v}&4~~kFPXdb$uIqR` zSg&@~nYF0ef9*Cn4lB0vpH8z+&6DP>Nan0{-$~9oTXXslQOa66+I7)?imEWXOtM!P zY?j^SgNqwL^9U45)|&=S6)Bm2f!aQ{%s%qLoL2*e&S3Zq?F(+><;+5TAJ0hXr_4fc zF|fm8S)Q8{vl;)69o@n+%f-u?Xptt{YhuNO=t?4MFdw(XoWAeE#c2q(?kb6Cc70qN zbX|Pq8al$2m=eN1<|Wfz0Sh{B3cZc5^u7wdQ~i~0+enJ^r#JI7fVOE=q=Mhy&AJtr zxVEDFS_aw2m1R#2%A4;{=+m1;xlfZ5bF#sUwE)4ee!ol+H<=S!RaONH(&pi}*$WxZ z0)fhRsde;co-S2Fgj!+Wo*qP0ncsN<3#?#ljJ-ZRjX;jU>h^bbQxsAysdVGXTnngL z3>HhdpzL&7KYFquBVy3oChl{#d*A*w!9rId)uD%hfN9cD!+1jA>w5 z&mXc!7ha1-GiM$06lNJoJqb-$^6ezNXUuod{%_Zh?#D}0v6v>YyKvyAte@`k631DW{Dar3=uLey za90;4p9IXz<=*?ccn?k(f{5Cxa;RjxmtHOLpJc9nX@P1D$nUcW&|Nu(gS&^uwmgtW z{I1W)wrz{;zbj0GM_;?N$80msmVlEmGm}-qP5mVIRE6?vj4=#5>SQ9yCLQ;_QsJ2V z+j4{;dU@Hsp00E5F1YzQfv?iNZgQRC>|&hRzrZ!Qp|VzoCrK!d{vEKwuAj!~>tM!X zN7sb=_tYSU|D%n{fB%6K-3{*l^^=(U?=1f3 zbJf%T-@THruYJuC4RZDlV{xB_R4-bbd~ZIwKFQ%-aOJ9LKXcD@Uy$8ed*R8>3XQis zCk_%(r0-h~d_SC&u~&XJ?S=Mo*v=`@UpzcV`LGgE-yVHmByM@#+!zcU+S3o;O?F|+ z_HuGtD-U(6ES?HW!Y8(zOv{;z)91QzNw9$pX8(9Ov}-)D_tdsKtR|F%NC9~ zUL*EiTi1B4qX6`i1&AIICEQ!nW*+I%S0xJ^Rkohg{>U_#j!Rvwrto$jknZUrT)(&P zRJot2{GufN?8Pakwp%J#_LPUgNH z0rR?F>p2zVCv!tUn-TKqtpJrK2oCPP(lEa?1uM}tKJ7BjHE^MdD6AwqC_R=o11k# zTyPLab}=~jj$8jeO^SQoK|lZ(SX=1?``#tx*VkslU9@W-#fh7gW<&$DF&Hlg{NR&^ z6Nah;6u`PKXHWdi@hI^ZFgT*u89z~h2uN;v<^;vjE^MR z$>C?$);Jt>a}M0FcwyY*0B2)cU32oo_B=q3=XMiR(Wgy5u-Sh8F$JyhHsmce4g4p~ zp&wtc-pNya+Kl28ZR;>wEc*< z347U15^|sXVWM3AmL52|$H7#APs0B{>{7;Wf8@e+U!cpt2CSE{UkVW7I! zvg6x=cYsg2urAI|f|8$=-uoXW5N2|>BunHDzT>mcYd{jyg(2*8+kuBgPF-eOb5^`y z)7nLe8AJQD>Cl-EHpP{5ogC9LO&>mt)9+f)P($#u4YBzo-BE;L!dhYH?YbZJrNpRA zui?-O@28918jOZ^cCT!|bA#_FFx~K_w26k%%UOd`tK49E_nz)xhPp5r{c(k~t)*~E zZRM9g8%fQjnE{@MZ(iR9_cTkj!U9^d4d*xkw&l^Y$-lGLQ!h>8Jx+>MD>(=LvtF+TI|kp^ zib~EA4V7aauT>HKj{NovO)}dtEvL_NY^@T@9cSw>p6@t75oSx&^9gB?)SUjlc7Hqo zl|=nG>GeN5StFl&drn#OS0k{Zu`~^eB}d74TDq>CmY`lx{k%0KyaeyQ8^iAf`i;Nfi=d`-yX^N*d?==qm%GX2OXu)w_tQYq1Uh&U!@AKa>(boL$~&uh}VK*(U6NGXr)1ePsXh=5mawPj?`(#tSR8C(dxt+ zozVb*s~&C#XE*diCg}DX{q-yoP56JmWp7xvkCJctX`|=X2?;tdT~tRqOMD-hQYsiP zNyLuS&`M*O8&nHy{;7USS^OlHQZ7s^XiPf;UNiJ7SIN)KfRW#R zqjv`(g!!PqUl0{Zl8_U9_Q zE2;5TH=(L^R5xVj{WU$+3!YaY!1<&80gn{0Nb;Y=drputro9kko#2Z~nC?6|;OU-Q z1kvnqCJ%6zY^YY~LN$6;Wa*@Jpe2y)O04Ldan_5t0&QC_ZsoW?V7<`-;D~q$(SWpQ*VBg{U zSox71NiVLU=+twgvlcdCmP1!e4r4=mm zp&A1Y3Bb1kK#rFkz0IQ`Q=J8w)lMpD6EdqE&+MZSy|yYl48iD0b`ICxPX5K)YXA|;cnfay;ba242b`t3XHDzV4VXr$%Hg_;*ZnHvnXE?Hx~N5Kpg2bQ$TnnKkn-6-odhx)_gstVNg2PG28@E`G&2Z9EuT_=Uwa znwDFi&#r4KNE%8zIUg9zPTJW1dp={-+!i#I+bsGV!6!lAq$w7?v{=Nx;SEV_IZewV zx+_r(f|;zWWmpLB4q5&!yo}xhIjl1t!S+ShPrHut*+u>)uj1~HF1hSb_+1(}pY(MW zJ>K2+Bl?|7b+8j-#8WTmHbU!sQ-nCWf81oedM}0V_WniX!E*52`RYWBgn1+RZdp7ZN&4!n=ZX;Ia4ENco!_ByYgAjo(#*M`_YJ(>AjUh4wH za>r#S^(%6(c*>?LUHJKHD*NdP-oW}E{jinTGaU zD><8c%qPBEF}!6y)3=+ts}>oLqe(()7E5F!k~MpO6El%3w!nmU>?Y1+I3+V@y>F~Q z&0k^_ie}dJ!ppcY=0dx7VuNtiz9dB-Y|PVK-v%)y(ymkca~kHzja0ZEdao?p9Ywej zs*7ESbs~%HHBcO`WqDC?9+GZv;OYh8(Q%_pnVz3L)T5~pkzh0gDVm^tnpQbNPUauR zq||Cc9<8BoY`gDZrn2U38`cjw8U1z5Rrcj&?5=QR4gLzl*b$3?yk{3fYkiz&f~%Mn zKALIAy&tg2vJL#IF9@q0uJQxAi=Lg4^>BXQ(Af?wokjf6FCgSzu(=VM6?FAVaO*!| z#`UTQe&e1TU%TF6hDJWC;)Zg#dzn}0{he1*s9ZR1EFK zpo639zUXKTo6(@KaXVV{q*eTpX-ysL3xktS;epV=K5=AotY|1%>su^*1^lwT6FqWXa*nTjWP;x{A5$Fi2Qx7 z#$oZB#v!tqrM#9j!VocOyJZ(a_iBMHde8p;nLEc(`X|k!DCzC2wBWu)wS@1#hEQ48 zTw@f0pv(^!>|4q6mbUh60J|aU*!Kr*B+%z@DPQ`Taszun?pt0CbAawAcir=P8{@vL z^sp)8LQS`(6vY}bw$XPIN#rlx1m%OIv#T4Q+dpTpy+Fx#1gr;J;YWF~9eDTvU4qc# zT>D`A;rHDhApB&bqd;pbxX+nHG2A^A&q`^EjP&Mi%G+iJL) zXHCEvdB~y}ee$kO7E*0mp3Vw7-extBjQ(PrMDx|oBk*y_nk1Egmk8*)OFvfeR`iFr zvlK!Vx#H4~Hlr!!s;-InznmCR=33_#$kXz1_P}Ru+^uz|Ae<)bfD4A!OkjmXM&MGf>%D`x^ln<--OHF~PNJ|BJ1OC_s0#$9I3#0&t1?3pKG_1g)LMslRK zFaAK2Hcp$5?xnOieDzwtF%-7UXU$W}QR)6{dUUm8D7+g^pB~O{m*Zr*$a!&-Q)07} zv*uz>kC3XpUVe6A@Vamg83j7Py%TvKC%F>+o;j6Wz_2Yfd>_(h=xP#CIQkLGMr-po zvqp?Dtt3+=_r@y~$w9F0oAwC{%Ld$a&-}2CDdo8^^gVr?!g#n{$TCdg8l2&( zChFVLFZ|h+zGeG>W3bLKVAR2e#GiMJKlvm{ z%}mS0pD29Bwz~AcWzUy;uoFv`B{U+ zPZ5!qs-omM8V9SL0B4b_$uYa>d^<~PiCr7&)uq;pX#IQP2P$1XdiSR0^N~&vmUi8> zRBkvrp@amfU&S1M?mz=h*ggsD7`l#9;WU2s`#beS#enwUw~fLo$5(~E1O3_>xqDMr z(g)^6y%`Eq)cz$k6p;`P%(0&A{F1SDdmrbs-@lO0UcbEOKHHKADtKcDPT>v=FO3RjxHy!0(c9;E z;=XUQ`fHBF)KL_|1Km{UV+!%dL!+RSFILBstw(I8cYG+rS zzrC38^G5#_OH;TVEzjvo|-3tb0c3 zA(X>d`mxo03Ls9O6nDn?k{x~&>@v_3Ny9tu)Vh{5VHCfUP(2*vlzC+m;ME@NZc(pg z+F`3xOco{)Cru8R!PC7_%GuzQKR3g_*{N=|i|+Wf`oos5UOQNNX&_YiyY_VQgt$)3 zvm8tbLBi?&Cm24P(R`|R_q_S~+eqRNXSvQfpr7#V7JN&|S@y$B=S7w8Q3w0RBsp!f z^eB183;z_2KPElIli&0g#}K6{#qY;7VB#+fd>kA8^r>?=q=*3k9EN+@Bq?uw0S2l` z7mpFDqBdy7v~kx9ez4^FLS%q7y|(viOlY8-Yt7w-V51Ng4sG}4#7cfA59uhp8bevAmb!${H-!e2WFmit0bH(n(^qg?bH!!5LAahJdRgI5 zo&bm`-UQ2{_aU*Jp#`MmymaUCB?PyBY9Of_scng!b$yI*n^{hO{&O9-?k9{~vl?(! zthMP@Rvr6vC|T~4iWLU2+oEzKgqn{}(U$aa6k^@ViTRhO<(OUT#a2LC0m8W+@OP`$ zwa#U-#{#qAy7bqy0tgIlshBfA93ZA>x>d8Ig&7}qwviD9Ni#ryDBZluYPg<-QOD1u zfeU}5r7UMNMvd#Lw#=w@^~U)MxGb}d<^6O_M63Z()36G3)e9%s&pg84t2ss2^Hg!T}9Z!@FJG0G)zZCJ5d$d6bm&RQohUC zjx|cP9k6LR?1B0)MgcbQyuteEQmRfNi>*UObiliuuy)7cN`zuEXU$aKT%KYQ34Je! zTPmf%a&O`308haS;-d1v$YT$=z=r!!$5(Ztn(sf@T_yQ)J`{?yD=^4sp;b%a_B}8C z$3>`#I8aL4IMEzO@tWFKgz$q+Uy)g?2YJ>r7t1|lDgk~gbK^p2UwQWpr93L0`(p)O zXIsu{*%Zep6@cuKxu&@VkKi9>0(%-u$X)uLCXvPBPRXFJzar~q5VRC{B8s%97lA3& zz2kTBv%>>K#YL`DyBvcPs3ejbcRn6~bf8~C`bl6?Cs&K*-$rrnIhiX-JcPt!tD1K` zw>RS$vzoO!qj$@3G%%0JK9cKsX+pB6NiLqzrcQW&MKeRhg;Y*I(3TWjCcxSzngXrd zt7ty3sqKaFPx3UlA#oc^b$t=zCE=y#Z-sA_K|~MP2rY+Gl0@&^vN6St>>Y9Dj~H!yXB(O^D(Qs$+Gq0==AOs zukRSMg|ga&j;1fV^6nkKDRP7`=9%kH>_x&V`CwDmB&&ZEU5#lzA&>l41r6P(~wi`1jBE9{o5cvD4*w@(7AS{dS1Xp+OWc7BsAH__-UZ4zO)tw zZ94h@aO5vUR z>CU+m&O1iG&+OP^x%l3YeDW>d+Hak>qOkC%bIl4E52izqlD$i3p#(<%Z5W~vI<)%z z@yZ5Q<$nOFS?zVKogxw09Y_}VWdL^9F0(Jo#O$yOMpV&nD%6o?BQDyJ9mBR?)Wz*Y1gDqV&+ebVndgwH!0&o{8^7Wp) zl%!^3cu$DF+We>0B+wW(zZOt+5%zTLZGI8h@(jBzey3IOwS258dfpRgmx=Xok78UP zoGol3bPrh`7>npT(}|1lDo?Ce`)v__*sM3rDzH;j$WaR%wX?bIFZwdD_DrLv$*Uck z4DT8IT0n%mYBRaI*^k{iGJ%y?99mpt9S^;jU+ZJEQ8?l`F_dBLlQ$`mlNeBoEQQPq zB9jArTb@^|-jb z??Y)?7D;RSC8Dc?Z<}f*uuei3{hN#8{i=ZbOZ1=DsFFzu?TBI0G`|Ic!BEh2-ks{X zx8J{-&~cX{*?yU#pd(y6c9)k>`RRa2_)5vZL`mc!tQ2oe+r6K|WzWaP?z6FqbFzsr zv&s1rrRK1@$MG!Zor98&Z&a%Vqc|Q|$hvkZ-d&-?*F!!V2h^W>CRO(|goyT;dW+qE z5&Q=qm?!e%&1Z@s(gsLB9Wl{h5uZJ-1?Xk^g99?h;CcG0Fe*tSgHNU1UzFvW={Lf4>4tftKBtueu` zV6<_;@(RMrS+{8`ux2~|N>1%-{w*`Y&4d}Qb?){80}*TgEte$w{yNX{Yc1I0|BE1< zKjAV~H*7h5jANg_sV@{!ZssQBJh^CX565TR zIuOCDc9mV0*P7Fm5A~|mPTLe~LxjK?aQx$CGckO*xn>#JP8-}+x*8=G-d*NdCf97B>gFtEi4keN~|vxYsLc) zN8ilTp_{ABu2o}>YuKorbAQ-^gsz-4GQCDQ=qYerqEz&u+cEtmi6}oEYP;@^D*+0; zA^McB$I;^|L`i?HSXgR2y(Tj-2cNUfK>*vtyK1$MpC&1KV&}q>>3PFexuqmsF`Z%K zyfB;E?;xffj*07*-8U(S9!6(7&lk3NrMh4XE|W0;;k~a6GT>>=&}O1KWuFv>H4)*- zU9kURSv+}dL{Fr1{DW|1CvV32XWRG9K*iNYyeaPW@sgomx2{Yp@7gF$k#mDn$_*{_ z4AC&>4nmqMhaLbs{WmC{`_=Rwt=mQ=?W9XEG!tA`3e54(Tr&47!ffHI>e1DXs(v^) zHzE)?=S!owGjJ#7_d@N={PlTpG;hu3Pf57B0hqGS&x(VY9u4@mljS&Zr=|VQ%M7VC zl6M?`W5?zAp!|iLqia{5NEL&C0rV)=#`5>ujc0mLog&$@H7Q6OCI!ACfrq&MuKN!D zaSd38+v4~9GLOIGWTi|NQzHAJl;X_;B>&FWf*MQ(K~CC9anFM$=-ATko=#e0 z$Q9R>jE_C(vG8J;ieRC(vjK@3p)Ll^;As zv_2HOb&V#kxY2``-)#_PJr-EBnuiW*tjOACw4BWj=K%XDVD?eY_2a)9_?O}{LrynV zzH9aal@qCJh0G=+@IiZurd7_K|9FT8b0`snp0 zxZx|6rBwr4-I29oV`XG>d0{9}?DgoIt3TnU@Ou2BWktiDc&O~hUrQzSO|h<7T@52E zYOMnX@ic3KBl1=WA!f}FvC{-JyF$i?g9*T#FtXaJt2npbI{vaAhm%tik;;Mp81|

LTF=9dTzTv?MX4m0aau}CG4wZyOFb;N=Di2 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 Q5&@Z=JbR+(nA5HQ0@%qMl>h($ literal 0 HcmV?d00001 From 812daa281d2d1cc274940f16778b0ca8e333e417 Mon Sep 17 00:00:00 2001 From: Garrett Beatty Date: Mon, 10 Feb 2025 10:40:28 -0500 Subject: [PATCH 7/9] fix readme file ref --- .../src/Amazon.Lambda.TestTool/Amazon.Lambda.TestTool.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Amazon.Lambda.TestTool.csproj b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Amazon.Lambda.TestTool.csproj index 4eb39b5e5..8349ab09e 100644 --- a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Amazon.Lambda.TestTool.csproj +++ b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Amazon.Lambda.TestTool.csproj @@ -72,6 +72,6 @@ - + From daaec49ca898b4b8f74fea9dd75bad9e2216ee3b Mon Sep 17 00:00:00 2001 From: Garrett Beatty Date: Tue, 18 Feb 2025 11:10:10 -0500 Subject: [PATCH 8/9] PR comments --- Tools/LambdaTestTool-v2/README.md | 58 ++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/Tools/LambdaTestTool-v2/README.md b/Tools/LambdaTestTool-v2/README.md index dbdca3fae..9537c02bc 100644 --- a/Tools/LambdaTestTool-v2/README.md +++ b/Tools/LambdaTestTool-v2/README.md @@ -11,11 +11,11 @@ The AWS Lambda Test Tool provides local testing capabilities for .NET Lambda fun ## Comparison with Previous Test Tool -The AWS Lambda Test Tool is an evolution of the previous AWS .NET Mock Lambda Test Tool, with several key improvements: +The AWS Lambda Test Tool is an evolution of the previous [AWS .NET Mock Lambda Test Tool](https://github.com/aws/aws-lambda-dotnet/tree/master/Tools/LambdaTestTool), with several key improvements: ### New Features - **API Gateway Emulation**: Direct support for testing API Gateway integrations locally -- New flow for loading Lambda functions that mimic's closer to the Lambda service. This solves many of the issues with the older tool when it came to loading dependencies. +- Updated to use a new flow for loading Lambda functions that mimics closer to the Lambda service. This solves many of the issues with the older tool when it came to loading dependencies. - Ability to have multiple Lambda functions use the same instance of the test tool. - UI refresh - [Support for integration with .NET Aspire](https://github.com/aws/integrations-on-dotnet-aspire-for-aws/issues/17) @@ -26,6 +26,7 @@ The AWS Lambda Test Tool is an evolution of the previous AWS .NET Mock Lambda Te - [Comparison with Previous Test Tool](#comparison-with-previous-test-tool) - [New Features](#new-features) - [Getting help](#getting-help) +- [.NET Aspire integration](#net-aspire-integration) - [Installing](#installing) - [Running the Test Tool](#running-the-test-tool) - [Lambda Emulator Mode](#lambda-emulator-mode) @@ -38,24 +39,24 @@ The AWS Lambda Test Tool is an evolution of the previous AWS .NET Mock Lambda Te - [Multiple Routes Configuration](#multiple-routes-configuration) - [Example Lambda Function Setup](#example-lambda-function-setup) - [1. Lambda Function Code](#1-lambda-function-code) - - [2. Configuration Files](#2-configuration-files) - - [3. AWS_LAMBDA_RUNTIME_API](#3-aws_lambda_runtime_api) - - [4. API Gateway Configuration](#4-api-gateway-configuration) - - [5. Testing the Function](#5-testing-the-function) - + - [Option 1: Using Top-Level Statements](#option-1-using-top-level-statements) + - [Option 2: Using Class Library](#option-2-using-class-library) + - [2. AWS_LAMBDA_RUNTIME_API](#2-aws_lambda_runtime_api) + - [3. API Gateway Configuration](#3-api-gateway-configuration) + - [4. Testing the Function](#4-testing-the-function) ## Getting help This tool is currently in preview and there are some known limitations. For questions and problems please open a GitHub issue in this repository. ## .NET Aspire integration -The easiest way to get started using the features of the new test tool is with .NET Aspire. The integration takes care of installing the tool and provides .NET Aspire extension methods for configuring your Lambda functions and API Gateway emulator in the .NET Aspire AppHost. It avoids all steps list below for installing the tooling and setting up environment variables. +The easiest way to get started using the features of the new test tool is with .NET Aspire. The integration takes care of installing the tool and provides .NET Aspire extension methods for configuring your Lambda functions and API Gateway emulator in the .NET Aspire AppHost. It avoids all of the steps list below for installing the tooling and setting up environment variables. Check out the following tracker issue for information on the .NET Aspire integration and steps for getting started. https://github.com/aws/integrations-on-dotnet-aspire-for-aws/issues/17 ## Installing -The tool is distributed as .NET Global Tools via the NuGet packages. To install the tool execute the following command: +The tool is distributed as .NET Global Tool. To install the tool execute the following command: ``` dotnet tool install -g amazon.lambda.testtool --prerelease @@ -78,7 +79,7 @@ dotnet lambda-test-tool start --lambda-emulator-port 5050 ``` ### API Gateway Emulator Mode -Use this mode when you want to test Lambda functions through API Gateway endpoints. This mode requires additional configuration through environment variables. +Use this mode when you want to test Lambda functions through API Gateway endpoints. **Note: Running this mode by itself will not work, you will still need have the lambda runtime client running elsewhere and reference it in the `Endpoint` parameter in the `APIGATEWAY_EMULATOR_ROUTE_CONFIG` env varible (see below [Required Configuration](#required-configuration))** Api gateway mode requires additional configuration through environment variables. ``` # Start API Gateway emulator on port 5051 in REST mode @@ -92,21 +93,27 @@ When running via command line, you must set the environment variable for API Gat Linux/macOS: ```bash -export APIGATEWAY_EMULATOR_ROUTE_CONFIG='{"LambdaResourceName":"AddLambdaFunction","HttpMethod":"Get","Path":"/add/{x}/{y}"}' +export APIGATEWAY_EMULATOR_ROUTE_CONFIG='{"LambdaResourceName":"AddLambdaFunction","HttpMethod":"Get","Path":"/add/{x}/{y}","Endpoint":"{LAMBDA_RUNTIME_API}"}' + ``` Windows (Command Prompt): ``` -set APIGATEWAY_EMULATOR_ROUTE_CONFIG={"LambdaResourceName":"AddLambdaFunction","HttpMethod":"Get","Path":"/add/{x}/{y}"} +set APIGATEWAY_EMULATOR_ROUTE_CONFIG={"LambdaResourceName":"AddLambdaFunction","HttpMethod":"Get","Path":"/add/{x}/{y}","Endpoint":"{LAMBDA_RUNTIME_API}"} + ``` Windows (PowerShell): ``` -$env:APIGATEWAY_EMULATOR_ROUTE_CONFIG='{"LambdaResourceName":"AddLambdaFunction","HttpMethod":"Get","Path":"/add/{x}/{y}"}' +$env:APIGATEWAY_EMULATOR_ROUTE_CONFIG='{"LambdaResourceName":"AddLambdaFunction","HttpMethod":"Get","Path":"/add/{x}/{y}","Endpoint":"{LAMBDA_RUNTIME_API}"}' + ``` +Replace `{LAMBDA_RUNTIME_API}` with your Lambda runtime API endpoint (e.g., "http://localhost:5050/AddLambdaFunction" or the endpoint specified in your `AWS_LAMBDA_RUNTIME_API` environment variable). + + ### Combined Mode Use this mode when you want to run both Lambda and API Gateway emulators simultaneously. @@ -231,7 +238,7 @@ Configure the Lambda function to use the test tool: "LambdaRuntimeClient_FunctionHandler": { "workingDirectory": ".\\bin\\$(Configuration)\\net8.0", "commandName": "Executable", - "commandLineArgs": "exec --depsfile ./MyLambdaFunction.deps.json --runtimeconfig ./MyLambdaFunction.runtimeconfig.json %USERPROFILE%/.dotnet/tools/.store/amazon.lambda.testtool/0.0.2-preview/amazon.lambda.testtool/0.0.2-preview/content/Amazon.Lambda.RuntimeSupport/net8.0/Amazon.Lambda.RuntimeSupport.dll MyLambdaFunction::MyLambdaFunction.Function::Add", + "commandLineArgs": "exec --depsfile ./MyLambdaFunction.deps.json --runtimeconfig ./MyLambdaFunction.runtimeconfig.json %USERPROFILE%/.dotnet/tools/.store/amazon.lambda.testtool/{TEST_TOOL_VERSION}/amazon.lambda.testtool/{TEST_TOOL_VERSION}/content/Amazon.Lambda.RuntimeSupport/{TARGET_FRAMEWORK}/Amazon.Lambda.RuntimeSupport.dll MyLambdaFunction::MyLambdaFunction.Function::Add", "executablePath": "dotnet", "environmentVariables": { "AWS_LAMBDA_RUNTIME_API": "localhost:5050/AddLambdaFunction" @@ -243,11 +250,22 @@ Configure the Lambda function to use the test tool: There are three variables you may need to replace: -1. The test tool version `0.0.2-preview` in the above path to the `Amazon.Lambda.RuntimeSupport.dll` should be updated to the current test tool version. -2. The .net version `net8.0` should be the same version that your lambda project is using. -3. The function hanadler `MyLambdaFunction::MyLambdaFunction.Function::Add` needs to be in the format of `::.::` +There are three variables you need to update in the launch settings: + +1. `{TEST_TOOL_VERSION}` - Replace with the current Amazon.Lambda.TestTool version (e.g., `0.0.2-preview` in the example above) + - This appears in the path: `.store/amazon.lambda.testtool/{TEST_TOOL_VERSION}/amazon.lambda.testtool/{TEST_TOOL_VERSION}/content/` + +2. `{TARGET_FRAMEWORK}` - Replace with your Lambda project's target framework version (e.g., `net8.0` in the example above) + - This appears in two places: + - The working directory: `.\\bin\\$(Configuration)\\{TARGET_FRAMEWORK}` + - The runtime support DLL path: `Amazon.Lambda.RuntimeSupport/{TARGET_FRAMEWORK}/Amazon.Lambda.RuntimeSupport.dll` + +3. `{FUNCTION_HANDLER}` - Replace with your function's handler using the format: `::.::` + - Example: `MyLambdaFunction::MyLambdaFunction.Function::Add` + + -3. ### AWS_LAMBDA_RUNTIME_API +### 2. AWS_LAMBDA_RUNTIME_API The `AWS_LAMBDA_RUNTIME_API` environment variable tells the Lambda function where to find the Lambda runtime API endpoint. It has the following format: @@ -257,7 +275,7 @@ The `AWS_LAMBDA_RUNTIME_API` environment variable tells the Lambda function wher The host and port should match the port that the lambda emulator is running on. In this example we will be running the lambda runtime api emulator on `localhost` on port `5050` and our function name will be `AddLambdaFunction`. -### 4. API Gateway Configuration +### 3. API Gateway Configuration To expose this Lambda function through API Gateway, set the APIGATEWAY_EMULATOR_ROUTE_CONFIG: ``` @@ -268,7 +286,7 @@ To expose this Lambda function through API Gateway, set the APIGATEWAY_EMULATOR_ } ``` -### 5. Testing the Function +### 4. Testing the Function 1. Start the test tool with both Lambda and API Gateway emulators: ``` dotnet lambda-test-tool start \ From 0f7ac574f34d4f0f3d69592e5e8a598498ebc536 Mon Sep 17 00:00:00 2001 From: Garrett Beatty Date: Tue, 25 Feb 2025 15:46:41 -0500 Subject: [PATCH 9/9] PR comments --- Tools/LambdaTestTool-v2/README.md | 37 +++++++++++++++++-- .../Components/Pages/Documentation.razor | 2 +- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/Tools/LambdaTestTool-v2/README.md b/Tools/LambdaTestTool-v2/README.md index 9537c02bc..2f5c33426 100644 --- a/Tools/LambdaTestTool-v2/README.md +++ b/Tools/LambdaTestTool-v2/README.md @@ -59,13 +59,13 @@ Check out the following tracker issue for information on the .NET Aspire integra The tool is distributed as .NET Global Tool. To install the tool execute the following command: ``` -dotnet tool install -g amazon.lambda.testtool --prerelease +dotnet tool install -g amazon.lambda.testtool ``` To update the tool run the following command: ``` -dotnet tool update -g amazon.lambda.testtool --prerelease +dotnet tool update -g amazon.lambda.testtool ``` ## Running the Test Tool @@ -165,6 +165,35 @@ When using API Gateway mode, you need to configure the route mapping using the A ``` + +#### Wildcard Paths +The API Gateway emulator supports the use of wildcard path. To define a wildcard path, you can use the `{proxy+}` syntax in the route pattern. See [here](https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html) for a more detailed explanation on how proxies work. + +Here's an example of how to set up an API Gateway emulator with a wildcard path: + +``` +[ + { + "LambdaResourceName": "RootFunction", + "HttpMethod": "Get", + "Path": "/root" + }, + { + "LambdaResourceName": "MyOtherLambdaFunction", + "HttpMethod": "Get", + "Path": "/root/{proxy+}" + } +] + +``` + +This JSON configuration sets up two API Gateway resources: + +1. `/root` that is mapped to the `RootFunction` Lambda function. +2. `/root/{proxy+}` that is a proxy resource mapped to the `MyOtherLambdaFunction` Lambda function. + +The `{proxy+}` syntax in the second path allows the API Gateway to proxy any additional path segments to the integrated Lambda function. + ## Example Lambda Function Setup Here's a simple Lambda function that adds two numbers together. @@ -252,7 +281,7 @@ There are three variables you may need to replace: There are three variables you need to update in the launch settings: -1. `{TEST_TOOL_VERSION}` - Replace with the current Amazon.Lambda.TestTool version (e.g., `0.0.2-preview` in the example above) +1. `{TEST_TOOL_VERSION}` - Replace with the current Amazon.Lambda.TestTool version (e.g., `0.0.3` in the example above) - This appears in the path: `.store/amazon.lambda.testtool/{TEST_TOOL_VERSION}/amazon.lambda.testtool/{TEST_TOOL_VERSION}/content/` 2. `{TARGET_FRAMEWORK}` - Replace with your Lambda project's target framework version (e.g., `net8.0` in the example above) @@ -273,7 +302,7 @@ The `AWS_LAMBDA_RUNTIME_API` environment variable tells the Lambda function wher The host and port should match the port that the lambda emulator is running on. -In this example we will be running the lambda runtime api emulator on `localhost` on port `5050` and our function name will be `AddLambdaFunction`. +In this example we will be running the lambda runtime api emulator on `localhost` on port `5050` and our function name will be `AddLambdaFunction`. **Warning**: You should *not* add `http://` prefix to the host (if you do the lambda will fail to connect). ### 3. API Gateway Configuration To expose this Lambda function through API Gateway, set the APIGATEWAY_EMULATOR_ROUTE_CONFIG: diff --git a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Components/Pages/Documentation.razor b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Components/Pages/Documentation.razor index dd3760968..2cff94fee 100644 --- a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Components/Pages/Documentation.razor +++ b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Components/Pages/Documentation.razor @@ -8,6 +8,6 @@


- TODO: Rewrite documentation for V2 + Please see the README file here for more information.