Smusdi WEB API configuration
Note
3 environment variables are used to setup the application configuration:
- ASPNETCORE_ENVIRONMENT
- SMUSDI_APPSETTINGS_FOLDER
- SMUSDI_SERVICE_NAME
Implementation overview
The Smusdi service adds some configuration providers to the default ones and update the default json files configuration providers.
var webApplicationOptions = new WebApplicationOptions
{
Args = args,
};
var builder = WebApplication.CreateBuilder(webApplicationOptions)
.InitConfiguration();
And the InitConfiguration extension method:
using Smusdi.Extensibility;
namespace Smusdi.Core.Configuration;
public static class ConfigurationBuilding
{
public static WebApplicationBuilder InitConfiguration(this WebApplicationBuilder webApplicationBuilder, string[]? args)
{
webApplicationBuilder.Configuration.InitConfiguration(webApplicationBuilder.Environment.EnvironmentName, args);
return webApplicationBuilder;
}
public static HostApplicationBuilder InitConfiguration(this HostApplicationBuilder hostApplicationBuilder, string[]? args)
{
hostApplicationBuilder.Configuration.InitConfiguration(hostApplicationBuilder.Environment.EnvironmentName, args);
return hostApplicationBuilder;
}
public static void InitConfiguration(this ConfigurationManager configuration, string environmentName, string[]? args)
{
// Cleanup already registered file config sources as the reset of the base path does not affect the sources, the associated provider is not reset!
foreach (var fileSource in configuration.Sources.OfType<FileConfigurationSource>())
{
fileSource.FileProvider = null;
}
configuration.SetBasePath(GetConfigFilesFolder());
var serviceName = Environment.GetEnvironmentVariable(SmusdiConstants.SmusdiServiceNameEnvVar);
if (!string.IsNullOrWhiteSpace(serviceName))
{
configuration
.AddJsonFile($"appsettings.{serviceName}.json", true, true)
.AddJsonFile($"appsettings.{serviceName}.{environmentName}.json", true, true);
}
if (args is { Length: > 0 })
{
// already done during default construction. But, the previous files may have overwritten these values.
configuration.AddCommandLine(args);
}
configuration
.EnableEnvironmentVariablesExpansion();
}
public static string GetConfigFilesFolder()
{
var basePath = Environment.ExpandEnvironmentVariables(Environment.GetEnvironmentVariable(SmusdiConstants.SmusdiAppsettingsFolderEnvVar) ?? string.Empty);
return Directory.Exists(basePath) ? Path.GetFullPath(basePath) : Directory.GetCurrentDirectory();
}
}
So, currently:
- The base path of the json appsettings file is set to the value of the SMUSDI_APPSETTINGS_FOLDER environment variable if the target folder exists;
-
Two appsettings files are added to the list of the configuration providers:
- appsettings.%SMUSDI_SERVICE_NAME%.json
- appsettings.%SMUSDI_SERVICE_NAME%_%ASPNETCORE_ENVIRONMENT%.json
The appsetting.json and appsettings/%ASPNETCORE_ENVIRONMENT%.json are shared by a list of services and define common settings. The two added ones contain only settings associated to the current service.
- The environment variables founded in the configuration properties are expanded by the provider added by the call to EnableEnvironmentVariablesExpansion().
Specs
Feature: Application settings folder selection
The application must load appsettings file either from local folder, or from folder defined by the environment variable
SMUSDI_APPSETTINGS_FOLDER.
Background:
Given the configuration in current folder
"""
{
"folder": "current"
}
"""
And the configuration in folder 'sub-folder'
"""
{
"folder": "sub-folder"
}
"""
Scenario: Starting the service with variable SMUSDI_APPSETTINGS_FOLDER not set
Given the service initialized
When I start the service
Then the read folder parameter is "current"
Scenario: Starting the service with variable SMUSDI_APPSETTINGS_FOLDER set to sub-folder
Given the environment variable "SMUSDI_APPSETTINGS_FOLDER" set to "sub-folder"
And the service initialized
When I start the service
Then the read folder parameter is "sub-folder"
Feature: Specific appsettings file
When a setting is overridden in the appsettings file specific to the current service, this value must be used instead of the
one defined in the shared file.
Scenario: Starting service with a setting overridden in the specific appsettings file
Given the environment variable "SMUSDI_SERVICE_NAME" set to "myservice"
And the configuration in current folder
"""
{
"folder": "current"
}
"""
And the configuration file "appsettings.myservice.json"
"""
{
"folder": "anotherone"
}
"""
And the service initialized
When I start the service
Then the read folder parameter is "anotherone"
Feature: Environment variables expansion in configuration settings
When a property uses an environement variable, the variable must be expanded before being sent to the application.
Scenario: Starting service with an property in appsettings.json using an environment variable
Given the configuration in current folder
"""
{
"serviceUrl": "http://%TARGET_SERVER%:%TARGET_PORT%"
}
"""
And the environment variable "TARGET_SERVER" set to "myserver.fr.world"
And the environment variable "TARGET_PORT" set to "23457"
And the service initialized
When I start the service
Then the value of the config property "serviceUrl" is "http://myserver.fr.world:23457"
Scenario Outline: Property containing an environement variable that references an environement variable
Given the configuration in current folder
"""
{
"serviceUrl": "http://%TARGET_SERVER%:%TARGET_PORT%"
}
"""
And the environment variable "ENV" set to "int"
And the environment variable "SMUSDI_EXPAND_ENV_TWICE" set to "<SMUSDI_EXPAND_ENV_TWICE>"
And the environment variable "TARGET_SERVER" set to "myserver.%ENV%.fr.world"
And the environment variable "TARGET_PORT" set to "23457"
And the service initialized
When I start the service
Then the value of the config property "serviceUrl" is "<SERVICE_URL>"
Examples:
| SMUSDI_EXPAND_ENV_TWICE | SERVICE_URL |
| | http://myserver.%ENV%.fr.world:23457 |
| dd | http://myserver.%ENV%.fr.world:23457 |
| True | http://myserver.int.fr.world:23457 |
| False | http://myserver.%ENV%.fr.world:23457 |