Skip to content Skip to sidebar Skip to footer

Steeltoe Config Server Reads Yml but Not Jjson

When yous design a modern application, and so many new "doors" are opened as you. One topic that yous should ponder: configuration. Information technology's not a very exciting topic like say, Kubernetes. But configuration has tremendous long term effects on the success of your application. The departure between a successful, quickly improving app and an unmaintainable organization can come down to how your app's configuration is managed.

How do you avoid a messy jumble of configuration management? Offset, you can dominion out holding settings internally to the app that's definitely not an selection. Hard coding values in a compiled artifact is so '90s, allow's movement on. Attaching a .config file to each case of the application is as well not reasonable. Yep, you externalized config values from the antiquity. Only y'all're no better off with managing and updating things.

So you're left with 2 options: environs variables and external configuration servers. Both are best practices when managing app settings in the cloud.

Just which one is the best for your use case? How do y'all cull one over the other? Let'due south talk virtually that.

Environs Variables: A Solid Choice, only Not at Scale

Environment variables are piece of cake to manage, but it lacks flexibility at scale. Variables can be globalized to each environs the app is promoted through (dev, QA, load-test, prod), but not much further. And what about refreshing the values, and keeping rails of those changes? Depending on your choice of runtime, your app might require a redeployment (or re-containerization) for each update in config values. Fifty-fifty for the most advanced cloud platforms, an app restart is needed.

Surround variables can exist the correct choice. Just realize that as instances grow, so must the app'south supporting systems.

External Configuration Server: More Complexity, merely Unremarkably Worth the Effort

With an external configuration server, you lot tin can relish greater accessibility and flexibility. There are other benefits too, namely nothing reanimation updates to values, and the separation of duties.

And so what's the take hold of? More dependencies, and more complexity. For example, nearly systems won't take a single awarding using the configuration; it volition be shared with multiple apps.

To help you evaluate these options, let'due south consider an example. But for fun, we can add together another twist: the freedom to use your own framework. There's no reason in these modern times that teams developing for different runtimes can't share the same configurations.

Using Steeltoe and Microsoft.Extensions for Your Config

Steeltoe offers superb options for .Internet applications looking to swallow values from an (external) config server, namely Bound Cloud Config. Now, you might be thinking about "framework lock-in", or "being at the mercy of that framework'southward pace of .Cyberspace adoption." Information technology'south only natural to be cautious.

But hither'due south the exciting thing: Steeltoe only extends all the rich features of the .NET Core runtime, not implementing everything from scratch! Under the covers, Steeltoe is native C# goodness. Remember, .NET Core is a runtime for many use cases, not just  cloud-native apps. (Of grade, Steeltoe adds in a little cloud-native opinion on meridian, to make it much easier to follow best practices for microservices management and security.)

Here's a fun fact. Microsoft.Extensions can be implemented in many different types of projects: MVC, Web Api, Forms, WCF, and others. The cyberspace effect for you lot, the developer: you can implement configuration management for all these unlike types apps exactly the aforementioned style! That ways sharing configuration models across your mobile app, API, desktop app, and console batch jobs. You can confidently promote your code through testing environments and to production in configuration harmony.

Let Microsoft.Extensions.Configuration Handle The Difficult Work

Consider a traditional .NET app. You likely take configuration coming from multiple directions. You are probably used to dealing with web.config, web.dev.config, spider web.test.config, surround variables, possibly a database holding values, command line arguments, and (even worse) a apartment .txt file.

You can't but merely call back a value from each of these config sources. You take to manage its availability, provide default values, parse the values into something structured, and (possibly the most complex) manage precedence of who overwrites who. If that's non toil, I don't know what is!

Microsoft.Extensions.Configuration takes a lot of that overhead away with its "different source providers" feature. Let's say y'all have different configuration values coming from appsettings.json and environment variables, with a rule that the environs variables should overwrite a matching value from both.

To attain this, simply tell your .NET Core app to expect in both places by placing the call to AddEnvironmentVariables() afterward the call to AddJsonFile(), and voila! You lot've established precedence.

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>  WebHost.CreateDefaultBuilder(args)    .ConfigureAppConfiguration((hostingContext, config) => {      config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)      config.AddEnvironmentVariables();    })    .UseStartup<Startup>();

To call back these values, you at present have one simple, structured place to reference - the Configuration Interface. Let's await at an example of retrieving a config value in a Controller. Using the dependency injection characteristic of .NET Core, simply inject the IConfiguration bundle in the constructor, and so reference the config equally a central/value collection.

public class HomeController : Controller {  private IConfiguration _config;  private string _myValue;   public HomeController(IConfiguration config) {     _config = config;      _myValue = _config["some-value"];  }  ... }

You can read further most Configuration, the options inside, and more notably the different types supported in the .Internet Core docs.

Now that you know how configuration is abstracted in mod .NET, let'south look at how Steeltoe uses these concepts to make  cloud-native design fifty-fifty easier.

Steeltoe Manages the External Config Server

