diff --git a/src/Cli.Tests/ConfigGeneratorTests.cs b/src/Cli.Tests/ConfigGeneratorTests.cs index 7adddcd4fd..4e7746af37 100644 --- a/src/Cli.Tests/ConfigGeneratorTests.cs +++ b/src/Cli.Tests/ConfigGeneratorTests.cs @@ -10,14 +10,14 @@ namespace Cli.Tests; public class ConfigGeneratorTests { private IFileSystem? _fileSystem; - private RuntimeConfigLoader? _runtimeConfigLoader; + private FileSystemRuntimeConfigLoader? _runtimeConfigLoader; [TestInitialize] public void TestInitialize() { _fileSystem = FileSystemUtils.ProvisionMockFileSystem(); - _runtimeConfigLoader = new RuntimeConfigLoader(_fileSystem); + _runtimeConfigLoader = new FileSystemRuntimeConfigLoader(_fileSystem); ILoggerFactory loggerFactory = TestLoggerSupport.ProvisionLoggerFactory(); @@ -49,9 +49,9 @@ public void TryGenerateConfig_WithUserProvidedConfig( // Mocking logger to assert on logs Mock> loggerMock = new(); - ConfigGenerator.SetLoggerForCliConfigGenerator(loggerMock.Object); + SetLoggerForCliConfigGenerator(loggerMock.Object); - Assert.AreEqual(isConfigGenerationSuccessful, ConfigGenerator.TryGenerateConfig(options, _runtimeConfigLoader!, _fileSystem!)); + Assert.AreEqual(isConfigGenerationSuccessful, TryGenerateConfig(options, _runtimeConfigLoader!, _fileSystem!)); if (!isConfigFilePresent) { @@ -96,9 +96,9 @@ public void TryGenerateConfig_UsingEnvironmentVariable( // Mocking logger to assert on logs Mock> loggerMock = new(); - ConfigGenerator.SetLoggerForCliConfigGenerator(loggerMock.Object); + SetLoggerForCliConfigGenerator(loggerMock.Object); - Assert.AreEqual(isConfigGenerationSuccessful, ConfigGenerator.TryGenerateConfig(options, _runtimeConfigLoader!, _fileSystem!)); + Assert.AreEqual(isConfigGenerationSuccessful, TryGenerateConfig(options, _runtimeConfigLoader!, _fileSystem!)); if (!isConfigFilePresent) { Assert.AreEqual(isConfigGenerationSuccessful, _fileSystem!.File.Exists(configFileName)); diff --git a/src/Cli.Tests/EndToEndTests.cs b/src/Cli.Tests/EndToEndTests.cs index 03226bae7d..ee52d67506 100644 --- a/src/Cli.Tests/EndToEndTests.cs +++ b/src/Cli.Tests/EndToEndTests.cs @@ -13,7 +13,7 @@ public class EndToEndTests : VerifyBase { private IFileSystem? _fileSystem; - private RuntimeConfigLoader? _runtimeConfigLoader; + private FileSystemRuntimeConfigLoader? _runtimeConfigLoader; private ILogger? _cliLogger; [TestInitialize] @@ -26,7 +26,7 @@ public void TestInitialize() _fileSystem = fileSystem; - _runtimeConfigLoader = new RuntimeConfigLoader(_fileSystem); + _runtimeConfigLoader = new FileSystemRuntimeConfigLoader(_fileSystem); ILoggerFactory loggerFactory = TestLoggerSupport.ProvisionLoggerFactory(); diff --git a/src/Cli.Tests/InitTests.cs b/src/Cli.Tests/InitTests.cs index b239185501..6d807ae48b 100644 --- a/src/Cli.Tests/InitTests.cs +++ b/src/Cli.Tests/InitTests.cs @@ -11,14 +11,14 @@ public class InitTests : VerifyBase { private IFileSystem? _fileSystem; - private RuntimeConfigLoader? _runtimeConfigLoader; + private FileSystemRuntimeConfigLoader? _runtimeConfigLoader; [TestInitialize] public void TestInitialize() { _fileSystem = FileSystemUtils.ProvisionMockFileSystem(); - _runtimeConfigLoader = new RuntimeConfigLoader(_fileSystem); + _runtimeConfigLoader = new FileSystemRuntimeConfigLoader(_fileSystem); ILoggerFactory loggerFactory = TestLoggerSupport.ProvisionLoggerFactory(); diff --git a/src/Cli.Tests/Usings.cs b/src/Cli.Tests/Usings.cs index df303ff941..ae1b4c1fcc 100644 --- a/src/Cli.Tests/Usings.cs +++ b/src/Cli.Tests/Usings.cs @@ -13,7 +13,7 @@ global using Microsoft.VisualStudio.TestTools.UnitTesting; global using Moq; global using Newtonsoft.Json.Linq; -global using static Azure.DataApiBuilder.Config.RuntimeConfigLoader; +global using static Azure.DataApiBuilder.Config.FileSystemRuntimeConfigLoader; global using static Cli.ConfigGenerator; global using static Cli.Tests.TestHelper; global using static Cli.Utils; diff --git a/src/Cli.Tests/UtilsTests.cs b/src/Cli.Tests/UtilsTests.cs index 11b2eef72d..550c8eebe6 100644 --- a/src/Cli.Tests/UtilsTests.cs +++ b/src/Cli.Tests/UtilsTests.cs @@ -107,8 +107,8 @@ public void ConstructGraphQLOptionsWithSingularAndPluralWillSetSingularAndPlural [DataTestMethod] [DataRow("", "my-config.json", "my-config.json", DisplayName = "user provided the config file and environment variable was not set.")] [DataRow("Test", "my-config.json", "my-config.json", DisplayName = "user provided the config file and environment variable was set.")] - [DataRow("Test", null, $"{RuntimeConfigLoader.CONFIGFILE_NAME}.Test{RuntimeConfigLoader.CONFIG_EXTENSION}", DisplayName = "config not provided, but environment variable was set.")] - [DataRow("", null, $"{RuntimeConfigLoader.CONFIGFILE_NAME}{RuntimeConfigLoader.CONFIG_EXTENSION}", DisplayName = "neither config was provided, nor environment variable was set.")] + [DataRow("Test", null, $"{CONFIGFILE_NAME}.Test{CONFIG_EXTENSION}", DisplayName = "config not provided, but environment variable was set.")] + [DataRow("", null, $"{CONFIGFILE_NAME}{CONFIG_EXTENSION}", DisplayName = "neither config was provided, nor environment variable was set.")] public void TestConfigSelectionBasedOnCliPrecedence( string? environmentValue, string? userProvidedConfigFile, @@ -117,13 +117,13 @@ public void TestConfigSelectionBasedOnCliPrecedence( MockFileSystem fileSystem = new(); fileSystem.AddFile(expectedRuntimeConfigFile, new MockFileData("")); - RuntimeConfigLoader loader = new(fileSystem); + FileSystemRuntimeConfigLoader loader = new(fileSystem); - string? envValueBeforeTest = Environment.GetEnvironmentVariable(RuntimeConfigLoader.RUNTIME_ENVIRONMENT_VAR_NAME); - Environment.SetEnvironmentVariable(RuntimeConfigLoader.RUNTIME_ENVIRONMENT_VAR_NAME, environmentValue); + string? envValueBeforeTest = Environment.GetEnvironmentVariable(RUNTIME_ENVIRONMENT_VAR_NAME); + Environment.SetEnvironmentVariable(RUNTIME_ENVIRONMENT_VAR_NAME, environmentValue); Assert.IsTrue(TryGetConfigFileBasedOnCliPrecedence(loader, userProvidedConfigFile, out string? actualRuntimeConfigFile)); Assert.AreEqual(expectedRuntimeConfigFile, actualRuntimeConfigFile); - Environment.SetEnvironmentVariable(RuntimeConfigLoader.RUNTIME_ENVIRONMENT_VAR_NAME, envValueBeforeTest); + Environment.SetEnvironmentVariable(RUNTIME_ENVIRONMENT_VAR_NAME, envValueBeforeTest); } /// @@ -239,14 +239,14 @@ public void TestValidateAudienceAndIssuerForAuthenticationProvider( public void TestMergeConfig() { MockFileSystem fileSystem = new(); - fileSystem.AddFile(RuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, new MockFileData(BASE_CONFIG)); + fileSystem.AddFile(DEFAULT_CONFIG_FILE_NAME, new MockFileData(BASE_CONFIG)); fileSystem.AddFile("dab-config.Test.json", new MockFileData(ENV_BASED_CONFIG)); - RuntimeConfigLoader loader = new(fileSystem); + FileSystemRuntimeConfigLoader loader = new(fileSystem); - Environment.SetEnvironmentVariable(RuntimeConfigLoader.RUNTIME_ENVIRONMENT_VAR_NAME, "Test"); + Environment.SetEnvironmentVariable(RUNTIME_ENVIRONMENT_VAR_NAME, "Test"); - Assert.IsTrue(Cli.ConfigMerger.TryMergeConfigsIfAvailable(fileSystem, loader, new StringLogger(), out string? mergedConfig), "Failed to merge config files"); + Assert.IsTrue(ConfigMerger.TryMergeConfigsIfAvailable(fileSystem, loader, new StringLogger(), out string? mergedConfig), "Failed to merge config files"); Assert.AreEqual(mergedConfig, "dab-config.Test.merged.json"); Assert.IsTrue(fileSystem.File.Exists(mergedConfig)); Assert.IsTrue(JToken.DeepEquals(JObject.Parse(MERGED_CONFIG), JObject.Parse(fileSystem.File.ReadAllText(mergedConfig)))); @@ -282,7 +282,7 @@ public void TestMergeConfigAvailability( MockFileSystem fileSystem = new(); // Setting up the test scenarios - Environment.SetEnvironmentVariable(RuntimeConfigLoader.RUNTIME_ENVIRONMENT_VAR_NAME, environmentValue); + Environment.SetEnvironmentVariable(RUNTIME_ENVIRONMENT_VAR_NAME, environmentValue); string baseConfig = "dab-config.json"; string envBasedConfig = "dab-config.Test.json"; @@ -296,7 +296,7 @@ public void TestMergeConfigAvailability( fileSystem.AddFile(envBasedConfig, new("{}")); } - RuntimeConfigLoader loader = new(fileSystem); + FileSystemRuntimeConfigLoader loader = new(fileSystem); Assert.AreEqual( expectedIsMergedConfigAvailable, @@ -304,7 +304,7 @@ public void TestMergeConfigAvailability( "Availability of merge config should match"); Assert.AreEqual(expectedMergedConfigFileName, mergedConfigFile, "Merge config file name should match expected"); - Environment.SetEnvironmentVariable(RuntimeConfigLoader.RUNTIME_ENVIRONMENT_VAR_NAME, null); + Environment.SetEnvironmentVariable(RUNTIME_ENVIRONMENT_VAR_NAME, null); } } diff --git a/src/Cli/Commands/AddOptions.cs b/src/Cli/Commands/AddOptions.cs index c00c95428b..8dc2378e26 100644 --- a/src/Cli/Commands/AddOptions.cs +++ b/src/Cli/Commands/AddOptions.cs @@ -56,7 +56,7 @@ public AddOptions( [Option("permissions", Required = true, Separator = ':', HelpText = "Permissions required to access the source table or container.")] public IEnumerable Permissions { get; } - public void Handler(ILogger logger, RuntimeConfigLoader loader, IFileSystem fileSystem) + public void Handler(ILogger logger, FileSystemRuntimeConfigLoader loader, IFileSystem fileSystem) { logger.LogInformation($"{PRODUCT_NAME} {ProductInfo.GetProductVersion()}"); if (!IsEntityProvided(Entity, logger, command: "add")) diff --git a/src/Cli/Commands/InitOptions.cs b/src/Cli/Commands/InitOptions.cs index 0c667a0c83..910f0ecc5f 100644 --- a/src/Cli/Commands/InitOptions.cs +++ b/src/Cli/Commands/InitOptions.cs @@ -103,7 +103,7 @@ public InitOptions( [Option("graphql.disabled", Default = false, Required = false, HelpText = "Disables GraphQL endpoint for all entities.")] public bool GraphQLDisabled { get; } - public void Handler(ILogger logger, RuntimeConfigLoader loader, IFileSystem fileSystem) + public void Handler(ILogger logger, FileSystemRuntimeConfigLoader loader, IFileSystem fileSystem) { logger.LogInformation($"{PRODUCT_NAME} {ProductInfo.GetProductVersion()}"); bool isSuccess = ConfigGenerator.TryGenerateConfig(this, loader, fileSystem); diff --git a/src/Cli/Commands/StartOptions.cs b/src/Cli/Commands/StartOptions.cs index 5f4fc1f009..066dccf370 100644 --- a/src/Cli/Commands/StartOptions.cs +++ b/src/Cli/Commands/StartOptions.cs @@ -35,7 +35,7 @@ public StartOptions(bool verbose, LogLevel? logLevel, bool isHttpsRedirectionDis [Option("no-https-redirect", Required = false, HelpText = "Disables automatic https redirects.")] public bool IsHttpsRedirectionDisabled { get; } - public void Handler(ILogger logger, RuntimeConfigLoader loader, IFileSystem fileSystem) + public void Handler(ILogger logger, FileSystemRuntimeConfigLoader loader, IFileSystem fileSystem) { logger.LogInformation($"{PRODUCT_NAME} {ProductInfo.GetProductVersion()}"); bool isSuccess = ConfigGenerator.TryStartEngineWithOptions(this, loader, fileSystem); diff --git a/src/Cli/Commands/UpdateOptions.cs b/src/Cli/Commands/UpdateOptions.cs index 2f762a5908..de665ccbd7 100644 --- a/src/Cli/Commands/UpdateOptions.cs +++ b/src/Cli/Commands/UpdateOptions.cs @@ -96,7 +96,7 @@ public UpdateOptions( [Option('m', "map", Separator = ',', Required = false, HelpText = "Specify mappings between database fields and GraphQL and REST fields. format: --map \"backendName1:exposedName1,backendName2:exposedName2,...\".")] public IEnumerable? Map { get; } - public void Handler(ILogger logger, RuntimeConfigLoader loader, IFileSystem fileSystem) + public void Handler(ILogger logger, FileSystemRuntimeConfigLoader loader, IFileSystem fileSystem) { logger.LogInformation($"{PRODUCT_NAME} {ProductInfo.GetProductVersion()}"); if (!IsEntityProvided(Entity, logger, command: "update")) diff --git a/src/Cli/ConfigGenerator.cs b/src/Cli/ConfigGenerator.cs index 4c1272a31a..2f4a16bd40 100644 --- a/src/Cli/ConfigGenerator.cs +++ b/src/Cli/ConfigGenerator.cs @@ -35,9 +35,9 @@ public static void SetLoggerForCliConfigGenerator( /// /// This method will generate the initial config with databaseType and connection-string. /// - public static bool TryGenerateConfig(InitOptions options, RuntimeConfigLoader loader, IFileSystem fileSystem) + public static bool TryGenerateConfig(InitOptions options, FileSystemRuntimeConfigLoader loader, IFileSystem fileSystem) { - string runtimeConfigFile = RuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME; + string runtimeConfigFile = FileSystemRuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME; if (!string.IsNullOrWhiteSpace(options.Config)) { _logger.LogInformation("Generating user provided config file with name: {configFileName}", options.Config); @@ -45,11 +45,11 @@ public static bool TryGenerateConfig(InitOptions options, RuntimeConfigLoader lo } else { - string? environmentValue = Environment.GetEnvironmentVariable(RuntimeConfigLoader.RUNTIME_ENVIRONMENT_VAR_NAME); + string? environmentValue = Environment.GetEnvironmentVariable(FileSystemRuntimeConfigLoader.RUNTIME_ENVIRONMENT_VAR_NAME); if (!string.IsNullOrWhiteSpace(environmentValue)) { - _logger.LogInformation("The environment variable {variableName} has a value of {variableValue}", RuntimeConfigLoader.RUNTIME_ENVIRONMENT_VAR_NAME, environmentValue); - runtimeConfigFile = RuntimeConfigLoader.GetEnvironmentFileName(RuntimeConfigLoader.CONFIGFILE_NAME, environmentValue); + _logger.LogInformation("The environment variable {variableName} has a value of {variableValue}", FileSystemRuntimeConfigLoader.RUNTIME_ENVIRONMENT_VAR_NAME, environmentValue); + runtimeConfigFile = FileSystemRuntimeConfigLoader.GetEnvironmentFileName(FileSystemRuntimeConfigLoader.CONFIGFILE_NAME, environmentValue); _logger.LogInformation("Generating environment config file: {configPath}", fileSystem.Path.GetFullPath(runtimeConfigFile)); } else @@ -81,7 +81,7 @@ public static bool TryGenerateConfig(InitOptions options, RuntimeConfigLoader lo /// Init options /// Output runtime config json. /// True on success. False otherwise. - public static bool TryCreateRuntimeConfig(InitOptions options, RuntimeConfigLoader loader, IFileSystem fileSystem, [NotNullWhen(true)] out RuntimeConfig? runtimeConfig) + public static bool TryCreateRuntimeConfig(InitOptions options, FileSystemRuntimeConfigLoader loader, IFileSystem fileSystem, [NotNullWhen(true)] out RuntimeConfig? runtimeConfig) { runtimeConfig = null; @@ -225,7 +225,7 @@ public static bool TryCreateRuntimeConfig(InitOptions options, RuntimeConfigLoad /// This method will add a new Entity with the given REST and GraphQL endpoints, source, and permissions. /// It also supports fields that needs to be included or excluded for a given role and operation. /// - public static bool TryAddEntityToConfigWithOptions(AddOptions options, RuntimeConfigLoader loader, IFileSystem fileSystem) + public static bool TryAddEntityToConfigWithOptions(AddOptions options, FileSystemRuntimeConfigLoader loader, IFileSystem fileSystem) { if (!TryGetConfigFileBasedOnCliPrecedence(loader, options.Config, out string runtimeConfigFile)) { @@ -455,7 +455,7 @@ public static bool TryCreateSourceObjectForNewEntity( /// This method will update an existing Entity with the given REST and GraphQL endpoints, source, and permissions. /// It also supports updating fields that need to be included or excluded for a given role and operation. /// - public static bool TryUpdateEntityWithOptions(UpdateOptions options, RuntimeConfigLoader loader, IFileSystem fileSystem) + public static bool TryUpdateEntityWithOptions(UpdateOptions options, FileSystemRuntimeConfigLoader loader, IFileSystem fileSystem) { if (!TryGetConfigFileBasedOnCliPrecedence(loader, options.Config, out string runtimeConfigFile)) { @@ -951,7 +951,7 @@ public static bool VerifyCanUpdateRelationship(RuntimeConfig runtimeConfig, stri /// overrides < environmentConfig < defaultConfig /// Also preforms validation to check connection string is not null or empty. /// - public static bool TryStartEngineWithOptions(StartOptions options, RuntimeConfigLoader loader, IFileSystem fileSystem) + public static bool TryStartEngineWithOptions(StartOptions options, FileSystemRuntimeConfigLoader loader, IFileSystem fileSystem) { string? configToBeUsed = options.Config; if (string.IsNullOrEmpty(configToBeUsed) && ConfigMerger.TryMergeConfigsIfAvailable(fileSystem, loader, _logger, out configToBeUsed)) diff --git a/src/Cli/ConfigMerger.cs b/src/Cli/ConfigMerger.cs index 84ace5cb85..a765db5d6d 100644 --- a/src/Cli/ConfigMerger.cs +++ b/src/Cli/ConfigMerger.cs @@ -15,13 +15,13 @@ public static class ConfigMerger /// and create a merged file called dab-config.{DAB_ENVIRONMENT}.merged.json /// /// Returns the name of the merged Config if successful. - public static bool TryMergeConfigsIfAvailable(IFileSystem fileSystem, RuntimeConfigLoader loader, ILogger logger, out string? mergedConfigFile) + public static bool TryMergeConfigsIfAvailable(IFileSystem fileSystem, FileSystemRuntimeConfigLoader loader, ILogger logger, out string? mergedConfigFile) { - string? environmentValue = Environment.GetEnvironmentVariable(RuntimeConfigLoader.RUNTIME_ENVIRONMENT_VAR_NAME); + string? environmentValue = Environment.GetEnvironmentVariable(FileSystemRuntimeConfigLoader.RUNTIME_ENVIRONMENT_VAR_NAME); mergedConfigFile = null; if (!string.IsNullOrEmpty(environmentValue)) { - string baseConfigFile = RuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME; + string baseConfigFile = FileSystemRuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME; string environmentBasedConfigFile = loader.GetFileName(environmentValue, considerOverrides: false); if (loader.DoesFileExistInCurrentDirectory(baseConfigFile) && !string.IsNullOrEmpty(environmentBasedConfigFile)) @@ -34,7 +34,7 @@ public static bool TryMergeConfigsIfAvailable(IFileSystem fileSystem, RuntimeCon string currentDir = fileSystem.Directory.GetCurrentDirectory(); logger.LogInformation("Merging {baseFilePath} and {envFilePath}", Path.Combine(currentDir, baseConfigFile), Path.Combine(currentDir, environmentBasedConfigFile)); string mergedConfigJson = MergeJsonProvider.Merge(baseConfigJson, overrideConfigJson); - mergedConfigFile = RuntimeConfigLoader.GetMergedFileNameForEnvironment(RuntimeConfigLoader.CONFIGFILE_NAME, environmentValue); + mergedConfigFile = FileSystemRuntimeConfigLoader.GetMergedFileNameForEnvironment(FileSystemRuntimeConfigLoader.CONFIGFILE_NAME, environmentValue); fileSystem.File.WriteAllText(mergedConfigFile, mergedConfigJson); logger.LogInformation("Generated merged config file: {mergedFile}", Path.Combine(currentDir, mergedConfigFile)); return true; diff --git a/src/Cli/Exporter.cs b/src/Cli/Exporter.cs index c3e48fcad2..b43ad46334 100644 --- a/src/Cli/Exporter.cs +++ b/src/Cli/Exporter.cs @@ -13,7 +13,7 @@ namespace Cli { internal static class Exporter { - public static void Export(ExportOptions options, ILogger logger, RuntimeConfigLoader loader, IFileSystem fileSystem) + public static void Export(ExportOptions options, ILogger logger, FileSystemRuntimeConfigLoader loader, IFileSystem fileSystem) { StartOptions startOptions = new(false, LogLevel.None, false, options.Config!); diff --git a/src/Cli/Program.cs b/src/Cli/Program.cs index feeacce7bd..17c3efe3d6 100644 --- a/src/Cli/Program.cs +++ b/src/Cli/Program.cs @@ -36,12 +36,12 @@ public static int Main(string[] args) ConfigGenerator.SetLoggerForCliConfigGenerator(configGeneratorLogger); Utils.SetCliUtilsLogger(cliUtilsLogger); IFileSystem fileSystem = new FileSystem(); - RuntimeConfigLoader loader = new(fileSystem); + FileSystemRuntimeConfigLoader loader = new(fileSystem); return Execute(args, cliLogger, fileSystem, loader); } - public static int Execute(string[] args, ILogger cliLogger, IFileSystem fileSystem, RuntimeConfigLoader loader) + public static int Execute(string[] args, ILogger cliLogger, IFileSystem fileSystem, FileSystemRuntimeConfigLoader loader) { // To know if `--help` or `--version` was requested. bool isHelpOrVersionRequested = false; diff --git a/src/Cli/Utils.cs b/src/Cli/Utils.cs index de1950e1e9..4390468c19 100644 --- a/src/Cli/Utils.cs +++ b/src/Cli/Utils.cs @@ -377,7 +377,7 @@ public static bool TryGetRoleAndOperationFromPermission(IEnumerable perm /// In case of false, the runtimeConfigFile will be set to string.Empty. /// public static bool TryGetConfigFileBasedOnCliPrecedence( - RuntimeConfigLoader loader, + FileSystemRuntimeConfigLoader loader, string? userProvidedConfigFile, out string runtimeConfigFile) { diff --git a/src/Config/FileSystemRuntimeConfigLoader.cs b/src/Config/FileSystemRuntimeConfigLoader.cs new file mode 100644 index 0000000000..6a35224337 --- /dev/null +++ b/src/Config/FileSystemRuntimeConfigLoader.cs @@ -0,0 +1,254 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Diagnostics.CodeAnalysis; +using System.IO.Abstractions; +using System.Net; +using System.Reflection; +using System.Text.Json; +using Azure.DataApiBuilder.Config.ObjectModel; +using Azure.DataApiBuilder.Service.Exceptions; + +namespace Azure.DataApiBuilder.Config; + +/// +/// This class is responsible for loading the runtime config from either a JSON string +/// or a file located on disk, depending on how the service is being run. +/// +/// +/// This class does not maintain any internal state of the loaded config, instead it will +/// always generate a new config when it is requested. +/// +/// To support better testability, the abstraction is provided +/// which allows for mocking of the file system in tests, providing a way to run the test +/// in isolation of other tests or the actual file system. +/// +public class FileSystemRuntimeConfigLoader : RuntimeConfigLoader +{ + private string _baseConfigFileName; + + private readonly IFileSystem _fileSystem; + + public const string CONFIGFILE_NAME = "dab-config"; + public const string CONFIG_EXTENSION = ".json"; + public const string ENVIRONMENT_PREFIX = "DAB_"; + public const string RUNTIME_ENVIRONMENT_VAR_NAME = $"{ENVIRONMENT_PREFIX}ENVIRONMENT"; + public const string RUNTIME_ENV_CONNECTION_STRING = $"{ENVIRONMENT_PREFIX}CONNSTRING"; + public const string ASP_NET_CORE_ENVIRONMENT_VAR_NAME = "ASPNETCORE_ENVIRONMENT"; + public const string SCHEMA = "dab.draft.schema.json"; + + /// + /// Returns the default config file name. + /// + public const string DEFAULT_CONFIG_FILE_NAME = $"{CONFIGFILE_NAME}{CONFIG_EXTENSION}"; + + public string ConfigFileName => GetFileNameForEnvironment(Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"), false); + + public FileSystemRuntimeConfigLoader(IFileSystem fileSystem, string baseConfigFileName = DEFAULT_CONFIG_FILE_NAME, string? connectionString = null) + : base(connectionString) + { + _fileSystem = fileSystem; + _baseConfigFileName = baseConfigFileName; + } + + /// + /// Load the runtime config from the specified path. + /// + /// The path to the dab-config.json file. + /// The loaded RuntimeConfig, or null if none was loaded. + /// True if the config was loaded, otherwise false. + public bool TryLoadConfig(string path, [NotNullWhen(true)] out RuntimeConfig? config) + { + if (_fileSystem.File.Exists(path)) + { + string json = _fileSystem.File.ReadAllText(path); + return TryParseConfig(json, out config, connectionString: _connectionString); + } + + config = null; + return false; + } + + /// + /// Tries to load the config file using the filename known to the RuntimeConfigLoader and for the default environment. + /// + /// The loaded RuntimeConfig, or null if none was loaded. + /// True if the config was loaded, otherwise false. + public override bool TryLoadKnownConfig([NotNullWhen(true)] out RuntimeConfig? config) + { + return TryLoadConfig(ConfigFileName, out config); + } + + /// + /// Precedence of environments is + /// 1) Value of DAB_ENVIRONMENT. + /// 2) Value of ASPNETCORE_ENVIRONMENT. + /// 3) Default config file name. + /// In each case, overridden file name takes precedence. + /// The first file name that exists in current directory is returned. + /// The fall back options are dab-config.overrides.json/dab-config.json + /// If no file exists, this will return an empty string. + /// + /// Value of ASPNETCORE_ENVIRONMENT variable + /// whether to look for overrides file or not. + /// + public string GetFileNameForEnvironment(string? aspnetEnvironment, bool considerOverrides) + { + string configFileNameWithExtension = string.Empty; + string?[] environmentPrecedence = new[] + { + Environment.GetEnvironmentVariable(RUNTIME_ENVIRONMENT_VAR_NAME), + aspnetEnvironment, + string.Empty + }; + + for (short index = 0; + index < environmentPrecedence.Length + && string.IsNullOrEmpty(configFileNameWithExtension); + index++) + { + if (!string.IsNullOrWhiteSpace(environmentPrecedence[index]) + // The last index is for the default case - the last fallback option + // where environmentPrecedence[index] is string.Empty + // for that case, we still need to get the file name considering overrides + // so need to do an OR on the last index here + || index == environmentPrecedence.Length - 1) + { + configFileNameWithExtension = GetFileName(environmentPrecedence[index], considerOverrides); + } + } + + return configFileNameWithExtension; + } + + /// + /// Generates the config file name and a corresponding overridden file name, + /// With precedence given to overridden file name, returns that name + /// if the file exists in the current directory, else an empty string. + /// + /// Name of the environment to + /// generate the config file name for. + /// whether to look for overrides file or not. + /// + public string GetFileName(string? environmentValue, bool considerOverrides) + { + string fileNameWithoutExtension = _fileSystem.Path.GetFileNameWithoutExtension(_baseConfigFileName); + string fileExtension = _fileSystem.Path.GetExtension(_baseConfigFileName); + string configFileName = + !string.IsNullOrEmpty(environmentValue) + ? $"{fileNameWithoutExtension}.{environmentValue}" + : $"{fileNameWithoutExtension}"; + string configFileNameWithExtension = $"{configFileName}{fileExtension}"; + string overriddenConfigFileNameWithExtension = GetOverriddenName(configFileName); + + if (considerOverrides && DoesFileExistInCurrentDirectory(overriddenConfigFileNameWithExtension)) + { + return overriddenConfigFileNameWithExtension; + } + + if (DoesFileExistInCurrentDirectory(configFileNameWithExtension)) + { + return configFileNameWithExtension; + } + + return string.Empty; + } + + private static string GetOverriddenName(string fileName) + { + return $"{fileName}.overrides{CONFIG_EXTENSION}"; + } + + /// + /// Generates the name of the file based on environment value. + /// NOTE: Input File name should not contain extension + /// + public static string GetEnvironmentFileName(string fileName, string environmentValue) + { + return $"{fileName}.{environmentValue}{CONFIG_EXTENSION}"; + } + + public bool DoesFileExistInCurrentDirectory(string fileName) + { + string currentDir = _fileSystem.Directory.GetCurrentDirectory(); + // Unable to use ILogger because this code is invoked before LoggerFactory + // is instantiated. + if (_fileSystem.File.Exists(_fileSystem.Path.Combine(currentDir, fileName))) + { + // This config file is logged as being found, but may not actually be used! + Console.WriteLine($"Found config file: {fileName}."); + return true; + } + else + { + // Unable to use ILogger because this code is invoked before LoggerFactory + // is instantiated. + Console.WriteLine($"Unable to find config file: {fileName} does not exist."); + return false; + } + } + + /// + /// This method reads the dab.draft.schema.json which contains the link for online published + /// schema for dab, based on the version of dab being used to generate the runtime config. + /// + public override string GetPublishedDraftSchemaLink() + { + string? assemblyDirectory = _fileSystem.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + + if (assemblyDirectory is null) + { + throw new DataApiBuilderException( + message: "Could not get the link for DAB draft schema.", + statusCode: HttpStatusCode.ServiceUnavailable, + subStatusCode: DataApiBuilderException.SubStatusCodes.ErrorInInitialization); + } + + string? schemaPath = _fileSystem.Path.Combine(assemblyDirectory, "dab.draft.schema.json"); + string schemaFileContent = _fileSystem.File.ReadAllText(schemaPath); + Dictionary? jsonDictionary = JsonSerializer.Deserialize>(schemaFileContent, GetSerializationOptions()); + + if (jsonDictionary is null) + { + throw new DataApiBuilderException( + message: "The schema file is misconfigured. Please check the file formatting.", + statusCode: HttpStatusCode.ServiceUnavailable, + subStatusCode: DataApiBuilderException.SubStatusCodes.ErrorInInitialization); + } + + object? additionalProperties; + if (!jsonDictionary.TryGetValue("additionalProperties", out additionalProperties)) + { + throw new DataApiBuilderException( + message: "The schema file doesn't have the required field : additionalProperties", + statusCode: HttpStatusCode.ServiceUnavailable, + subStatusCode: DataApiBuilderException.SubStatusCodes.ErrorInInitialization); + } + + // properties cannot be null since the property additionalProperties exist in the schema file. + Dictionary properties = JsonSerializer.Deserialize>(additionalProperties.ToString()!)!; + + if (!properties.TryGetValue("version", out string? versionNum)) + { + throw new DataApiBuilderException(message: "Missing required property 'version' in additionalProperties section.", + statusCode: HttpStatusCode.ServiceUnavailable, + subStatusCode: DataApiBuilderException.SubStatusCodes.ErrorInInitialization); + } + + return versionNum; + } + + public static string GetMergedFileNameForEnvironment(string fileName, string environmentValue) + { + return $"{fileName}.{environmentValue}.merged{CONFIG_EXTENSION}"; + } + + /// + /// Allows the base config file name to be updated. This is commonly done when the CLI is starting up. + /// + /// + public void UpdateBaseConfigFileName(string fileName) + { + _baseConfigFileName = fileName; + } +} diff --git a/src/Config/RuntimeConfigLoader.cs b/src/Config/RuntimeConfigLoader.cs index 5444ce9a34..e696633d26 100644 --- a/src/Config/RuntimeConfigLoader.cs +++ b/src/Config/RuntimeConfigLoader.cs @@ -2,72 +2,36 @@ // Licensed under the MIT License. using System.Diagnostics.CodeAnalysis; -using System.IO.Abstractions; -using System.Net; -using System.Reflection; using System.Text.Json; using System.Text.Json.Serialization; using Azure.DataApiBuilder.Config.Converters; using Azure.DataApiBuilder.Config.NamingPolicies; using Azure.DataApiBuilder.Config.ObjectModel; -using Azure.DataApiBuilder.Service.Exceptions; using Microsoft.Extensions.Logging; namespace Azure.DataApiBuilder.Config; -/// -/// This class is responsible for loading the runtime config from either a JSON string -/// or a file located on disk, depending on how the service is being run. -/// -/// -/// This class does not maintain any internal state of the loaded config, instead it will -/// always generate a new config when it is requested. -/// -/// To support better testability, the abstraction is provided -/// which allows for mocking of the file system in tests, providing a way to run the test -/// in isolation of other tests or the actual file system. -/// -public class RuntimeConfigLoader +public abstract class RuntimeConfigLoader { - private string _baseConfigFileName; + protected readonly string? _connectionString; - private readonly IFileSystem _fileSystem; - private readonly string? _connectionString; - - public const string CONFIGFILE_NAME = "dab-config"; - public const string CONFIG_EXTENSION = ".json"; - public const string ENVIRONMENT_PREFIX = "DAB_"; - public const string RUNTIME_ENVIRONMENT_VAR_NAME = $"{ENVIRONMENT_PREFIX}ENVIRONMENT"; - public const string RUNTIME_ENV_CONNECTION_STRING = $"{ENVIRONMENT_PREFIX}CONNSTRING"; - public const string ASP_NET_CORE_ENVIRONMENT_VAR_NAME = "ASPNETCORE_ENVIRONMENT"; - public const string SCHEMA = "dab.draft.schema.json"; - - public string ConfigFileName => GetFileNameForEnvironment(Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"), false); - - public RuntimeConfigLoader(IFileSystem fileSystem, string baseConfigFileName = DEFAULT_CONFIG_FILE_NAME, string? connectionString = null) + public RuntimeConfigLoader(string? connectionString = null) { - _fileSystem = fileSystem; - _baseConfigFileName = baseConfigFileName; _connectionString = connectionString; } /// - /// Load the runtime config from the specified path. + /// Returns RuntimeConfig. /// - /// The path to the dab-config.json file. /// The loaded RuntimeConfig, or null if none was loaded. /// True if the config was loaded, otherwise false. - public bool TryLoadConfig(string path, [NotNullWhen(true)] out RuntimeConfig? config) - { - if (_fileSystem.File.Exists(path)) - { - string json = _fileSystem.File.ReadAllText(path); - return TryParseConfig(json, out config, connectionString: _connectionString); - } + public abstract bool TryLoadKnownConfig([NotNullWhen(true)] out RuntimeConfig? config); - config = null; - return false; - } + /// + /// Returns the link to the published draft schema. + /// + /// + public abstract string GetPublishedDraftSchemaLink(); /// /// Parses a JSON string into a RuntimeConfig object @@ -116,6 +80,9 @@ public static bool TryParseConfig(string json, [NotNullWhen(true)] out RuntimeCo return true; } + /// + /// Get Serializer options for the config file. + /// public static JsonSerializerOptions GetSerializationOptions() { JsonSerializerOptions options = new() @@ -134,193 +101,4 @@ public static JsonSerializerOptions GetSerializationOptions() options.Converters.Add(new StringJsonConverterFactory()); return options; } - - /// - /// Tries to load the config file using the filename known to the RuntimeConfigLoader and for the default environment. - /// - /// The loaded RuntimeConfig, or null if none was loaded. - /// True if the config was loaded, otherwise false. - public bool TryLoadKnownConfig([NotNullWhen(true)] out RuntimeConfig? config) - { - return TryLoadConfig(ConfigFileName, out config); - } - - /// - /// Precedence of environments is - /// 1) Value of DAB_ENVIRONMENT. - /// 2) Value of ASPNETCORE_ENVIRONMENT. - /// 3) Default config file name. - /// In each case, overridden file name takes precedence. - /// The first file name that exists in current directory is returned. - /// The fall back options are dab-config.overrides.json/dab-config.json - /// If no file exists, this will return an empty string. - /// - /// Value of ASPNETCORE_ENVIRONMENT variable - /// whether to look for overrides file or not. - /// - public string GetFileNameForEnvironment(string? aspnetEnvironment, bool considerOverrides) - { - string configFileNameWithExtension = string.Empty; - string?[] environmentPrecedence = new[] - { - Environment.GetEnvironmentVariable(RUNTIME_ENVIRONMENT_VAR_NAME), - aspnetEnvironment, - string.Empty - }; - - for (short index = 0; - index < environmentPrecedence.Length - && string.IsNullOrEmpty(configFileNameWithExtension); - index++) - { - if (!string.IsNullOrWhiteSpace(environmentPrecedence[index]) - // The last index is for the default case - the last fallback option - // where environmentPrecedence[index] is string.Empty - // for that case, we still need to get the file name considering overrides - // so need to do an OR on the last index here - || index == environmentPrecedence.Length - 1) - { - configFileNameWithExtension = GetFileName(environmentPrecedence[index], considerOverrides); - } - } - - return configFileNameWithExtension; - } - - /// - /// Returns the default config file name. - /// - public const string DEFAULT_CONFIG_FILE_NAME = $"{CONFIGFILE_NAME}{CONFIG_EXTENSION}"; - - /// - /// Generates the config file name and a corresponding overridden file name, - /// With precedence given to overridden file name, returns that name - /// if the file exists in the current directory, else an empty string. - /// - /// Name of the environment to - /// generate the config file name for. - /// whether to look for overrides file or not. - /// - public string GetFileName(string? environmentValue, bool considerOverrides) - { - string fileNameWithoutExtension = _fileSystem.Path.GetFileNameWithoutExtension(_baseConfigFileName); - string fileExtension = _fileSystem.Path.GetExtension(_baseConfigFileName); - string configFileName = - !string.IsNullOrEmpty(environmentValue) - ? $"{fileNameWithoutExtension}.{environmentValue}" - : $"{fileNameWithoutExtension}"; - string configFileNameWithExtension = $"{configFileName}{fileExtension}"; - string overriddenConfigFileNameWithExtension = GetOverriddenName(configFileName); - - if (considerOverrides && DoesFileExistInCurrentDirectory(overriddenConfigFileNameWithExtension)) - { - return overriddenConfigFileNameWithExtension; - } - - if (DoesFileExistInCurrentDirectory(configFileNameWithExtension)) - { - return configFileNameWithExtension; - } - - return string.Empty; - } - - private static string GetOverriddenName(string fileName) - { - return $"{fileName}.overrides{CONFIG_EXTENSION}"; - } - - /// - /// Generates the name of the file based on environment value. - /// NOTE: Input File name should not contain extension - /// - public static string GetEnvironmentFileName(string fileName, string environmentValue) - { - return $"{fileName}.{environmentValue}{CONFIG_EXTENSION}"; - } - - public bool DoesFileExistInCurrentDirectory(string fileName) - { - string currentDir = _fileSystem.Directory.GetCurrentDirectory(); - // Unable to use ILogger because this code is invoked before LoggerFactory - // is instantiated. - if (_fileSystem.File.Exists(_fileSystem.Path.Combine(currentDir, fileName))) - { - // This config file is logged as being found, but may not actually be used! - Console.WriteLine($"Found config file: {fileName}."); - return true; - } - else - { - // Unable to use ILogger because this code is invoked before LoggerFactory - // is instantiated. - Console.WriteLine($"Unable to find config file: {fileName} does not exist."); - return false; - } - } - - /// - /// This method reads the dab.draft.schema.json which contains the link for online published - /// schema for dab, based on the version of dab being used to generate the runtime config. - /// - public string GetPublishedDraftSchemaLink() - { - string? assemblyDirectory = _fileSystem.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - - if (assemblyDirectory is null) - { - throw new DataApiBuilderException( - message: "Could not get the link for DAB draft schema.", - statusCode: HttpStatusCode.ServiceUnavailable, - subStatusCode: DataApiBuilderException.SubStatusCodes.ErrorInInitialization); - } - - string? schemaPath = _fileSystem.Path.Combine(assemblyDirectory, "dab.draft.schema.json"); - string schemaFileContent = _fileSystem.File.ReadAllText(schemaPath); - Dictionary? jsonDictionary = JsonSerializer.Deserialize>(schemaFileContent, GetSerializationOptions()); - - if (jsonDictionary is null) - { - throw new DataApiBuilderException( - message: "The schema file is misconfigured. Please check the file formatting.", - statusCode: HttpStatusCode.ServiceUnavailable, - subStatusCode: DataApiBuilderException.SubStatusCodes.ErrorInInitialization); - } - - object? additionalProperties; - if (!jsonDictionary.TryGetValue("additionalProperties", out additionalProperties)) - { - throw new DataApiBuilderException( - message: "The schema file doesn't have the required field : additionalProperties", - statusCode: HttpStatusCode.ServiceUnavailable, - subStatusCode: DataApiBuilderException.SubStatusCodes.ErrorInInitialization); - } - - // properties cannot be null since the property additionalProperties exist in the schema file. - Dictionary properties = JsonSerializer.Deserialize>(additionalProperties.ToString()!)!; - - if (!properties.TryGetValue("version", out string? versionNum)) - { - throw new DataApiBuilderException(message: "Missing required property 'version' in additionalProperties section.", - statusCode: HttpStatusCode.ServiceUnavailable, - subStatusCode: DataApiBuilderException.SubStatusCodes.ErrorInInitialization); - } - - return versionNum; - } - - public static string GetMergedFileNameForEnvironment(string fileName, string environmentValue) - { - return $"{fileName}.{environmentValue}.merged{CONFIG_EXTENSION}"; - } - - /// - /// Allows the base config file name to be updated. This is commonly done when the CLI is starting up. - /// - /// - public void UpdateBaseConfigFileName(string fileName) - { - _baseConfigFileName = fileName; - } } - diff --git a/src/Core/Authorization/AuthorizationResolver.cs b/src/Core/Authorization/AuthorizationResolver.cs index 489d11e6bc..a3e4376840 100644 --- a/src/Core/Authorization/AuthorizationResolver.cs +++ b/src/Core/Authorization/AuthorizationResolver.cs @@ -532,7 +532,7 @@ private static string GetClaimValueFromClaim(Match claimTypeMatch, Dictionary /// This class is responsible for exposing the runtime config to the rest of the service. -/// The RuntimeConfigProvider won't directly load the config, but will instead rely on the to do so. +/// The RuntimeConfigProvider won't directly load the config, but will instead rely on the to do so. /// /// /// The RuntimeConfigProvider will maintain internal state of the config, and will only load it once. @@ -40,14 +40,13 @@ public class RuntimeConfigProvider /// public string? ManagedIdentityAccessToken { get; private set; } - private readonly RuntimeConfigLoader _runtimeConfigLoader; - private RuntimeConfig? _runtimeConfig; + public RuntimeConfigLoader ConfigLoader { get; private set; } - public string RuntimeConfigFileName => _runtimeConfigLoader.ConfigFileName; + private RuntimeConfig? _runtimeConfig; public RuntimeConfigProvider(RuntimeConfigLoader runtimeConfigLoader) { - _runtimeConfigLoader = runtimeConfigLoader; + ConfigLoader = runtimeConfigLoader; } /// @@ -63,7 +62,7 @@ public RuntimeConfig GetConfig() return _runtimeConfig; } - if (_runtimeConfigLoader.TryLoadKnownConfig(out RuntimeConfig? config)) + if (ConfigLoader.TryLoadKnownConfig(out RuntimeConfig? config)) { _runtimeConfig = config; } @@ -88,7 +87,7 @@ public bool TryGetConfig([NotNullWhen(true)] out RuntimeConfig? runtimeConfig) { if (_runtimeConfig is null) { - if (_runtimeConfigLoader.TryLoadKnownConfig(out RuntimeConfig? config)) + if (ConfigLoader.TryLoadKnownConfig(out RuntimeConfig? config)) { _runtimeConfig = config; } diff --git a/src/Core/Models/GraphQLFilterParsers.cs b/src/Core/Models/GraphQLFilterParsers.cs index ffd5e3d922..61f80701e4 100644 --- a/src/Core/Models/GraphQLFilterParsers.cs +++ b/src/Core/Models/GraphQLFilterParsers.cs @@ -328,7 +328,7 @@ public HttpContext GetHttpContextFromMiddlewareContext(IMiddlewareContext ctx) { throw new DataApiBuilderException( message: "No HttpContext found in GraphQL Middleware Context.", - statusCode: System.Net.HttpStatusCode.BadRequest, + statusCode: HttpStatusCode.BadRequest, subStatusCode: DataApiBuilderException.SubStatusCodes.BadRequest); } diff --git a/src/Core/Models/HttpContextExtensions.cs b/src/Core/Models/HttpContextExtensions.cs index 5568646b03..cb0c6a8618 100644 --- a/src/Core/Models/HttpContextExtensions.cs +++ b/src/Core/Models/HttpContextExtensions.cs @@ -42,7 +42,7 @@ public static class HttpContextExtensions /// string representing correlation id. public static string GetLoggerCorrelationId(HttpContext? context) { - Guid? correlationId = context is not null ? HttpContextExtensions.GetCorrelationId(context) : null; + Guid? correlationId = context is not null ? GetCorrelationId(context) : null; return correlationId is not null ? $"{correlationId.ToString()!}: " : ""; } } diff --git a/src/Core/Resolvers/MsSqlQueryExecutor.cs b/src/Core/Resolvers/MsSqlQueryExecutor.cs index 469cce91c3..1a64ae2c7a 100644 --- a/src/Core/Resolvers/MsSqlQueryExecutor.cs +++ b/src/Core/Resolvers/MsSqlQueryExecutor.cs @@ -132,7 +132,7 @@ private bool ShouldManagedIdentityAccessBeAttempted() private bool IsDefaultAccessTokenValid() { return _defaultAccessToken is not null && - ((AccessToken)_defaultAccessToken).ExpiresOn.CompareTo(System.DateTimeOffset.Now) > 0; + ((AccessToken)_defaultAccessToken).ExpiresOn.CompareTo(DateTimeOffset.Now) > 0; } /// diff --git a/src/Core/Resolvers/MySqlQueryExecutor.cs b/src/Core/Resolvers/MySqlQueryExecutor.cs index 616795d4ab..8059451f1e 100644 --- a/src/Core/Resolvers/MySqlQueryExecutor.cs +++ b/src/Core/Resolvers/MySqlQueryExecutor.cs @@ -122,7 +122,7 @@ private bool ShouldManagedIdentityAccessBeAttempted() private bool IsDefaultAccessTokenValid() { return _defaultAccessToken is not null && - ((AccessToken)_defaultAccessToken).ExpiresOn.CompareTo(System.DateTimeOffset.Now) > 0; + ((AccessToken)_defaultAccessToken).ExpiresOn.CompareTo(DateTimeOffset.Now) > 0; } /// diff --git a/src/Core/Resolvers/QueryExecutor.cs b/src/Core/Resolvers/QueryExecutor.cs index 64c291ad77..3abb5a3341 100644 --- a/src/Core/Resolvers/QueryExecutor.cs +++ b/src/Core/Resolvers/QueryExecutor.cs @@ -47,7 +47,7 @@ public QueryExecutor(DbExceptionParser dbExceptionParser, ConnectionStringBuilder = connectionStringBuilder; ConfigProvider = configProvider; HttpContextAccessor = httpContextAccessor; - _retryPolicy = Polly.Policy + _retryPolicy = Policy .Handle(DbExceptionParser.IsTransientException) .WaitAndRetryAsync( retryCount: _maxRetryCount, diff --git a/src/Core/Resolvers/Sql Query Structures/SqlQueryStructure.cs b/src/Core/Resolvers/Sql Query Structures/SqlQueryStructure.cs index 01a53beb87..9174202dec 100644 --- a/src/Core/Resolvers/Sql Query Structures/SqlQueryStructure.cs +++ b/src/Core/Resolvers/Sql Query Structures/SqlQueryStructure.cs @@ -443,7 +443,7 @@ private void AddPrimaryKeyPredicates(IDictionary queryParams) { string columnName = parameter.Key; - MetadataProvider.TryGetBackingColumn(base.EntityName, parameter.Key, out string? backingColumnName); + MetadataProvider.TryGetBackingColumn(EntityName, parameter.Key, out string? backingColumnName); if (!string.IsNullOrWhiteSpace(backingColumnName)) { columnName = backingColumnName; diff --git a/src/Core/Resolvers/SqlPaginationUtil.cs b/src/Core/Resolvers/SqlPaginationUtil.cs index 8c41e8f29f..398fdcd349 100644 --- a/src/Core/Resolvers/SqlPaginationUtil.cs +++ b/src/Core/Resolvers/SqlPaginationUtil.cs @@ -459,7 +459,7 @@ public static bool TryResolveJsonElementToScalarVariable( public static string Base64Encode(string plainText) { byte[] plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText); - return System.Convert.ToBase64String(plainTextBytes); + return Convert.ToBase64String(plainTextBytes); } /// @@ -467,7 +467,7 @@ public static string Base64Encode(string plainText) /// public static string Base64Decode(string base64EncodedData) { - byte[] base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData); + byte[] base64EncodedBytes = Convert.FromBase64String(base64EncodedData); return System.Text.Encoding.UTF8.GetString(base64EncodedBytes); } diff --git a/src/Core/Services/GraphQLSchemaCreator.cs b/src/Core/Services/GraphQLSchemaCreator.cs index 3112b4f032..c8fb481e2b 100644 --- a/src/Core/Services/GraphQLSchemaCreator.cs +++ b/src/Core/Services/GraphQLSchemaCreator.cs @@ -160,7 +160,7 @@ DatabaseType.PostgreSQL or { throw new DataApiBuilderException( message: "Column already processed for building ObjectTypeDefinition authorization definition.", - statusCode: System.Net.HttpStatusCode.InternalServerError, + statusCode: HttpStatusCode.InternalServerError, subStatusCode: DataApiBuilderException.SubStatusCodes.ErrorInInitialization ); } diff --git a/src/Service.GraphQLBuilder/GraphQLUtils.cs b/src/Service.GraphQLBuilder/GraphQLUtils.cs index 8ece2ecde5..3b7d10bb1b 100644 --- a/src/Service.GraphQLBuilder/GraphQLUtils.cs +++ b/src/Service.GraphQLBuilder/GraphQLUtils.cs @@ -108,7 +108,7 @@ public static List FindPrimaryKeyFields(ObjectTypeDefinitio throw new DataApiBuilderException( message: "No primary key defined and conventions couldn't locate a fallback", subStatusCode: DataApiBuilderException.SubStatusCodes.ErrorInInitialization, - statusCode: System.Net.HttpStatusCode.ServiceUnavailable); + statusCode: HttpStatusCode.ServiceUnavailable); } } diff --git a/src/Service.Tests/Authentication/Helpers/WebHostBuilderHelper.cs b/src/Service.Tests/Authentication/Helpers/WebHostBuilderHelper.cs index b4b656f2e3..79c95cd10e 100644 --- a/src/Service.Tests/Authentication/Helpers/WebHostBuilderHelper.cs +++ b/src/Service.Tests/Authentication/Helpers/WebHostBuilderHelper.cs @@ -41,7 +41,7 @@ public static async Task CreateWebHost( { // Setup RuntimeConfigProvider object for the pipeline. MockFileSystem fileSystem = new(); - RuntimeConfigLoader loader = new(fileSystem); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider runtimeConfigProvider = new(loader); return await new HostBuilder() diff --git a/src/Service.Tests/Authentication/JwtTokenAuthenticationUnitTests.cs b/src/Service.Tests/Authentication/JwtTokenAuthenticationUnitTests.cs index 159426bead..2946417ed6 100644 --- a/src/Service.Tests/Authentication/JwtTokenAuthenticationUnitTests.cs +++ b/src/Service.Tests/Authentication/JwtTokenAuthenticationUnitTests.cs @@ -284,7 +284,7 @@ private static async Task CreateWebHostCustomIssuer(SecurityKey key) { // Setup RuntimeConfigProvider object for the pipeline. MockFileSystem fileSystem = new(); - RuntimeConfigLoader loader = new(fileSystem); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider runtimeConfigProvider = new(loader); return await new HostBuilder() diff --git a/src/Service.Tests/Authorization/AuthorizationHelpers.cs b/src/Service.Tests/Authorization/AuthorizationHelpers.cs index 7221bdf7ed..f39dc68ea1 100644 --- a/src/Service.Tests/Authorization/AuthorizationHelpers.cs +++ b/src/Service.Tests/Authorization/AuthorizationHelpers.cs @@ -35,8 +35,8 @@ public static class AuthorizationHelpers public static AuthorizationResolver InitAuthorizationResolver(RuntimeConfig runtimeConfig) { MockFileSystem fileSystem = new(); - fileSystem.AddFile(RuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, new(runtimeConfig.ToJson())); - RuntimeConfigLoader loader = new(fileSystem); + fileSystem.AddFile(FileSystemRuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, new(runtimeConfig.ToJson())); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider runtimeConfigProvider = TestHelper.GetRuntimeConfigProvider(loader); Mock metadataProvider = new(); diff --git a/src/Service.Tests/Configuration/AuthenticationConfigValidatorUnitTests.cs b/src/Service.Tests/Configuration/AuthenticationConfigValidatorUnitTests.cs index ebecee88d2..d17a3e1a60 100644 --- a/src/Service.Tests/Configuration/AuthenticationConfigValidatorUnitTests.cs +++ b/src/Service.Tests/Configuration/AuthenticationConfigValidatorUnitTests.cs @@ -20,7 +20,7 @@ public class AuthenticationOptionsValidatorUnitTests private const string DEFAULT_ISSUER = "https://login.microsoftonline.com"; private MockFileSystem _mockFileSystem; - private RuntimeConfigLoader _runtimeConfigLoader; + private FileSystemRuntimeConfigLoader _runtimeConfigLoader; private RuntimeConfigProvider _runtimeConfigProvider; private RuntimeConfigValidator _runtimeConfigValidator; @@ -28,7 +28,7 @@ public class AuthenticationOptionsValidatorUnitTests public void TestInitialize() { _mockFileSystem = new MockFileSystem(); - _runtimeConfigLoader = new RuntimeConfigLoader(_mockFileSystem); + _runtimeConfigLoader = new FileSystemRuntimeConfigLoader(_mockFileSystem); _runtimeConfigProvider = new RuntimeConfigProvider(_runtimeConfigLoader); Mock> logger = new(); _runtimeConfigValidator = new RuntimeConfigValidator(_runtimeConfigProvider, _mockFileSystem, logger.Object); @@ -41,7 +41,7 @@ public void ValidateEasyAuthConfig() CreateRuntimeConfigWithOptionalAuthN(new AuthenticationOptions(EasyAuthType.StaticWebApps.ToString(), null)); _mockFileSystem.AddFile( - RuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, + FileSystemRuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, new MockFileData(config.ToJson()) ); @@ -67,7 +67,7 @@ public void ValidateJwtConfigParamsSet() RuntimeConfig config = CreateRuntimeConfigWithOptionalAuthN(authNConfig); _mockFileSystem.AddFile( - RuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, + FileSystemRuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, new MockFileData(config.ToJson()) ); @@ -86,7 +86,7 @@ public void ValidateAuthNSectionNotNecessary() { RuntimeConfig config = CreateRuntimeConfigWithOptionalAuthN(); _mockFileSystem.AddFile( - RuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, + FileSystemRuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, new MockFileData(config.ToJson()) ); @@ -113,7 +113,7 @@ public void ValidateFailureWithIncompleteJwtConfig() RuntimeConfig config = CreateRuntimeConfigWithOptionalAuthN(authNConfig); _mockFileSystem.AddFile( - RuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, + FileSystemRuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, new MockFileData(config.ToJson()) ); @@ -146,7 +146,7 @@ public void ValidateFailureWithUnneededEasyAuthConfig() RuntimeConfig config = CreateRuntimeConfigWithOptionalAuthN(authNConfig); _mockFileSystem.AddFile( - RuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, + FileSystemRuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, new MockFileData(config.ToJson()) ); @@ -173,7 +173,7 @@ private static RuntimeConfig CreateRuntimeConfigWithOptionalAuthN(Authentication HostOptions hostOptions = new(Cors: null, Authentication: authNConfig); RuntimeConfig config = new( - Schema: RuntimeConfigLoader.SCHEMA, + Schema: FileSystemRuntimeConfigLoader.SCHEMA, DataSource: dataSource, Runtime: new( Rest: new(), diff --git a/src/Service.Tests/Configuration/ConfigurationTests.cs b/src/Service.Tests/Configuration/ConfigurationTests.cs index d3507b394d..9e49b52cd9 100644 --- a/src/Service.Tests/Configuration/ConfigurationTests.cs +++ b/src/Service.Tests/Configuration/ConfigurationTests.cs @@ -40,7 +40,7 @@ using MySqlConnector; using Npgsql; using VerifyMSTest; -using static Azure.DataApiBuilder.Config.RuntimeConfigLoader; +using static Azure.DataApiBuilder.Config.FileSystemRuntimeConfigLoader; namespace Azure.DataApiBuilder.Service.Tests.Configuration { @@ -802,7 +802,7 @@ public void VerifyExceptionOnNullModelinFilterParser() [TestMethod("Validates if deserialization of MsSql config file succeeds."), TestCategory(TestCategory.MSSQL)] public Task TestReadingRuntimeConfigForMsSql() { - return ConfigFileDeserializationValidationHelper(File.ReadAllText($"{RuntimeConfigLoader.CONFIGFILE_NAME}.{MSSQL_ENVIRONMENT}{RuntimeConfigLoader.CONFIG_EXTENSION}")); + return ConfigFileDeserializationValidationHelper(File.ReadAllText($"{CONFIGFILE_NAME}.{MSSQL_ENVIRONMENT}{CONFIG_EXTENSION}")); } /// @@ -812,7 +812,7 @@ public Task TestReadingRuntimeConfigForMsSql() [TestMethod("Validates if deserialization of MySql config file succeeds."), TestCategory(TestCategory.MYSQL)] public Task TestReadingRuntimeConfigForMySql() { - return ConfigFileDeserializationValidationHelper(File.ReadAllText($"{RuntimeConfigLoader.CONFIGFILE_NAME}.{MYSQL_ENVIRONMENT}{RuntimeConfigLoader.CONFIG_EXTENSION}")); + return ConfigFileDeserializationValidationHelper(File.ReadAllText($"{CONFIGFILE_NAME}.{MYSQL_ENVIRONMENT}{CONFIG_EXTENSION}")); } /// @@ -822,7 +822,7 @@ public Task TestReadingRuntimeConfigForMySql() [TestMethod("Validates if deserialization of PostgreSql config file succeeds."), TestCategory(TestCategory.POSTGRESQL)] public Task TestReadingRuntimeConfigForPostgreSql() { - return ConfigFileDeserializationValidationHelper(File.ReadAllText($"{RuntimeConfigLoader.CONFIGFILE_NAME}.{POSTGRESQL_ENVIRONMENT}{RuntimeConfigLoader.CONFIG_EXTENSION}")); + return ConfigFileDeserializationValidationHelper(File.ReadAllText($"{CONFIGFILE_NAME}.{POSTGRESQL_ENVIRONMENT}{CONFIG_EXTENSION}")); } /// @@ -832,7 +832,7 @@ public Task TestReadingRuntimeConfigForPostgreSql() [TestMethod("Validates if deserialization of the CosmosDB_NoSQL config file succeeds."), TestCategory(TestCategory.COSMOSDBNOSQL)] public Task TestReadingRuntimeConfigForCosmos() { - return ConfigFileDeserializationValidationHelper(File.ReadAllText($"{RuntimeConfigLoader.CONFIGFILE_NAME}.{COSMOS_ENVIRONMENT}{RuntimeConfigLoader.CONFIG_EXTENSION}")); + return ConfigFileDeserializationValidationHelper(File.ReadAllText($"{CONFIGFILE_NAME}.{COSMOS_ENVIRONMENT}{CONFIG_EXTENSION}")); } /// @@ -856,8 +856,8 @@ public void TestCommandLineConfigurationProvider() Environment.SetEnvironmentVariable(ASP_NET_CORE_ENVIRONMENT_VAR_NAME, MSSQL_ENVIRONMENT); string[] args = new[] { - $"--ConfigFileName={RuntimeConfigLoader.CONFIGFILE_NAME}." + - $"{COSMOS_ENVIRONMENT}{RuntimeConfigLoader.CONFIG_EXTENSION}" + $"--ConfigFileName={CONFIGFILE_NAME}." + + $"{COSMOS_ENVIRONMENT}{CONFIG_EXTENSION}" }; TestServer server = new(Program.CreateWebHostBuilder(args)); @@ -875,7 +875,7 @@ public void TestRuntimeEnvironmentVariable() Environment.SetEnvironmentVariable( ASP_NET_CORE_ENVIRONMENT_VAR_NAME, MSSQL_ENVIRONMENT); Environment.SetEnvironmentVariable( - RuntimeConfigLoader.RUNTIME_ENVIRONMENT_VAR_NAME, COSMOS_ENVIRONMENT); + RUNTIME_ENVIRONMENT_VAR_NAME, COSMOS_ENVIRONMENT); TestServer server = new(Program.CreateWebHostBuilder(Array.Empty())); @@ -886,7 +886,7 @@ public void TestRuntimeEnvironmentVariable() public void TestConfigIsValid() { TestHelper.SetupDatabaseEnvironment(MSSQL_ENVIRONMENT); - RuntimeConfigLoader configPath = TestHelper.GetRuntimeConfigLoader(); + FileSystemRuntimeConfigLoader configPath = TestHelper.GetRuntimeConfigLoader(); RuntimeConfigProvider configProvider = TestHelper.GetRuntimeConfigProvider(configPath); Mock> configValidatorLogger = new(); @@ -906,26 +906,26 @@ public void TestConfigIsValid() /// has highest precedence irrespective of what the connection string is in the config file. /// Verifying the Exception thrown. /// - [TestMethod($"Validates that environment variable {RuntimeConfigLoader.RUNTIME_ENV_CONNECTION_STRING} has highest precedence."), TestCategory(TestCategory.COSMOSDBNOSQL)] + [TestMethod($"Validates that environment variable {RUNTIME_ENV_CONNECTION_STRING} has highest precedence."), TestCategory(TestCategory.COSMOSDBNOSQL)] public void TestConnectionStringEnvVarHasHighestPrecedence() { Environment.SetEnvironmentVariable(ASP_NET_CORE_ENVIRONMENT_VAR_NAME, COSMOS_ENVIRONMENT); Environment.SetEnvironmentVariable( - RuntimeConfigLoader.RUNTIME_ENV_CONNECTION_STRING, + RUNTIME_ENV_CONNECTION_STRING, "Invalid Connection String"); try { TestServer server = new(Program.CreateWebHostBuilder(Array.Empty())); _ = server.Services.GetService(typeof(CosmosClientProvider)) as CosmosClientProvider; - Assert.Fail($"{RuntimeConfigLoader.RUNTIME_ENV_CONNECTION_STRING} is not given highest precedence"); + Assert.Fail($"{RUNTIME_ENV_CONNECTION_STRING} is not given highest precedence"); } catch (Exception e) { Assert.AreEqual(typeof(ApplicationException), e.GetType()); Assert.AreEqual( $"Could not initialize the engine with the runtime config file: " + - $"{RuntimeConfigLoader.CONFIGFILE_NAME}.{COSMOS_ENVIRONMENT}{RuntimeConfigLoader.CONFIG_EXTENSION}", + $"{CONFIGFILE_NAME}.{COSMOS_ENVIRONMENT}{CONFIG_EXTENSION}", e.Message); } } @@ -947,7 +947,7 @@ public void TestGetConfigFileNameForEnvironment( { MockFileSystem fileSystem = new(); fileSystem.AddFile(expectedRuntimeConfigFile, new MockFileData(string.Empty)); - RuntimeConfigLoader runtimeConfigLoader = new(fileSystem); + FileSystemRuntimeConfigLoader runtimeConfigLoader = new(fileSystem); Environment.SetEnvironmentVariable(ASP_NET_CORE_ENVIRONMENT_VAR_NAME, hostingEnvironmentValue); Environment.SetEnvironmentVariable(RUNTIME_ENVIRONMENT_VAR_NAME, environmentValue); @@ -995,7 +995,7 @@ public async Task TestInteractiveGraphQLEndpoints( const string CUSTOM_CONFIG = "custom-config.json"; TestHelper.SetupDatabaseEnvironment(MSSQL_ENVIRONMENT); FileSystem fileSystem = new(); - RuntimeConfigLoader loader = new(fileSystem); + FileSystemRuntimeConfigLoader loader = new(fileSystem); loader.TryLoadKnownConfig(out RuntimeConfig config); RuntimeConfig configWithCustomHostMode = config with @@ -1421,7 +1421,7 @@ public void TestProductionModeAppServiceEnvironmentCheck(HostMode hostMode, Easy TestHelper.SetupDatabaseEnvironment(TestCategory.MSSQL); FileSystem fileSystem = new(); - RuntimeConfigLoader loader = new(fileSystem); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider configProvider = TestHelper.GetRuntimeConfigProvider(loader); RuntimeConfig config = configProvider.GetConfig(); @@ -1947,7 +1947,7 @@ private static string GenerateMockJwtToken() private static ConfigurationPostParameters GetCosmosConfigurationParameters() { - string cosmosFile = $"{RuntimeConfigLoader.CONFIGFILE_NAME}.{COSMOS_ENVIRONMENT}{RuntimeConfigLoader.CONFIG_EXTENSION}"; + string cosmosFile = $"{CONFIGFILE_NAME}.{COSMOS_ENVIRONMENT}{CONFIG_EXTENSION}"; return new( File.ReadAllText(cosmosFile), File.ReadAllText("schema.gql"), @@ -1957,7 +1957,7 @@ private static ConfigurationPostParameters GetCosmosConfigurationParameters() private static ConfigurationPostParametersV2 GetCosmosConfigurationParametersV2() { - string cosmosFile = $"{RuntimeConfigLoader.CONFIGFILE_NAME}.{COSMOS_ENVIRONMENT}{RuntimeConfigLoader.CONFIG_EXTENSION}"; + string cosmosFile = $"{CONFIGFILE_NAME}.{COSMOS_ENVIRONMENT}{CONFIG_EXTENSION}"; RuntimeConfig overrides = new( null, new DataSource(DatabaseType.CosmosDB_NoSQL, $"AccountEndpoint=https://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==;Database={COSMOS_DATABASE_NAME}", new()), @@ -2168,7 +2168,7 @@ public static EntityPermission GetMinimalPermissionConfig(string roleName) public static string GetConnectionStringFromEnvironmentConfig(string environment) { FileSystem fileSystem = new(); - string sqlFile = new RuntimeConfigLoader(fileSystem).GetFileNameForEnvironment(environment, considerOverrides: true); + string sqlFile = new FileSystemRuntimeConfigLoader(fileSystem).GetFileNameForEnvironment(environment, considerOverrides: true); string configPayload = File.ReadAllText(sqlFile); RuntimeConfigLoader.TryParseConfig(configPayload, out RuntimeConfig runtimeConfig); diff --git a/src/Service.Tests/Configuration/CorsUnitTests.cs b/src/Service.Tests/Configuration/CorsUnitTests.cs index 81d6feff12..6407f69290 100644 --- a/src/Service.Tests/Configuration/CorsUnitTests.cs +++ b/src/Service.Tests/Configuration/CorsUnitTests.cs @@ -45,11 +45,11 @@ public Task TestCorsConfigReadCorrectly() { IFileSystem fileSystem = new MockFileSystem(new Dictionary { - { RuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, new MockFileData(TestHelper.INITIAL_CONFIG) } + { FileSystemRuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, new MockFileData(TestHelper.INITIAL_CONFIG) } }); - RuntimeConfigLoader loader = new(fileSystem); - Assert.IsTrue(loader.TryLoadConfig(RuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, out RuntimeConfig runtimeConfig), "Load runtime config."); + FileSystemRuntimeConfigLoader loader = new(fileSystem); + Assert.IsTrue(loader.TryLoadConfig(FileSystemRuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, out RuntimeConfig runtimeConfig), "Load runtime config."); Config.ObjectModel.HostOptions hostGlobalSettings = runtimeConfig.Runtime.Host; return Verify(hostGlobalSettings); diff --git a/src/Service.Tests/Configuration/RuntimeConfigLoaderTests.cs b/src/Service.Tests/Configuration/RuntimeConfigLoaderTests.cs index 8cd0213714..c92cd5673a 100644 --- a/src/Service.Tests/Configuration/RuntimeConfigLoaderTests.cs +++ b/src/Service.Tests/Configuration/RuntimeConfigLoaderTests.cs @@ -26,7 +26,7 @@ public async Task CanLoadStandardConfig(string configPath) IFileSystem fs = new MockFileSystem(new Dictionary() { { "dab-config.json", new MockFileData(fileContents) } }); - RuntimeConfigLoader loader = new(fs); + FileSystemRuntimeConfigLoader loader = new(fs); Assert.IsTrue(loader.TryLoadConfig("dab-config.json", out RuntimeConfig _), "Failed to load config"); } diff --git a/src/Service.Tests/CosmosTests/TestBase.cs b/src/Service.Tests/CosmosTests/TestBase.cs index 40030ddd4a..e53afd22cb 100644 --- a/src/Service.Tests/CosmosTests/TestBase.cs +++ b/src/Service.Tests/CosmosTests/TestBase.cs @@ -97,7 +97,7 @@ protected WebApplicationFactory SetupTestApplicationFactory() { // Read the base config from the file system TestHelper.SetupDatabaseEnvironment(TestCategory.COSMOSDBNOSQL); - RuntimeConfigLoader baseLoader = TestHelper.GetRuntimeConfigLoader(); + FileSystemRuntimeConfigLoader baseLoader = TestHelper.GetRuntimeConfigLoader(); if (!baseLoader.TryLoadKnownConfig(out RuntimeConfig baseConfig)) { throw new ApplicationException("Failed to load the default CosmosDB_NoSQL config and cannot continue with tests."); @@ -117,9 +117,9 @@ protected WebApplicationFactory SetupTestApplicationFactory() MockFileSystem fileSystem = new(new Dictionary() { { @"../schema.gql", new MockFileData(GRAPHQL_SCHEMA) }, - { RuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, new MockFileData(updatedConfig.ToJson()) } + { FileSystemRuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, new MockFileData(updatedConfig.ToJson()) } }); - RuntimeConfigLoader loader = new(fileSystem); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider provider = new(loader); ISqlMetadataProvider cosmosSqlMetadataProvider = new CosmosSqlMetadataProvider(provider, fileSystem); diff --git a/src/Service.Tests/OpenApiDocumentor/StoredProcedureGeneration.cs b/src/Service.Tests/OpenApiDocumentor/StoredProcedureGeneration.cs index d8d246dbd5..a671d90974 100644 --- a/src/Service.Tests/OpenApiDocumentor/StoredProcedureGeneration.cs +++ b/src/Service.Tests/OpenApiDocumentor/StoredProcedureGeneration.cs @@ -48,7 +48,7 @@ public static async Task ClassInitialize(TestContext context) { TestHelper.SetupDatabaseEnvironment(MSSQL_ENVIRONMENT); FileSystem fileSystem = new(); - RuntimeConfigLoader loader = new(fileSystem); + FileSystemRuntimeConfigLoader loader = new(fileSystem); loader.TryLoadKnownConfig(out RuntimeConfig config); CreateEntities(); diff --git a/src/Service.Tests/SqlTests/GraphQLQueryTests/MsSqlGraphQLQueryTests.cs b/src/Service.Tests/SqlTests/GraphQLQueryTests/MsSqlGraphQLQueryTests.cs index c1d2f255e1..d8353ec7eb 100644 --- a/src/Service.Tests/SqlTests/GraphQLQueryTests/MsSqlGraphQLQueryTests.cs +++ b/src/Service.Tests/SqlTests/GraphQLQueryTests/MsSqlGraphQLQueryTests.cs @@ -371,7 +371,7 @@ await TestConfigTakesPrecedenceForRelationshipFieldsOverDB( public async Task QueryAgainstSPWithOnlyTypenameInSelectionSet() { string dbQuery = "select count(*) as count from books"; - await base.QueryAgainstSPWithOnlyTypenameInSelectionSet(dbQuery); + await QueryAgainstSPWithOnlyTypenameInSelectionSet(dbQuery); } #endregion diff --git a/src/Service.Tests/SqlTests/SqlTestHelper.cs b/src/Service.Tests/SqlTests/SqlTestHelper.cs index 270fc57207..cce53aaeb4 100644 --- a/src/Service.Tests/SqlTests/SqlTestHelper.cs +++ b/src/Service.Tests/SqlTests/SqlTestHelper.cs @@ -254,7 +254,7 @@ public static async Task VerifyResultAsync( /// public static RuntimeConfig SetupRuntimeConfig() { - RuntimeConfigLoader configPath = TestHelper.GetRuntimeConfigLoader(); + FileSystemRuntimeConfigLoader configPath = TestHelper.GetRuntimeConfigLoader(); RuntimeConfigProvider provider = new(configPath); return provider.GetConfig(); diff --git a/src/Service.Tests/TestHelper.cs b/src/Service.Tests/TestHelper.cs index 145690a4cc..a6eb8e0d30 100644 --- a/src/Service.Tests/TestHelper.cs +++ b/src/Service.Tests/TestHelper.cs @@ -18,14 +18,14 @@ static class TestHelper { public static void SetupDatabaseEnvironment(string database) { - Environment.SetEnvironmentVariable(RuntimeConfigLoader.RUNTIME_ENVIRONMENT_VAR_NAME, database); + Environment.SetEnvironmentVariable(FileSystemRuntimeConfigLoader.RUNTIME_ENVIRONMENT_VAR_NAME, database); } public static void UnsetAllDABEnvironmentVariables() { - Environment.SetEnvironmentVariable(RuntimeConfigLoader.RUNTIME_ENVIRONMENT_VAR_NAME, null); - Environment.SetEnvironmentVariable(RuntimeConfigLoader.ASP_NET_CORE_ENVIRONMENT_VAR_NAME, null); - Environment.SetEnvironmentVariable(RuntimeConfigLoader.RUNTIME_ENV_CONNECTION_STRING, null); + Environment.SetEnvironmentVariable(FileSystemRuntimeConfigLoader.RUNTIME_ENVIRONMENT_VAR_NAME, null); + Environment.SetEnvironmentVariable(FileSystemRuntimeConfigLoader.ASP_NET_CORE_ENVIRONMENT_VAR_NAME, null); + Environment.SetEnvironmentVariable(FileSystemRuntimeConfigLoader.RUNTIME_ENV_CONNECTION_STRING, null); } /// @@ -33,10 +33,10 @@ public static void UnsetAllDABEnvironmentVariables() /// /// /// - public static RuntimeConfigLoader GetRuntimeConfigLoader() + public static FileSystemRuntimeConfigLoader GetRuntimeConfigLoader() { FileSystem fileSystem = new(); - RuntimeConfigLoader runtimeConfigLoader = new(fileSystem); + FileSystemRuntimeConfigLoader runtimeConfigLoader = new(fileSystem); return runtimeConfigLoader; } @@ -46,7 +46,7 @@ public static RuntimeConfigLoader GetRuntimeConfigLoader() /// /// /// - public static RuntimeConfigProvider GetRuntimeConfigProvider(RuntimeConfigLoader loader) + public static RuntimeConfigProvider GetRuntimeConfigProvider(FileSystemRuntimeConfigLoader loader) { RuntimeConfigProvider runtimeConfigProvider = new(loader); @@ -106,7 +106,7 @@ public static RuntimeConfig AddMissingEntitiesToConfig(RuntimeConfig config, str /// for unit tests /// public const string SCHEMA_PROPERTY = @" - ""$schema"": """ + RuntimeConfigLoader.SCHEMA + @""""; + ""$schema"": """ + FileSystemRuntimeConfigLoader.SCHEMA + @""""; /// /// Data source property of the config json. This is used for constructing the required config json strings @@ -182,8 +182,8 @@ public static RuntimeConfig AddMissingEntitiesToConfig(RuntimeConfig config, str public static RuntimeConfigProvider GenerateInMemoryRuntimeConfigProvider(RuntimeConfig runtimeConfig) { MockFileSystem fileSystem = new(); - fileSystem.AddFile(RuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, runtimeConfig.ToJson()); - RuntimeConfigLoader loader = new(fileSystem); + fileSystem.AddFile(FileSystemRuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, runtimeConfig.ToJson()); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider runtimeConfigProvider = new(loader); return runtimeConfigProvider; } @@ -198,8 +198,8 @@ public static RuntimeConfigProvider GenerateInMemoryRuntimeConfigProvider(Runtim /// Base route for API requests. public static void ConstructNewConfigWithSpecifiedHostMode(string configFileName, HostMode hostModeType, string databaseType, string runtimeBaseRoute = "/") { - TestHelper.SetupDatabaseEnvironment(databaseType); - RuntimeConfigProvider configProvider = TestHelper.GetRuntimeConfigProvider(TestHelper.GetRuntimeConfigLoader()); + SetupDatabaseEnvironment(databaseType); + RuntimeConfigProvider configProvider = GetRuntimeConfigProvider(GetRuntimeConfigLoader()); RuntimeConfig config = configProvider.GetConfig(); RuntimeConfig configWithCustomHostMode = diff --git a/src/Service.Tests/Unittests/ConfigValidationUnitTests.cs b/src/Service.Tests/Unittests/ConfigValidationUnitTests.cs index 44f752f644..62a4ceebc8 100644 --- a/src/Service.Tests/Unittests/ConfigValidationUnitTests.cs +++ b/src/Service.Tests/Unittests/ConfigValidationUnitTests.cs @@ -124,7 +124,7 @@ public void InvalidCRUDForStoredProcedure( { Entities = new(new Dictionary() { { AuthorizationHelpers.TEST_ENTITY, testEntity } }) }; MockFileSystem fileSystem = new(); - RuntimeConfigLoader loader = new(fileSystem); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider provider = new(loader); RuntimeConfigValidator configValidator = new(provider, fileSystem, new Mock>().Object); @@ -163,7 +163,7 @@ public void InvalidActionSpecifiedForARole(string dbPolicy, EntityActionOperatio databasePolicy: dbPolicy ); MockFileSystem fileSystem = new(); - RuntimeConfigLoader loader = new(fileSystem); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider provider = new(loader); RuntimeConfigValidator configValidator = new(provider, fileSystem, new Mock>().Object); @@ -260,7 +260,7 @@ public void TestAddingRelationshipWithInvalidTargetEntity() ); MockFileSystem fileSystem = new(); - RuntimeConfigLoader loader = new(fileSystem); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider provider = new(loader); RuntimeConfigValidator configValidator = new(provider, fileSystem, new Mock>().Object); Mock _sqlMetadataProvider = new(); @@ -324,7 +324,7 @@ public void TestAddingRelationshipWithDisabledGraphQL() ); MockFileSystem fileSystem = new(); - RuntimeConfigLoader loader = new(fileSystem); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider provider = new(loader); RuntimeConfigValidator configValidator = new(provider, fileSystem, new Mock>().Object); Mock _sqlMetadataProvider = new(); @@ -379,7 +379,7 @@ string relationshipEntity // Mocking EntityToDatabaseObject MockFileSystem fileSystem = new(); - RuntimeConfigLoader loader = new(fileSystem); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider provider = new(loader) { IsLateConfigured = true }; RuntimeConfigValidator configValidator = new(provider, fileSystem, new Mock>().Object); Mock _sqlMetadataProvider = new(); @@ -485,7 +485,7 @@ bool isValidScenario // Mocking EntityToDatabaseObject MockFileSystem fileSystem = new(); - RuntimeConfigLoader loader = new(fileSystem); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider provider = new(loader) { IsLateConfigured = true }; RuntimeConfigValidator configValidator = new(provider, fileSystem, new Mock>().Object); Mock _sqlMetadataProvider = new(); @@ -575,7 +575,7 @@ string linkingObject Entities: new(entityMap)); MockFileSystem fileSystem = new(); - RuntimeConfigLoader loader = new(fileSystem); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider provider = new(loader) { IsLateConfigured = true }; RuntimeConfigValidator configValidator = new(provider, fileSystem, new Mock>().Object); Mock _sqlMetadataProvider = new(); @@ -638,7 +638,7 @@ public void EmptyClaimTypeSuppliedInPolicy(string dbPolicy) databasePolicy: dbPolicy ); MockFileSystem fileSystem = new(); - RuntimeConfigLoader loader = new(fileSystem); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider provider = new(loader); RuntimeConfigValidator configValidator = new(provider, fileSystem, new Mock>().Object); @@ -673,7 +673,7 @@ public void ParseInvalidDbPolicyWithInvalidClaimTypeFormat(string policy) databasePolicy: policy ); MockFileSystem fileSystem = new(); - RuntimeConfigLoader loader = new(fileSystem); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider provider = new(loader); RuntimeConfigValidator configValidator = new(provider, fileSystem, new Mock>().Object); @@ -755,7 +755,7 @@ public void WildCardAndOtherFieldsPresentInIncludeSet(EntityActionOperation acti includedCols: new HashSet { "*", "col2" } ); MockFileSystem fileSystem = new(); - RuntimeConfigLoader loader = new(fileSystem); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider provider = new(loader); RuntimeConfigValidator configValidator = new(provider, fileSystem, new Mock>().Object); @@ -781,7 +781,7 @@ public void WildCardAndOtherFieldsPresentInExcludeSet(EntityActionOperation acti excludedCols: new HashSet { "*", "col1" } ); MockFileSystem fileSystem = new(); - RuntimeConfigLoader loader = new(fileSystem); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider provider = new(loader); RuntimeConfigValidator configValidator = new(provider, fileSystem, new Mock>().Object); @@ -855,7 +855,7 @@ public void TestOperationValidityAndCasing(string operationName, bool exceptionE Entities: new(entityMap)); MockFileSystem fileSystem = new(); - RuntimeConfigLoader loader = new(fileSystem); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider provider = new(loader); RuntimeConfigValidator configValidator = new(provider, fileSystem, new Mock>().Object); if (!exceptionExpected) @@ -1661,7 +1661,7 @@ public void TestFieldInclusionExclusion( RuntimeConfigLoader.TryParseConfig(runtimeConfigString, out RuntimeConfig runtimeConfig); MockFileSystem fileSystem = new(); - RuntimeConfigLoader loader = new(fileSystem); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider provider = new(loader); RuntimeConfigValidator configValidator = new(provider, fileSystem, new Mock>().Object); @@ -1757,7 +1757,7 @@ public void ValidateMisconfiguredColumnSets( RuntimeConfigLoader.TryParseConfig(runtimeConfigString, out RuntimeConfig runtimeConfig); MockFileSystem fileSystem = new(); - RuntimeConfigLoader loader = new(fileSystem); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider provider = new(loader); RuntimeConfigValidator configValidator = new(provider, fileSystem, new Mock>().Object); diff --git a/src/Service.Tests/Unittests/DbExceptionParserUnitTests.cs b/src/Service.Tests/Unittests/DbExceptionParserUnitTests.cs index 69eda1a280..62c3972c40 100644 --- a/src/Service.Tests/Unittests/DbExceptionParserUnitTests.cs +++ b/src/Service.Tests/Unittests/DbExceptionParserUnitTests.cs @@ -45,8 +45,8 @@ public void VerifyCorrectErrorMessage(bool isDeveloperMode, string expected) int connectionEstablishmentError = 53; MockFileSystem fileSystem = new(); - fileSystem.AddFile(RuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, new MockFileData(mockConfig.ToJson())); - RuntimeConfigLoader loader = new(fileSystem); + fileSystem.AddFile(FileSystemRuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, new MockFileData(mockConfig.ToJson())); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider provider = new(loader); Mock parser = new(provider); @@ -79,8 +79,8 @@ public void TestIsTransientExceptionMethod(bool expected, int number) Entities: new(new Dictionary()) ); MockFileSystem fileSystem = new(); - fileSystem.AddFile(RuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, new MockFileData(mockConfig.ToJson())); - RuntimeConfigLoader loader = new(fileSystem); + fileSystem.AddFile(FileSystemRuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, new MockFileData(mockConfig.ToJson())); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider provider = new(loader); DbExceptionParser dbExceptionParser = new MsSqlDbExceptionParser(provider); diff --git a/src/Service.Tests/Unittests/MySqlQueryExecutorUnitTests.cs b/src/Service.Tests/Unittests/MySqlQueryExecutorUnitTests.cs index c8e12a4be5..7b7e8187cd 100644 --- a/src/Service.Tests/Unittests/MySqlQueryExecutorUnitTests.cs +++ b/src/Service.Tests/Unittests/MySqlQueryExecutorUnitTests.cs @@ -52,8 +52,8 @@ public async Task TestHandleManagedIdentityAccess( ); MockFileSystem fileSystem = new(); - fileSystem.AddFile(RuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, new MockFileData(mockConfig.ToJson())); - RuntimeConfigLoader loader = new(fileSystem); + fileSystem.AddFile(FileSystemRuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, new MockFileData(mockConfig.ToJson())); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider provider = new(loader); Mock dbExceptionParser = new(provider); Mock> queryExecutorLogger = new(); diff --git a/src/Service.Tests/Unittests/RestServiceUnitTests.cs b/src/Service.Tests/Unittests/RestServiceUnitTests.cs index 84921d5a56..a16df81f46 100644 --- a/src/Service.Tests/Unittests/RestServiceUnitTests.cs +++ b/src/Service.Tests/Unittests/RestServiceUnitTests.cs @@ -117,8 +117,8 @@ public static void InitializeTest(string restRoutePrefix, string entityName) ); MockFileSystem fileSystem = new(); - fileSystem.AddFile(RuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, new MockFileData(mockConfig.ToJson())); - RuntimeConfigLoader loader = new(fileSystem); + fileSystem.AddFile(FileSystemRuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, new MockFileData(mockConfig.ToJson())); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider provider = new(loader); MsSqlQueryBuilder queryBuilder = new(); Mock dbExceptionParser = new(provider); diff --git a/src/Service.Tests/Unittests/RuntimeConfigLoaderJsonDeserializerTests.cs b/src/Service.Tests/Unittests/RuntimeConfigLoaderJsonDeserializerTests.cs index e5968e8da1..603703415d 100644 --- a/src/Service.Tests/Unittests/RuntimeConfigLoaderJsonDeserializerTests.cs +++ b/src/Service.Tests/Unittests/RuntimeConfigLoaderJsonDeserializerTests.cs @@ -143,7 +143,7 @@ public void TestLoadRuntimeConfigFailures( string exceptionMessage) { MockFileSystem fileSystem = new(); - RuntimeConfigLoader loader = new(fileSystem); + FileSystemRuntimeConfigLoader loader = new(fileSystem); Assert.IsFalse(loader.TryLoadConfig(configFileName, out RuntimeConfig _)); } diff --git a/src/Service.Tests/Unittests/SqlQueryExecutorUnitTests.cs b/src/Service.Tests/Unittests/SqlQueryExecutorUnitTests.cs index 0d1b135328..29dffac0e6 100644 --- a/src/Service.Tests/Unittests/SqlQueryExecutorUnitTests.cs +++ b/src/Service.Tests/Unittests/SqlQueryExecutorUnitTests.cs @@ -79,8 +79,8 @@ public async Task TestHandleManagedIdentityAccess( ); MockFileSystem fileSystem = new(); - fileSystem.AddFile(RuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, new MockFileData(mockConfig.ToJson())); - RuntimeConfigLoader loader = new(fileSystem); + fileSystem.AddFile(FileSystemRuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, new MockFileData(mockConfig.ToJson())); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider provider = new(loader); Mock dbExceptionParser = new(provider); Mock> queryExecutorLogger = new(); @@ -153,8 +153,8 @@ public async Task TestRetryPolicyExhaustingMaxAttempts() ); MockFileSystem fileSystem = new(); - fileSystem.AddFile(RuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, new MockFileData(mockConfig.ToJson())); - RuntimeConfigLoader loader = new(fileSystem); + fileSystem.AddFile(FileSystemRuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME, new MockFileData(mockConfig.ToJson())); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider provider = new(loader) { IsLateConfigured = true @@ -213,7 +213,7 @@ public async Task TestRetryPolicySuccessfullyExecutingQueryAfterNAttempts() { TestHelper.SetupDatabaseEnvironment(TestCategory.MSSQL); FileSystem fileSystem = new(); - RuntimeConfigLoader loader = new(fileSystem); + FileSystemRuntimeConfigLoader loader = new(fileSystem); RuntimeConfigProvider provider = new(loader) { IsLateConfigured = true }; Mock>> queryExecutorLogger = new(); Mock httpContextAccessor = new(); diff --git a/src/Service/Program.cs b/src/Service/Program.cs index b68e55c992..cfb87931f3 100644 --- a/src/Service/Program.cs +++ b/src/Service/Program.cs @@ -172,7 +172,7 @@ private static void AddConfigurationProviders( string[] args) { configurationBuilder - .AddEnvironmentVariables(prefix: RuntimeConfigLoader.ENVIRONMENT_PREFIX) + .AddEnvironmentVariables(prefix: FileSystemRuntimeConfigLoader.ENVIRONMENT_PREFIX) .AddCommandLine(args); } } diff --git a/src/Service/Startup.cs b/src/Service/Startup.cs index 4e9a70d45e..e6884a1364 100644 --- a/src/Service/Startup.cs +++ b/src/Service/Startup.cs @@ -58,12 +58,12 @@ public Startup(IConfiguration configuration, ILogger logger) // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { - string configFileName = Configuration.GetValue("ConfigFileName", RuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME); + string configFileName = Configuration.GetValue("ConfigFileName", FileSystemRuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME); string? connectionString = Configuration.GetValue( - RuntimeConfigLoader.RUNTIME_ENV_CONNECTION_STRING.Replace(RuntimeConfigLoader.ENVIRONMENT_PREFIX, ""), + FileSystemRuntimeConfigLoader.RUNTIME_ENV_CONNECTION_STRING.Replace(FileSystemRuntimeConfigLoader.ENVIRONMENT_PREFIX, ""), null); IFileSystem fileSystem = new FileSystem(); - RuntimeConfigLoader configLoader = new(fileSystem, configFileName, connectionString); + FileSystemRuntimeConfigLoader configLoader = new(fileSystem, configFileName, connectionString); RuntimeConfigProvider configProvider = new(configLoader); services.AddSingleton(fileSystem); @@ -287,13 +287,15 @@ private void AddGraphQLService(IServiceCollection services) public void Configure(IApplicationBuilder app, IWebHostEnvironment env, RuntimeConfigProvider runtimeConfigProvider) { bool isRuntimeReady = false; + FileSystemRuntimeConfigLoader fileSystemRuntimeConfigLoader = (FileSystemRuntimeConfigLoader)runtimeConfigProvider.ConfigLoader; + if (runtimeConfigProvider.TryGetConfig(out RuntimeConfig? runtimeConfig)) { // Config provided before starting the engine. isRuntimeReady = PerformOnConfigChangeAsync(app).Result; if (_logger is not null) { - _logger.LogDebug("Loaded config file from {filePath}", runtimeConfigProvider.RuntimeConfigFileName); + _logger.LogDebug("Loaded config file from {filePath}", fileSystemRuntimeConfigLoader.ConfigFileName); } if (!isRuntimeReady) @@ -304,7 +306,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, RuntimeC _logger.LogError("Exiting the runtime engine..."); } - throw new ApplicationException($"Could not initialize the engine with the runtime config file: {runtimeConfigProvider.RuntimeConfigFileName}"); + throw new ApplicationException($"Could not initialize the engine with the runtime config file: {fileSystemRuntimeConfigLoader.ConfigFileName}"); } } else