From 9fdd63efb0d86ae268646ca2db6cbc30e0b9b614 Mon Sep 17 00:00:00 2001 From: Garrett Beatty Date: Fri, 24 Jan 2025 13:44:30 -0500 Subject: [PATCH] Use default host and port if endpoint not specified --- .../Processes/ApiGatewayEmulatorProcess.cs | 25 +++++++-- .../ApiGatewayEmulatorProcessTests.cs | 56 +++++++++++++++++-- 2 files changed, 70 insertions(+), 11 deletions(-) diff --git a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Processes/ApiGatewayEmulatorProcess.cs b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Processes/ApiGatewayEmulatorProcess.cs index 8f654ae55..70a02d7af 100644 --- a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Processes/ApiGatewayEmulatorProcess.cs +++ b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Processes/ApiGatewayEmulatorProcess.cs @@ -96,7 +96,7 @@ public static ApiGatewayEmulatorProcess Startup(RunCommandSettings settings, Can PayloadStream = lambdaRequestStream }; - using var lambdaClient = CreateLambdaServiceClient(routeConfig); + using var lambdaClient = CreateLambdaServiceClient(routeConfig, settings); var response = await lambdaClient.InvokeAsync(invokeRequest); if (response.FunctionError != null) @@ -111,13 +111,11 @@ public static ApiGatewayEmulatorProcess Startup(RunCommandSettings settings, Can { var lambdaResponse = response.ToApiGatewayHttpApiV2ProxyResponse(); await lambdaResponse.ToHttpResponseAsync(context); - return; } else { var lambdaResponse = response.ToApiGatewayProxyResponse(settings.ApiGatewayEmulatorMode.Value); await lambdaResponse.ToHttpResponseAsync(context, settings.ApiGatewayEmulatorMode.Value); - return; } }); @@ -131,12 +129,27 @@ public static ApiGatewayEmulatorProcess Startup(RunCommandSettings settings, Can }; } - private static IAmazonLambda CreateLambdaServiceClient(ApiGatewayRouteConfig routeConfig) + /// + /// Creates an Amazon Lambda service client with the specified configuration. + /// + /// The API Gateway route configuration containing the endpoint information. + /// If the endpoint is specified in routeConfig, it will be used as the service URL. + /// The run command settings containing host and port information. + /// If routeConfig endpoint is null, the service URL will be constructed using settings.Host and settings.Port. + /// An instance of IAmazonLambda configured with the specified endpoint and credentials. + /// + /// The function uses hard-coded AWS credentials ("accessKey", "secretKey") for authentication since they are not actually being used. + /// The service URL is determined by either: + /// - Using routeConfig.Endpoint if it's not null + /// - Combining settings.Host and settings.Port if routeConfig.Endpoint is null + /// + private static IAmazonLambda CreateLambdaServiceClient(ApiGatewayRouteConfig routeConfig, RunCommandSettings settings) { - // TODO: Handle routeConfig.Endpoint to null and use the settings versions of runtime. + var endpoint = routeConfig.Endpoint ?? $"http://{settings.LambdaEmulatorHost}:{settings.LambdaEmulatorPort}"; + var lambdaConfig = new AmazonLambdaConfig { - ServiceURL = routeConfig.Endpoint + ServiceURL = endpoint }; return new AmazonLambdaClient(new Amazon.Runtime.BasicAWSCredentials("accessKey", "secretKey"), lambdaConfig); diff --git a/Tools/LambdaTestTool-v2/tests/Amazon.Lambda.TestTool.IntegrationTests/ApiGatewayEmulatorProcessTests.cs b/Tools/LambdaTestTool-v2/tests/Amazon.Lambda.TestTool.IntegrationTests/ApiGatewayEmulatorProcessTests.cs index eb5b693a1..96415e630 100644 --- a/Tools/LambdaTestTool-v2/tests/Amazon.Lambda.TestTool.IntegrationTests/ApiGatewayEmulatorProcessTests.cs +++ b/Tools/LambdaTestTool-v2/tests/Amazon.Lambda.TestTool.IntegrationTests/ApiGatewayEmulatorProcessTests.cs @@ -61,7 +61,6 @@ public async Task TestLambdaToUpperV2() finally { await cancellationTokenSource.CancelAsync(); - await CleanupProcesses(); } } @@ -97,7 +96,6 @@ public async Task TestLambdaToUpperRest() finally { await cancellationTokenSource.CancelAsync(); - await CleanupProcesses(); } } @@ -133,7 +131,6 @@ public async Task TestLambdaToUpperV1() finally { await cancellationTokenSource.CancelAsync(); - await CleanupProcesses(); } } @@ -175,7 +172,6 @@ public async Task TestLambdaBinaryResponse() finally { await cancellationTokenSource.CancelAsync(); - await CleanupProcesses(); } } @@ -211,7 +207,39 @@ public async Task TestLambdaReturnString() finally { await cancellationTokenSource.CancelAsync(); - await CleanupProcesses(); + } + } + + [Fact] + public async Task TestLambdaWithNullEndpoint() + { + var testProjectDir = Path.GetFullPath("../../../../../testapps"); + var config = new TestConfig + { + TestToolPath = Path.GetFullPath(Path.Combine(testProjectDir, "../src/Amazon.Lambda.TestTool")), + LambdaPath = Path.GetFullPath(Path.Combine(testProjectDir, "LambdaTestFunctionV2")), + FunctionName = "LambdaTestFunctionV2", + RouteName = "testfunction", + HttpMethod = "Post" + }; + + var cancellationTokenSource = new CancellationTokenSource(); + + try + { + StartTestToolProcessWithNullEndpoint(ApiGatewayEmulatorMode.HttpV2, Constants.DefaultApiGatewayEmulatorPort, config, cancellationTokenSource); + await WaitForGatewayHealthCheck(Constants.DefaultApiGatewayEmulatorPort); + await StartLambdaProcess(config, Constants.DefaultLambdaEmulatorPort); + + var response = await TestEndpoint(config, Constants.DefaultApiGatewayEmulatorPort ); + var responseContent = await response.Content.ReadAsStringAsync(); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal("HELLO WORLD", responseContent); + } + finally + { + await cancellationTokenSource.CancelAsync(); } } @@ -236,6 +264,24 @@ private async Task TestEndpoint(TestConfig config, int apiG }; } + private void StartTestToolProcessWithNullEndpoint(ApiGatewayEmulatorMode apiGatewayMode, int apiGatewayPort, TestConfig config, CancellationTokenSource cancellationTokenSource) + { + Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development"); + Environment.SetEnvironmentVariable("APIGATEWAY_EMULATOR_ROUTE_CONFIG", $@"{{ + ""LambdaResourceName"": ""{config.RouteName}"", + ""HttpMethod"": ""{config.HttpMethod}"", + ""Path"": ""/{config.RouteName}"" + }}"); + + cancellationTokenSource.CancelAfter(5000); + var settings = new RunCommandSettings { NoLaunchWindow = true, ApiGatewayEmulatorMode = apiGatewayMode, ApiGatewayEmulatorPort = apiGatewayPort}; + + var command = new RunCommand(_mockInteractiveService.Object, _mockEnvironmentManager.Object); + var context = new CommandContext(new List(), _mockRemainingArgs.Object, "run", null); + + _ = command.ExecuteAsync(context, settings, cancellationTokenSource); + } + private void StartTestToolProcess(ApiGatewayEmulatorMode apiGatewayMode, TestConfig config, int lambdaPort, int apiGatewayPort, CancellationTokenSource cancellationTokenSource) { Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development");