Skip to content

Commit 0b0a71d

Browse files
authored
Update README with information about expanded keys. (#53)
1 parent 982f47f commit 0b0a71d

1 file changed

Lines changed: 127 additions & 25 deletions

File tree

README.md

Lines changed: 127 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,58 @@
55
[![NuGet version](https://img.shields.io/nuget/v/Winton.Extensions.Configuration.Consul.svg)](https://www.nuget.org/packages/Winton.Extensions.Configuration.Consul)
66
[![NuGet version](https://img.shields.io/nuget/vpre/Winton.Extensions.Configuration.Consul.svg)](https://www.nuget.org/packages/Winton.Extensions.Configuration.Consul)
77

8-
Adds support for configuring .Net Core application using Consul. It is expected that the configuration will be stored as a single object under a given key in Consul. Works great with [git2consul](https://github.com/Cimpress-MCP/git2consul).
8+
Adds support for configuring .NET Core applications using Consul. Works great with [git2consul](https://github.com/Cimpress-MCP/git2consul).
99

1010
## Installation
1111

12-
Add `Winton.Extensions.Configuration.Consul` to the `dependencies` section of your project.json
12+
Add `Winton.Extensions.Configuration.Consul` to your project's dependencies, either via the NuGet package manager or as a `PackageReference` in the csproj file.
1313

1414
## Usage
1515

16-
Add the following to your `StartUp` class for the minimal setup:
16+
### Minimal Setup
17+
The library provides an extension method called `AddConsul` for `IConfigurationBuilder` in the same way that other configuration providers do. The `IConfigurationBuilder` is usually configured in either the `Program` or `Startup` class for an ASP.NET Core application. See Microsoft's [documentation](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-2.1) for more information about `IConfigurationBuilder`.
18+
19+
A minimal example is shown below:
1720

1821
```csharp
1922
var cancellationTokenSource = new cancellationTokenSource();
20-
var builder = new ConfigurationBuilder()
23+
builder
2124
.AddConsul(
22-
$"{env.ApplicationName}.{env.EnvironmentName}",
25+
$"{env.ApplicationName}/{env.EnvironmentName}",
2326
cancellationTokenSource.Token);
24-
Configuration = builder.Build();
2527
```
2628

27-
Assuming the application is running in the development environment and the application name is Website, this will load a json configuration object from the key `Website/Development` in Consul.
29+
Assuming the application is running in the 'Development' environment and the application name is 'Website', then this will load a JSON configuration object from the `Website/Development` key in Consul.
30+
31+
The `CancellationToken` is used to cancel any active requests/watches to/on Consul.
32+
It is recommended that this is cancelled during application shutdown to clean up resources. This will typically be done in one of two places. Either in the `Program` class, for example:
33+
34+
```csharp
35+
public static void Main(string[] args)
36+
{
37+
var cancellationTokenSource = new CancellationTokenSource();
38+
WebHost
39+
.CreateDefaultBuilder(args)
40+
.ConfigureAppConfiguration(
41+
builder => builder.AddConsul("key", cancellationTokenSource.Token))
42+
// Rest of webhost setup
43+
.Build()
44+
.Run();
45+
cancellationTokenSource.Cancel();
46+
}
47+
```
2848

29-
The `CancellationToken` is used to cancel any current requests or watches with Consul.
30-
It is recommended that this is cancelled during application shut down to clean up resources. This can be done like so in the `Configure` method of your `StartUp` class by injecting the `IApplicationLifetime`:
49+
Or in the `Startup` class, for example:
3150

3251
```csharp
52+
public Startup()
53+
{
54+
_cancellationTokenSource = new cancellationTokenSource();
55+
var builder = new ConfigurationBuilder()
56+
.AddConsul("key", _cancellationTokenSource.Token);
57+
Configuration = builder.Build();
58+
}
59+
3360
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime appLifetime)
3461
{
3562
// Other app configuration
@@ -38,35 +65,110 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplica
3865
}
3966
```
4067

41-
An options `Action` can be specified as a third argument to set the options outlined below.
68+
### Options
69+
`AddConsul` has an overload with an additional third parameter of type `Action<IConsulConfigurationSource>` which allows the options outlined below to be set.
4270

43-
## Configuration Options
4471
* **`ConsulConfigurationOptions`**
4572

46-
An `Action` that can be used to configure Consul options
47-
* **`ConsulHttpClientOptions`**
48-
49-
An `Action` that can be used to configure Consul HTTP options
73+
An `Action<ConsulClientConfiguration>` that can be used to configure the underlying Consul client.
5074
* **`ConsulHttpClientHandlerOptions`**
5175

52-
An `Action` that can be used to configure Consul HTTP handler options
53-
* **`OnLoadException`**
76+
An `Action<HttpClientHandler>` that can be used to configure the underlying Consul client's HTTP handler options.
77+
* **`ConsulHttpClientOptions`**
5478

55-
An `Action` that can be used to configure how exceptions should be handled during load
79+
An `Action<HttpClient>` that can be used to configure the underlying Consul client's HTTP options.
5680
* **`OnLoadException`**
5781

58-
An `Action` that can be used to configure how exceptions should be handled that are thrown when watching for changes
82+
An `Action<ConsulLoadExceptionContext>` that can be used to configure how exceptions thrown during the first load should be handled.
83+
* **`OnWatchException`**
84+
85+
An `Action<ConsulWatchExceptionContext>` that can be used to configure how exceptions thrown when watching for changes should be handled.
5986
* **`Optional`**
6087

61-
A `bool` that indicates whether the config is optional. If `false` then will throw during load if the config is missing for the given key.
88+
A `bool` that indicates whether the config is optional. If `false` then it will throw during the first load if the config is missing for the given key. Defaults to `false`.
6289
* **`Parser`**
6390

64-
The parser to use, should match the format of the configuration stored in Consul. Defaults to `JsonConfigurationParser`. Either use those under `Winton.Extensions.Configuration.Consul.Parsers` or create your own by implementing `IConfigurationParser`.
91+
The parser to use, which should match the format of the configuration stored in Consul. Defaults to `JsonConfigurationParser`. Either use those under `Winton.Extensions.Configuration.Consul.Parsers` or create your own by implementing `IConfigurationParser`.
6592
* **`ReloadOnChange`**
6693

6794
A `bool` indicating whether to reload the config when it changes in Consul.
68-
If `true` it will watch the configured key for changes and then reload the config asynchronously and trigger the `IChangeToken` to raise the event that the config has been reloaded.
95+
If `true` it will watch the configured key for changes. When a change occurs the config will be asynchronously reloaded and the `IChangeToken` will be triggered to signal that the config has been reloaded. Defaults to `false`.
96+
97+
## Storing Config as Expanded Keys In Consul
98+
99+
By default this configuration provider will load all key-value pairs from Consul under the specified root key, but by default it assumes that the values of the leaf keys are encoded as JSON.
100+
101+
Take the following example of a particular instance of the Consul KV store:
102+
```
103+
- myApp/
104+
- auth/
105+
{
106+
"appId": "guid",
107+
"claims": [
108+
"email",
109+
"name"
110+
]
111+
}
112+
- logging/
113+
{
114+
"level": "warn"
115+
}
116+
```
69117

70-
## Backlog
71-
* Add more parsers for different file formats
72-
* Add support for expanded configuration where the configuration is a tree of KV pairs under the root key
118+
In this instance we could add Consul as a configuration source like so:
119+
120+
```csharp
121+
var configuration = builder
122+
.AddConsul("myApp", cancellationToken)
123+
.Build();
124+
```
125+
126+
The resultant configuration would contain sections for `auth` and `logging`. As a concrete example `configuration.GetValue<string>("logging:level")` would return `"warn"` and `configuration.GetValue<string>("auth:claims:0")` would return `"email"`.
127+
128+
Sometimes however, config in Consul is stored as a set of expanded keys. For instance, tools such as `consul-cli` load config in this format.
129+
130+
The config in this case can be thought of as a tree under a specific root key in Consul. For instance, continuing with the example above, the config would be stored as:
131+
132+
```
133+
- myApp/
134+
- auth/
135+
- appId/
136+
"guid"
137+
- claims/
138+
0/
139+
"email"
140+
1/
141+
"name"
142+
- logging/
143+
- level/
144+
"warn"
145+
```
146+
147+
As outlined above this configuration provider deals with recursive keys by default. The only difference here is that the values are no longer encoded as JSON. Therefore, in order to load this config the parser must be changed. This can be done like so when adding the configuration provider:
148+
149+
```csharp
150+
builder
151+
.AddConsul(
152+
"myApp",
153+
cancellationToken,
154+
options =>
155+
{
156+
options.Parser = new SimpleConfigurationParser();
157+
});
158+
```
159+
160+
The `SimpleConfigurationParser` expects to encounter a scalar value at each leaf key in the tree.
161+
162+
If you need to support both expanded keys and JSON values then this can be achieved by putting them under different root keys and adding multiple configuration sources. For example:
163+
164+
```csharp
165+
builder
166+
.AddConsul(
167+
"myApp/expandedKeys",
168+
cancellationToken,
169+
options =>
170+
{
171+
options.Parser = new SimpleConfigurationParser();
172+
})
173+
.AddConsul("myApp/jsonValues", cancellationToken);
174+
```

0 commit comments

Comments
 (0)