diff --git a/.autover/changes/1c4eb3ce-e61b-4119-ac8d-d431f7b426cb.json b/.autover/changes/1c4eb3ce-e61b-4119-ac8d-d431f7b426cb.json new file mode 100644 index 000000000..063b9fbd4 --- /dev/null +++ b/.autover/changes/1c4eb3ce-e61b-4119-ac8d-d431f7b426cb.json @@ -0,0 +1,11 @@ +{ + "Projects": [ + { + "Name": "Amazon.Lambda.TestTool", + "Type": "Patch", + "ChangelogMessages": [ + "Update default log level to be ERROR in production and INFORMATION in debug mode." + ] + } + ] +} \ No newline at end of file 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 e1997b4cd..184b33bf3 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 @@ -56,4 +56,13 @@ + + + PreserveNewest + + + PreserveNewest + + + diff --git a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Configuration/ConfigurationSetup.cs b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Configuration/ConfigurationSetup.cs new file mode 100644 index 000000000..8e3395306 --- /dev/null +++ b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Configuration/ConfigurationSetup.cs @@ -0,0 +1,53 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +using System.Reflection; + +namespace Amazon.Lambda.TestTool.Configuration; + +/// +/// Handles the configuration setup for the Lambda Test Tool by loading settings from JSON files. +/// +/// +/// This class uses dependency injection to receive an Assembly instance, allowing for better testability +/// and flexibility in determining the configuration file locations. +/// +public class ConfigurationSetup(Assembly assembly) +{ + /// + /// Retrieves the application configuration by loading settings from JSON configuration files. + /// + /// An IConfiguration instance containing the application settings. + /// Thrown when unable to determine the assembly location. + /// + /// The method performs the following steps: + /// 1. Locates the directory containing the assembly + /// 2. Loads the base configuration from appsettings.json + /// 3. Loads environment-specific configuration from appsettings.{environment}.json if available + /// + public IConfiguration GetConfiguration() + { + // Get the directory where the assembly is located + var assemblyLocation = assembly.Location; + var packageDirectory = Path.GetDirectoryName(assemblyLocation) + ?? throw new InvalidOperationException("Unable to determine assembly location"); + + // Construct path to configuration file + var appsettingsPath = Path.Combine(packageDirectory, "appsettings.json"); + if (!File.Exists(appsettingsPath)) + { + Console.WriteLine($"Warning: appsettings.json not found at {appsettingsPath}"); + } + + // Determine the current environment + var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"; + + // Build and return the configuration + var builder = new ConfigurationBuilder() + .SetBasePath(packageDirectory) + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .AddJsonFile($"appsettings.{environment}.json", optional: true, reloadOnChange: true); + + return builder.Build(); + } +} diff --git a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Extensions/ServiceCollectionExtensions.cs b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Extensions/ServiceCollectionExtensions.cs index 1afe1704c..b518fee7c 100644 --- a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Extensions/ServiceCollectionExtensions.cs +++ b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Extensions/ServiceCollectionExtensions.cs @@ -1,6 +1,8 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +using System.Reflection; +using Amazon.Lambda.TestTool.Configuration; using Amazon.Lambda.TestTool.Services; using Amazon.Lambda.TestTool.Services.IO; using Microsoft.Extensions.DependencyInjection.Extensions; 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 b585187de..35efb968a 100644 --- a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Processes/ApiGatewayEmulatorProcess.cs +++ b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Processes/ApiGatewayEmulatorProcess.cs @@ -1,6 +1,7 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +using System.Reflection; using Amazon.Lambda.APIGatewayEvents; using Amazon.Lambda.Model; using Amazon.Lambda.TestTool.Commands.Settings; @@ -9,6 +10,8 @@ using Amazon.Lambda.TestTool.Services; using System.Text.Json; +using Amazon.Lambda.TestTool.Configuration; +using Amazon.Lambda.TestTool.Utilities; namespace Amazon.Lambda.TestTool.Processes; @@ -46,6 +49,8 @@ public static ApiGatewayEmulatorProcess Startup(RunCommandSettings settings, Can var builder = WebApplication.CreateBuilder(); + Utils.ConfigureWebApplicationBuilder(builder); + builder.Services.AddApiGatewayEmulatorServices(); var serviceUrl = $"http://{settings.LambdaEmulatorHost}:{settings.ApiGatewayEmulatorPort}"; diff --git a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Processes/TestToolProcess.cs b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Processes/TestToolProcess.cs index d6823c6d6..420631a0b 100644 --- a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Processes/TestToolProcess.cs +++ b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Processes/TestToolProcess.cs @@ -1,10 +1,13 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +using System.Reflection; using Amazon.Lambda.TestTool.Commands.Settings; using Amazon.Lambda.TestTool.Components; +using Amazon.Lambda.TestTool.Configuration; using Amazon.Lambda.TestTool.Services; using Amazon.Lambda.TestTool.Services.IO; +using Amazon.Lambda.TestTool.Utilities; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Options; @@ -37,6 +40,8 @@ public static TestToolProcess Startup(RunCommandSettings settings, CancellationT { var builder = WebApplication.CreateBuilder(); + Utils.ConfigureWebApplicationBuilder(builder); + builder.Services.AddSingleton(); builder.Services.AddSingleton(); diff --git a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Utilities/Utils.cs b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Utilities/Utils.cs index ead444dd3..34f200dd7 100644 --- a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Utilities/Utils.cs +++ b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Utilities/Utils.cs @@ -3,6 +3,7 @@ using System.Reflection; using System.Text.Json; +using Amazon.Lambda.TestTool.Configuration; namespace Amazon.Lambda.TestTool.Utilities; @@ -74,4 +75,32 @@ public static string TryPrettyPrintJson(string? data) return data ?? string.Empty; } } + + /// + /// Configures the web application builder with necessary services, configuration, and logging setup. + /// + /// The WebApplicationBuilder instance to be configured + /// + /// This method performs the following configurations: + /// 1. Registers the current assembly as a singleton service + /// 2. Registers ConfigurationSetup as a singleton service + /// 3. Builds and applies custom configuration + /// 4. Sets up logging providers with console output + /// + /// + /// Thrown when ConfigurationSetup service cannot be resolved from the service provider + /// + public static void ConfigureWebApplicationBuilder(WebApplicationBuilder builder) + { + builder.Services.AddSingleton(typeof(Assembly), typeof(ConfigurationSetup).Assembly); + builder.Services.AddSingleton(); + + var configSetup = builder.Services.BuildServiceProvider().GetRequiredService(); + var configuration = configSetup.GetConfiguration(); + builder.Configuration.AddConfiguration(configuration); + + builder.Logging.ClearProviders(); + builder.Logging.AddConfiguration(configuration.GetSection("Logging")); + builder.Logging.AddConsole(); + } } diff --git a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/appsettings.Development.json b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/appsettings.Development.json index 08696af70..0b8026458 100644 --- a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/appsettings.Development.json +++ b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/appsettings.Development.json @@ -1,8 +1,7 @@ { "Logging": { "LogLevel": { - "Default": "Trace", - "Microsoft.AspNetCore": "Trace" + "Default": "Information" } }, "DetailedErrors": true diff --git a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/appsettings.json b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/appsettings.json index 9dbb62aee..8a024f3bd 100644 --- a/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/appsettings.json +++ b/Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/appsettings.json @@ -1,9 +1,7 @@ { "Logging": { "LogLevel": { - "Default": "Trace", - "Microsoft": "Trace", - "Microsoft.AspNetCore": "Trace" + "Default": "Error" } }, "AllowedHosts": "*" diff --git a/Tools/LambdaTestTool-v2/tests/Amazon.Lambda.TestTool.UnitTests/Configuration/ConfigurationSetupTests.cs b/Tools/LambdaTestTool-v2/tests/Amazon.Lambda.TestTool.UnitTests/Configuration/ConfigurationSetupTests.cs new file mode 100644 index 000000000..34cb746d3 --- /dev/null +++ b/Tools/LambdaTestTool-v2/tests/Amazon.Lambda.TestTool.UnitTests/Configuration/ConfigurationSetupTests.cs @@ -0,0 +1,113 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +using System.Reflection; +using Amazon.Lambda.TestTool.Configuration; +using Moq; +using Xunit; + +namespace Amazon.Lambda.TestTool.UnitTests.Configuration; + +public class ConfigurationSetupTests +{ + [Fact] + public void GetConfiguration_WithValidAssemblyLocation_ReturnsConfiguration() + { + // Arrange + var mockAssembly = new Mock(); + var testDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); + Directory.CreateDirectory(testDirectory); + + try + { + // Create test appsettings.json + File.WriteAllText( + Path.Combine(testDirectory, "appsettings.json"), + @"{""TestSetting"": ""TestValue""}" + ); + + mockAssembly + .Setup(x => x.Location) + .Returns(Path.Combine(testDirectory, "dummy.dll")); + + var configSetup = new ConfigurationSetup(mockAssembly.Object); + + // Act + var configuration = configSetup.GetConfiguration(); + + // Assert + Assert.NotNull(configuration); + Assert.Equal("TestValue", configuration["TestSetting"]); + } + finally + { + // Cleanup + Directory.Delete(testDirectory, true); + } + } + + [Fact] + public void GetConfiguration_WithEnvironmentSpecificConfig_LoadsBothConfigs() + { + // Arrange + var mockAssembly = new Mock(); + var testDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); + Directory.CreateDirectory(testDirectory); + + try + { + // Create test appsettings.json + File.WriteAllText( + Path.Combine(testDirectory, "appsettings.json"), + @"{""TestSetting"": ""BaseValue"", ""CommonSetting"": ""BaseValue""}" + ); + + // Create test appsettings.Development.json + File.WriteAllText( + Path.Combine(testDirectory, "appsettings.Development.json"), + @"{""TestSetting"": ""DevValue""}" + ); + + Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development"); + + mockAssembly + .Setup(x => x.Location) + .Returns(Path.Combine(testDirectory, "dummy.dll")); + + var configSetup = new ConfigurationSetup(mockAssembly.Object); + + // Act + var configuration = configSetup.GetConfiguration(); + + // Assert + Assert.NotNull(configuration); + Assert.Equal("DevValue", configuration["TestSetting"]); // Overridden value + Assert.Equal("BaseValue", configuration["CommonSetting"]); // Base value + } + finally + { + // Cleanup + Directory.Delete(testDirectory, true); + Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", null); + } + } + + [Fact] + public void GetConfiguration_WithInvalidAssemblyLocation_ThrowsInvalidOperationException() + { + // Arrange + var mockAssembly = new Mock(); + mockAssembly + .Setup(x => x.Location) + .Returns(string.Empty); + + var configSetup = new ConfigurationSetup(mockAssembly.Object); + + // Act & Assert + var exception = Assert.Throws( + () => configSetup.GetConfiguration() + ); + Assert.Equal("Unable to determine assembly location", exception.Message); + } +} +