How to Handle Configuration for Multiple Environments in Console App Service?

Written by annakopteva | Published 2021/04/29
Tech Story Tags: programming | c-sharp | dotnet-core | devops | deployment | docker | testing

TLDR Anna Kopteva is a Software Engineer in MTS Digital on the SSO project. Her team developed a service for processing messages from Kafka. Deployment was simple, but when the test team joined us and deployed in a testing environment, we faced another chore - fixing the configuration file manually. Afterward, I attach files with the name of the development environment that appeared in the appsettings.json file to the start of the service. This solution can save time and resources which are very critical for pipeline deployment.via the TL;DR App

Projects grow - sometimes faster than we expect. We know that manual work takes more time. I'll show how I automated the service deployment process after issues caused by adding the test environment. Our team has developed a service for processing messages from Kafka. It is a console application that subscribes to topics, and when messages appear against each of them, a processing algorithm is executed.
During the first iterations, the deployment was quite simple: we publish the service locally, copy build files to the server, create a docker image, and start the service in a container.
We lived like this until the test team joined us and deployed in a testing environment. The appsettings.json configuration file in this environment was different. Therefore, we faced another chore - fixing the configuration file manually. At this stage, the human factor intervened; sometimes, we forgot to edit the file, which led to errors and loss of time.
When we got tired of it, we decided to call DevOps to help. However, it still took time. Therefore I came up with an idea and implemented a quick solution for handling multiple environments. Here are the details:

Initial Conditions

Our service is a console application, and we didn't have out-of-the-box solutions as provided in the ASP.NET Core web application.
The application is launched from the docker container.

Setup Console App

Well, let's see how to use multi-configuration in a console application. First, let's create files for our environments Testing and development:
There is no default nesting in console applications. Therefore, open the .csproj project file and add:
<ItemGroup>
  <Content Include="appsettings.json">
	<CopyToOutputDirectory>Always</CopyToOutputDirectory>
  </Content>
  <Content Include="appsettings.Dev.json;appsettings.Testing.json;">
	<DependentUpon>appsettings.json</DependentUpon>
	<CopyToOutputDirectory>Always</CopyToOutputDirectory>
  </Content>
</ItemGroup>
It looks much better, right? Afterward, I attach files with the name of the development environment that appeared in the appsettings.json file:
The appsettings.{Environment}.json contains parts of the config that change relative to the environment. For example, we change the name of the topics for Kafka in the load testing loop:
{
  "Kafka": {
    "EventMainTopicTitle": "Test_EventMain",
    "EventDelayTopicTitle": "Test_EventDelay",
    "EventRejectTopicTitle": "Test_EventReject"
  }
}
Now, we just need to select the suitable appsettings.json file during the start of the service. To do this, let's make changes to the program class:
/// <summary>
/// Service configuration
/// </summary>
private static IServiceProvider ConfigureServices ()
{
    const string environmentVariableName = "ASPNETCORE_ENVIRONMENT";
    var environmentName =
        Environment.GetEnvironmentVariable (environmentVariable name);

    var services = new ServiceCollection ();
    _configuration = new ConfigurationBuilder ()
        .SetBasePath (Directory.GetParent (AppContext.BaseDirectory) .FullName)
        .AddJsonFile ("appsettings.json")
        .AddJsonFile ($ "appsettings. {EnvironmentName} .json")
        .AddEnvironmentVariables ()
        .Build();
    services.AddSingleton (_configuration);
    services.AddSingleton <KafkaHandler> ();

    return services.BuildServiceProvider ();
}

Setup Docker Container

Now everything is ready to start the service in a docker container.
First, you need to specify the environment variables for the container. There are several ways to do this:
  • command line
  • text file
  • docker compose
I settled on specifying the index in the string. Here's an example script to create an image and run a container:
# Create image
# build docker. -t consoleapp

# Run container on Dev
# docker run -d --env ASPNETCORE_ENVIRONMENT = Dev --name app consoleapp

Conclusion

There are more elegant solutions for pipeline deployment. However, this solution can save time and human resources which are very critical in the early stages of building applications. 
Thanks for your attention and happy coding!

Written by annakopteva | I work as a Software Engineer in MTS Digital on the SSO project. Love programming and corgi!
Published by HackerNoon on 2021/04/29