You may have heard of The 12 Factor app, the design techniques that every cloud native application should follow. The third factor "Config" states that "A litmus test for whether an app has all config correctly factored out of the lawmaking is whether the codebase could be made open source at any moment, without compromising any credentials." To extend that exam, what if another development squad using a different runtime needed to share configuration with your app? How easily could that happen?

With an external config server, similar Spring Cloud Config Server, information technology's like shooting fish in a barrel to create these types of tests. Simply create a separate Git repo that holds a config file (yml, or equivalent name/value pairs). When information technology changes, the app automatically sees it.

But what does "app automatically sees it" mean? Well, that'due south how the Steeltoe.Configuration component implements Microsoft.Extensions.Configuration. A developer tin can use an external Spring Cloud Config Server with Steeltoe.

The relevant snippet of Program.cs looks like this:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>  WebHost.CreateDefaultBuilder(args)     .UseCloudFoundryHosting()    .AddConfigServer()    .UseStartup<Startup>();

Y'all tin add a course to concord config values…

public form MyConfiguration {    public string Property1 { get; set; }    public string Property2 { get; fix; } }

Then modify Startup.cs…

public void ConfigureServices(IServiceCollection services) {  // Setup Options framework with DI  services.AddOptions();   // Configure IOptions<MyConfiguration>  services.Configure<MyConfiguration>(Configuration);  ... }

The fundamentals are still post-obit the configuration principles discussed in the before "Let Microsoft.Extensions.Configuration Handle The Hard Work" department. We've introduced a new concept known as the "options pattern."  The idea here is to extend configuration capabilities past using classes to represent a group of configuration values. Information technology is implemented via the Microsoft.Extensions.Options.ConfigurationExtensions bundle.

In the in a higher place example, UseCloudFoundryHosting() retrieved the connexion properties provided past the platform for connecting to its Spring Deject Config Server instance via a custom configuration provider. Then AddConfigServer() used those config values to retrieve the properties from the config server. Considering we gave the app further direction to load our property values into a custom object [services.Configure<MyConfiguration>], nosotros at present have external config values for consumption.

There's a lot going on with a little amount of code. Below is the result—the ability to reference config values in a simple, structured mode.

public class HomeController : Controller {    public HomeController(IOptions<MyConfiguration> myOptions) {        MyOptions = myOptions.Value;    }     MyConfiguration MyOptions { get; private ready; }     // GET: /<controller>/    public IActionResult Index() {        ViewData["property1"] = MyOptions.Property1;        ViewData["property2"] = MyOptions.Property2;        render View();    } }

As a bonus, you can innovate a kind of blue/light-green deployment when the values alter. Spin up a new example of the app. Your nifty new lawmaking will remember the latest values, and monitor the logs. If everything looks good, you can then cease the original app instance. Congratulations, y'all have refreshed a config value with no reanimation!

Stateless Applications Working with its Platform

Surround variables are a key component of an app running on a modern platform. It's not simply nigh configuration; it's too a fashion for the platform to "talk" to the app. Why should a stateless, portable app demand to care about its platform? Or its environment for that thing? Information technology doesn't!

It may seem a chip counter-intuitive, but the platform needs to "tell" the app what services have been bound to it, and if any startup customizations are expected. These are communicated in the form of environment variables.

Take Deject Foundry for example. It offers two surround variables to every app instance running equally VCAP_APPLICATION and VCAP_SERVICES. The value of these VARS is a json formatted cord with details almost how that specific app example has been deployed. For VCAP_APPLICATION, this covers bound routes, app proper noun, and space (environment) name are but a few. Meanwhile, the VCAP_SERVICES var has (you guessed it) information nigh what services have been bound to the application. Information technology'll encompass things like service proper noun, plan, tags, and all the connection details.

Having all that rich information is very valuable. But who wants to deal with parsing the json, managing exceptions, and other gruntwork? You want to exist the best developer y'all can be, and create concern value by working on the of import stuff, like new features and issues fixes.

This is where configuration components come in. The Steeltoe team saw how .NET Core configuration providers made consuming environment variables so easy. So they used that with the structure of the VCAP_* values to create the Steeltoe Deject Foundry configuration provider.

This is quite similar to how values are retrieved from an external Spring Deject Config server. The Cloud Foundry config provider offers a simple, structured object containing the VCAP values. And it's all thank you to .NET Core'due south custom configuration provider.

Configuration Default Values and Dynamic Placeholders

You have many unlike ways to feed configuration values to your app. Two challenges come to mind. Get-go, how and where will a value become defaulted. Second, the local development environs and the product environment need to be every bit similar every bit possible - especially with how configuration values are evaluated.

Of course Microsoft'south Configuration provider along with the Steeltoe Framework have a simple respond to these challenges. We tin start with a look at the ordering of the providers when you build the WebHost.

In Program.cs...

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>  WebHost.CreateDefaultBuilder(args)     .ConfigureAppConfiguration((hostingContext, config) => {       config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: false);       config.AddCommandLine(args)       config.AddEnvironmentVariables()     }     .UseStartup<Startup>();

Now, consider providing the same labeled value first in appsettings.json as "123" and and so as  "456" in environment variables. No values are provided as arguments when the app starts upwards. In the end, the app is going to run into the value every bit "456" considering that was the terminal provider to exist parsed.

There's some other piece of the puzzle that isn't so obvious. Notice our example uses CreateDefaultBuilder to create the WebHost, equally opposed to creating a new case of WebHostBuilder and manual configuration. We tin can look to the WebHost.CreateDefaultBuilder docs to see what is loaded and in what gild.

Here's the sequence:

  • use Kestrel equally the web server and configure it using the application's configuration providers

  • set the ContentRootPath to the result of GetCurrentDirectory()

  • load IConfiguration from 'appsettings.json' and 'appsettings.[EnvironmentName].json'

  • load IConfiguration from User Secrets when EnvironmentName is 'Development' using the entry assembly

  • load IConfiguration from environment variables

  • load IConfiguration from supplied command line args

  • configure the ILoggerFactory to log to the panel and debug output

  • enable IIS integration.

Look at that! IConfiguration already loaded appsettings.json and its derivatives, plus environs variables and command line args. Then why did we specifically call out appsettings.json, if it's a default of CreateDefaultBuilder? Considering the app needed to load the Configuration Providers in a dissimilar order, thus giving the app a unlike way to set default values. This is often a overnice pick when switching environments.

What most a middle ground between relying on surround variables for values, and implementing a configuration server? One may not offering enough flexibility; the other may be overkill for the app. Steeltoe introduces a provider called Placeholder. The idea here is to enable an app to define configuration values as placeholders. Then they can exist  resolved to real values at runtime during configuration access. A placeholder takes the grade of ${key:subkey1:subkey2?default_value} where cardinal:subkey1:subkey2 represents some other key in the configuration.

Lets wait at an implementation of Placeholders. Commencement set values in appsettings.json...

// appsettings.json {  "Logging": {    "LogLevel": {      "Default": "Alarm"    }  },  "AllowedHosts": "*",  "ResolvedPlaceholderFromEnvVariables": "${PATH?NotFound}",  "UnresolvedPlaceholder": "${SomKeyNotFound?NotFound}",  "ResolvedPlaceholderFromJson": "${Logging:LogLevel:System?${Logging:LogLevel:Default?NotFound}}" }   // appsettings.Evolution.json {  "Logging": {    "LogLevel": {      "Default": "Debug",      "System": "Information",      "Microsoft": "Data"    }  } }

Notice ResolvedPlaceholderFromEnvVariables uses a placeholder that references the PATH surround variable. As we saw to a higher place, WebHost.CreateDefaultBuilder automatically loads environment variables. Likewise discover ResolvedPlaceholderFromJson uses a placeholder that references keys that come from the .json configuration files. WebHost.CreateDefaultBuilder loads applicable .json files just equally it did the surroundings variables. But wait! There's a (somewhat) hidden precious stone in the AddJsonFile provider.

E'er wondered almost the accompanying parameter reloadOnChange: true/fake?

Because appsettings.json isn't compiled in the app artifact a value tin can be changed within, while the app is running. Set reloadOnChange to "true," employ the Options Design, and your app will automatically refresh live values. That'due south pretty cool!

Is this just more toil I'g asking you to accept on? Of course not, I wouldn't practice that to you. Steeltoe takes care of all the hard piece of work. But implement the PlaceHolder provider and get on with edifice smashing software!

Getting Started

Now information technology's time for you to put all these features to the test. Fortunately, there are quite a few options to go started.

Sean McKenna gave a overnice rundown of Cloud Foundry on Azure Friday, and the Azure Marketplace offers a really easy way to go going with Cloud Foundry. Catch the sample apps in the Steeltoe Github Samples repo forth with the docs on the Steeltoe site, and the next stop is cloud-native .NET.

If you'd similar to work locally, the Steeltoe team has published some Docker Files to help get started. Combine this with the sample apps in the Steeltoe Github repo and you lot can go a local .NET Core app instance running with Steeltoe in no fourth dimension.

If you adopt a pre-configured platform, caput on over to Pivotal Spider web Services and create a free business relationship. This will requite you access to a fully productionized Cloud Foundry platform. Catch the sample apps in the Steeltoe Github Samples repo along with the docs on the Steeltoe site, and y'all are off to the races.

Cloud native .NET hither we come!


Learn more than

  • Webinar: Learn Deject-Native .NET: Cadre Configuration Fundamentals with Steeltoe
  • Training: Pivotal Cloud-Native .NET Developer (with Steeltoe)
  • eBook: Modernizing .NET Applications

About the Author

David Dieruf

David is a function of the tech marketing team within VMware Tanzu, bringing a focus to .Cyberspace-related technologies. He has been writing C# for as long every bit it'due south been a matter. In his spare time he enjoys breaking things, merely to set them. Prior to VMware, David had a wide-ranging background, from making things get fast to building computers to writing bad code.

Follow on Linkedin More Content by David Dieruf

johnsonmadis1978.blogspot.com

Source: https://tanzu.vmware.com/content/blog/using-microsoft-configuration-extensions-with-steeltoe

Post a Comment for "Steeltoe Config Server Reads Yml but Not Jjson"