Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix IConfiguration adapter #365

Merged
merged 8 commits into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 113 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -312,8 +312,9 @@ The `dependencyResolver.Props<MySingletonDiActor>()` call will leverage the `Act
## IConfiguration To HOCON Adapter

The `AddHocon` extension method can convert `Microsoft.Extensions.Configuration` `IConfiguration` into HOCON `Config` instance and adds it to the ActorSystem being configured.
* All variable name are automatically converted to lower case.
* All "." (period) in the `IConfiguration` key will be treated as a HOCON object key separator
* Unlike `IConfiguration`, all HOCON key names are **case sensitive**.
* **Unless enclosed inside double quotes**, all "." (period) in the `IConfiguration` key will be treated as a HOCON object key separator
* `IConfiguration` **does not support object composition**, if you declare the same key multiple times inside multiple configuration providers (JSON/environment variables/etc), **only the last one declared will take effect**.
* For environment variable configuration provider:
* "__" (double underline) will be converted to "." (period).
* "_" (single underline) will be converted to "-" (dash).
Expand All @@ -340,16 +341,33 @@ __Example:__
}
}
}
```
```

Environment variables:

```powershell
AKKA__ACTOR__TELEMETRY__ENABLED=true
AKKA__ACTOR__TELEMETRY__ENABLE=true
AKKA__CLUSTER__SEED_NODES__0=akka.tcp//mySystem@localhost:4055
AKKA__CLUSTER__SEED_NODES__1=akka.tcp//mySystem@localhost:4056
AKKA__CLUSTER__SEED_NODE_TIMEOUT=00:00:05
```
```

Note the integer parseable key inside the seed-nodes configuration, seed-nodes will be parsed as an array. These environment variables will be parsed as HOCON settings:

```hocon
akka {
actor {
telemetry.enabled: on
}
cluster {
seed-nodes: [
"akka.tcp//mySystem@localhost:4055",
"akka.tcp//mySystem@localhost:4056"
]
seed-node-timeout: 5s
}
}
```

Example code:

Expand Down Expand Up @@ -392,6 +410,96 @@ var host = new HostBuilder()
});
```

### Special Characters And Case Sensitivity

This advanced usage of the `IConfiguration` adapter is solely used for edge cases where HOCON key capitalization needs to be preserved, such as declaring serialization binding. Note that when you're using this feature, none of the keys are normalized, you will have to write all of your keys in a HOCON compatible way.

`appsettings.json`:

```json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"akka": {
"\"Key.With.Dots\"": "Key Value",
"cluster": {
"roles": [ "front-end", "back-end" ],
"min-nr-of-members": 3,
"log-info": true
}
}
}
```

Note that "Key.With.Dots" needs to be inside escaped double quotes, this is a HOCON requirement that preserves the "." (period) inside HOCON property names.

Environment variables:

```powershell
PS C:/> [Environment]::SetEnvironmentVariable('akka__actor__telemetry__enabled', 'true')
PS C:/> [Environment]::SetEnvironmentVariable('akka__actor__serialization_bindings__"System.Object"', 'hyperion')
PS C:/> [Environment]::SetEnvironmentVariable('akka__cluster__seed_nodes__0', 'akka.tcp//mySystem@localhost:4055')
PS C:/> [Environment]::SetEnvironmentVariable('akka__cluster__seed_nodes__1', 'akka.tcp//mySystem@localhost:4056')
PS C:/> [Environment]::SetEnvironmentVariable('akka__cluster__seed_node_timeout', '00:00:05')
```

Note that:
1. All of the environment variable names are in lower case, except "System.Object" where it needs to preserve name capitalization.
2. To set serialization binding via environment variable, you have to use "." (period) instead of "__" (double underscore), this might be problematic for some shell scripts and there is no way of getting around this.

Example code:

```csharp
/*
Both appsettings.json and environment variables are combined
into HOCON configuration:

akka {
"Key.With.Dots": Key Value
actor {
telemetry.enabled: on
serialization-bindings {
"System.Object" = hyperion
}
}
cluster {
roles: [ "front-end", "back-end" ]
seed-nodes: [
"akka.tcp//mySystem@localhost:4055",
"akka.tcp//mySystem@localhost:4056"
]
min-nr-of-members: 3
seed-node-timeout: 5s
log-info: true
}
}
*/
var host = new HostBuilder()
.ConfigureHostConfiguration(builder =>
{
// Setup IConfiguration to load from appsettings.json and
// environment variables
builder
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables();
})
.ConfigureServices((context, services) =>
{
services.AddAkka("mySystem", (builder, provider) =>
{
// convert IConfiguration to HOCON
var akkaConfig = context.Configuration.GetSection("akka");
// Note the last method argument is set to false
builder.AddHocon(akkaConfig, HoconAddMode.Prepend, false);
});
});
```

[Back to top](#akkahosting)

<a id="microsoftextensionslogging-integration"></a>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ namespace Akka.Hosting
public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddAkka<T>(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, string actorSystemName, System.Action<Akka.Hosting.AkkaConfigurationBuilder, System.IServiceProvider> builder)
where T : Akka.Hosting.AkkaHostedService { }
public static Akka.Hosting.AkkaConfigurationBuilder AddHocon(this Akka.Hosting.AkkaConfigurationBuilder builder, Akka.Configuration.Config hocon, Akka.Hosting.HoconAddMode addMode) { }
public static Akka.Hosting.AkkaConfigurationBuilder AddHocon(this Akka.Hosting.AkkaConfigurationBuilder builder, Microsoft.Extensions.Configuration.IConfiguration configuration, Akka.Hosting.HoconAddMode addMode) { }
public static Akka.Hosting.AkkaConfigurationBuilder AddHocon(this Akka.Hosting.AkkaConfigurationBuilder builder, Microsoft.Extensions.Configuration.IConfiguration configuration, Akka.Hosting.HoconAddMode addMode, bool normalizeKeys = true) { }
public static Akka.Hosting.AkkaConfigurationBuilder AddHoconFile(this Akka.Hosting.AkkaConfigurationBuilder builder, string hoconFilePath, Akka.Hosting.HoconAddMode addMode) { }
public static Akka.Hosting.AkkaConfigurationBuilder AddSetup(this Akka.Hosting.AkkaConfigurationBuilder builder, Akka.Actor.Setup.Setup setup) { }
public static Akka.Hosting.AkkaConfigurationBuilder WithActorAskTimeout(this Akka.Hosting.AkkaConfigurationBuilder builder, System.TimeSpan timeout) { }
Expand Down Expand Up @@ -187,7 +187,7 @@ namespace Akka.Hosting.Configuration
{
public static class ConfigurationHoconAdapter
{
public static Akka.Configuration.Config ToHocon(this Microsoft.Extensions.Configuration.IConfiguration config) { }
public static Akka.Configuration.Config ToHocon(this Microsoft.Extensions.Configuration.IConfiguration config, bool normalizeKeys = true) { }
}
}
namespace Akka.Hosting.Coordination
Expand Down
Loading
Loading