Skip to content
This repository has been archived by the owner on May 23, 2023. It is now read-only.

v0.4.0-rc2 release #80

Merged
merged 3 commits into from
Mar 5, 2020
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ If you need any information on the supported commands, please execute the `build

This build script is powered by [FAKE](https://fake.build/); please see their API documentation should you need to make any changes to the [`build.fsx`](build.fsx) file.

This library is maintained by Petabridge®. Copyright 2018.
This library is maintained by Petabridge®. Copyright 2015-2020.
5 changes: 3 additions & 2 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
#### 0.4.0-rc1 March 04 2020 ####
* Upgraded to Akka.NET v1.4.1-rc1 and used native environment variable substitution from HOCON
#### 0.4.0-rc2 March 05 2020 ####
* [Array handling rollback and improvements](https://github.com/petabridge/akkadotnet-bootstrap/pull/78)
* Restores startup and diagnostic logging from v0.2.2
96 changes: 78 additions & 18 deletions src/Akka.Bootstrap.Docker.Tests/DockerBootstrapSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using Akka.Configuration;
using FluentAssertions;
using Xunit;
using Hocon;

namespace Akka.Bootstrap.Docker.Tests
{
Expand All @@ -28,9 +29,11 @@ public void ShouldStartIfValidSeedNodesIfSupplied(string seedNodes)
{
Environment.SetEnvironmentVariable("CLUSTER_SEEDS", seedNodes, EnvironmentVariableTarget.Process);
var myConfig = ConfigurationFactory.Empty.BootstrapFromDocker();
Config expected = $"array={seedNodes.ToProperHoconArray(true)}";

myConfig.HasPath("akka.cluster.seed-nodes").Should().BeTrue();
var seeds = myConfig.GetStringList("akka.cluster.seed-nodes").Select(x => x.Trim());
seeds.Should().BeEquivalentTo(seedNodes.Split(",").Select(x => x.Trim()));
var seeds = myConfig.GetStringList("akka.cluster.seed-nodes");
seeds.Should().BeEquivalentTo(expected.GetStringList("array"));
}
finally
{
Expand All @@ -39,6 +42,46 @@ public void ShouldStartIfValidSeedNodesIfSupplied(string seedNodes)
}
}

[Theory]
[InlineData("akka.tcp://MySys@localhost:9140, akka.tcp://MySys@localhost:9141")]
[InlineData("akka.tcp://MySys@localhost:9140, \"akka.tcp://MySys@localhost:9141\"")]
[InlineData("\"akka.tcp://MySys@localhost:9140\", akka.tcp://MySys@localhost:9141")]
[InlineData("[akka.tcp://MySys@localhost:9140, akka.tcp://MySys@localhost:9141]")]
[InlineData("[\"akka.tcp://MySys@localhost:9140\", \"akka.tcp://MySys@localhost:9141\"]")]
public void ToProperHoconArray_ShouldHandleAllPossibleInput(string input)
{
Config config = $"array={input.ToProperHoconArray(true)}";
config.GetStringList("array").Should().BeEquivalentTo(new[] { "akka.tcp://MySys@localhost:9140", "akka.tcp://MySys@localhost:9141" });
}

[Theory]
[InlineData("normal", "normal")]
[InlineData("nor.mal", "nor.mal")]
[InlineData("nor:-\\mal", "\"nor:-\\mal\"")]
[InlineData("nor:-\nmal", "\"\"\"nor:-\nmal\"\"\"")]
public void ToSafeHoconString_ShouldHandleAllPossibleInput(string input, string expected)
{
input.ToSafeHoconString().Should().Be(expected);
}

[Fact]
public void GetConfig_and_FromEnvironment_ShouldBeEqual()
{
try
{
Environment.SetEnvironmentVariable("CLUSTER_IP", "10.0.0.1", EnvironmentVariableTarget.Process);

var config1 = ConfigurationFactory.Empty.FromEnvironment();
var config2 = EnvironmentVariableConfigLoader.GetConfig();
config1.Should().Equals(config2);
}
finally
{
// clean the environment variable up afterwards
Environment.SetEnvironmentVariable("CLUSTER_IP", null);
}
}

[Theory]
[InlineData("localhost")]
[InlineData("127.0.0.1")]
Expand Down Expand Up @@ -87,23 +130,40 @@ public void ShouldStartNormallyIfNotEnvironmentVariablesAreSupplied()
[Fact]
public void ShouldStartIfValidAkkaConfigurationSuppliedByEnvironmentVariables()
{
Environment.SetEnvironmentVariable("AKKA__COORDINATED_SHUTDOWN__EXIT_CLR", "on", EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("AKKA__ACTOR__PROVIDER", "cluster", EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("AKKA__REMOTE__DOT_NETTY__TCP__HOSTNAME", "127.0.0.1", EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("AKKA__REMOTE__DOT_NETTY__TCP__PUBLIC_HOSTNAME", "example.local", EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("AKKA__REMOTE__DOT_NETTY__TCP__PORT", "2559", EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("AKKA__CLUSTER__ROLES__0", "demo", EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("AKKA__CLUSTER__ROLES__1", "test", EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("AKKA__CLUSTER__ROLES__2", "backup", EnvironmentVariableTarget.Process);
try
{
Environment.SetEnvironmentVariable("AKKA__COORDINATED_SHUTDOWN__EXIT_CLR", "on", EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("AKKA__ACTOR__PROVIDER", "cluster", EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("AKKA__REMOTE__DOT_NETTY__TCP__HOSTNAME", "127.0.0.1", EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("AKKA__REMOTE__DOT_NETTY__TCP__PUBLIC_HOSTNAME", "example.local", EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("AKKA__REMOTE__DOT_NETTY__TCP__PORT", "2559", EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("AKKA__CLUSTER__ROLES__0", "demo", EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("AKKA__CLUSTER__ROLES__1", "test", EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("AKKA__CLUSTER__ROLES__2", "backup", EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("AKKA__ARRAY", "[demo, test, backup]", EnvironmentVariableTarget.Process);

var myConfig = ConfigurationFactory.Empty.BootstrapFromDocker();

myConfig.GetBoolean("akka.coordinated-shutdown.exit-clr").Should().BeTrue();
myConfig.GetString("akka.actor.provider").Should().Be("cluster");
myConfig.GetString("akka.remote.dot-netty.tcp.hostname").Should().Be("127.0.0.1");
myConfig.GetString("akka.remote.dot-netty.tcp.public-hostname").Should().Be("example.local");
myConfig.GetInt("akka.remote.dot-netty.tcp.port").Should().Be(2559);
myConfig.GetStringList("akka.cluster.roles").Should().BeEquivalentTo(new [] { "demo", "test", "backup" });
var myConfig = ConfigurationFactory.Empty.BootstrapFromDocker();

myConfig.GetBoolean("akka.coordinated-shutdown.exit-clr").Should().BeTrue();
myConfig.GetString("akka.actor.provider").Should().Be("cluster");
myConfig.GetString("akka.remote.dot-netty.tcp.hostname").Should().Be("127.0.0.1");
myConfig.GetString("akka.remote.dot-netty.tcp.public-hostname").Should().Be("example.local");
myConfig.GetInt("akka.remote.dot-netty.tcp.port").Should().Be(2559);
myConfig.GetStringList("akka.cluster.roles").Should().BeEquivalentTo(new[] { "demo", "test", "backup" });
myConfig.GetStringList("akka.array").Should().BeEquivalentTo(new[] { "demo", "test", "backup" });
}
finally
{
Environment.SetEnvironmentVariable("AKKA__COORDINATED_SHUTDOWN__EXIT_CLR", null);
Environment.SetEnvironmentVariable("AKKA__ACTOR__PROVIDER", null);
Environment.SetEnvironmentVariable("AKKA__REMOTE__DOT_NETTY__TCP__HOSTNAME", null);
Environment.SetEnvironmentVariable("AKKA__REMOTE__DOT_NETTY__TCP__PUBLIC_HOSTNAME", null);
Environment.SetEnvironmentVariable("AKKA__REMOTE__DOT_NETTY__TCP__PORT", null);
Environment.SetEnvironmentVariable("AKKA__CLUSTER__ROLES__0", null);
Environment.SetEnvironmentVariable("AKKA__CLUSTER__ROLES__1", null);
Environment.SetEnvironmentVariable("AKKA__CLUSTER__ROLES__2", null);
Environment.SetEnvironmentVariable("AKKA__ARRAY", null);
}
}
}
}
8 changes: 8 additions & 0 deletions src/Akka.Bootstrap.Docker/Akka.Bootstrap.Docker.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@
<DocumentationFile>bin\Release\netstandard1.6\Akka.Bootstrap.Docker.xml</DocumentationFile>
</PropertyGroup>

<ItemGroup>
<None Remove="Docker.Environment.conf" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="Docker.Environment.conf" />
</ItemGroup>


<ItemGroup>
<PackageReference Include="Akka" Version="$(AkkaVersion)" />
Expand Down
10 changes: 10 additions & 0 deletions src/Akka.Bootstrap.Docker/AssemblyMarker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace Akka.Bootstrap.Docker
{
internal class AssemblyMarker
{
}
}
7 changes: 7 additions & 0 deletions src/Akka.Bootstrap.Docker/Docker.Environment.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
###############################################
# Docker Environment Variable Overrides #
###############################################

akka.remote.dot-netty.tcp.public-hostname = ${?CLUSTER_IP}
akka.remote.dot-netty.tcp.port = ${?CLUSTER_PORT}
environment.seed-nodes = ${?CLUSTER_SEEDS}
56 changes: 36 additions & 20 deletions src/Akka.Bootstrap.Docker/DockerBootstrap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,6 @@
// -----------------------------------------------------------------------

using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Net;
using System.Text;
using Akka.Configuration;
Expand All @@ -23,6 +18,8 @@ namespace Akka.Bootstrap.Docker
/// </summary>
public static class DockerBootstrap
{
private const string DefaultConfigResource = "Akka.Bootstrap.Docker.Docker.Environment.conf";

/// <summary>
/// Extension method intended to chain configuration derived from
/// Docker-supplied environment variables to the front of the fallback chain,
Expand All @@ -38,21 +35,40 @@ public static class DockerBootstrap
/// </example>
public static Config BootstrapFromDocker(this Config input, bool assignDefaultHostName = true)
{
return ConfigurationFactory.Empty
.FromEnvironment()
.WithFallback(
ConfigurationFactory.ParseString(
$@"
akka.remote.dot-netty.tcp {{
hostname=0.0.0.0
public-hostname={Dns.GetHostName()}
}}
"
)
)
.WithFallback(
input
);
var environmentConfig = HoconConfigurationFactory.FromResource<AssemblyMarker>(DefaultConfigResource);

if(!environmentConfig.HasPath("akka.remote.dot-netty.tcp.public-hostname") && assignDefaultHostName)
Console.WriteLine($"[Docker-Bootstrap] Environment variable CLUSTER_IP was not set." +
$"Defaulting to local hostname [{Dns.GetHostName()}] for remote addressing.");

var defaultValues = new StringBuilder();
defaultValues.AppendLine("akka.remote.dot-netty.tcp.hostname=0.0.0.0");

if (assignDefaultHostName)
defaultValues.AppendLine($"akka.remote.dot-netty.tcp.public-hostname={Dns.GetHostName()}");

if (environmentConfig.HasPath("environment.seed-nodes"))
defaultValues.AppendLine(
$"akka.cluster.seed-nodes={environmentConfig.GetString("environment.seed-nodes").ToProperHoconArray(true)}");

var finalConfig = environmentConfig
.WithEnvironmentFallback()
.WithFallback(ConfigurationFactory.ParseString(defaultValues.ToString()))
.WithFallback(input);

Console.WriteLine($"[Docker-Bootstrap] IP={finalConfig.GetString("akka.remote.dot-netty.tcp.public-hostname")}");

if(finalConfig.HasPath("akka.remote.dot-netty.tcp.port"))
Console.WriteLine($"[Docker-Bootstrap] PORT={finalConfig.GetString("akka.remote.dot-netty.tcp.port")}");
else
Console.WriteLine($"[Docker-Bootstrap] PORT=0");

if(finalConfig.HasPath("akka.cluster.seed-nodes"))
Console.WriteLine($"[Docker-Bootstrap] SEEDS={finalConfig.GetStringList("akka.cluster.seed-nodes")}");
else
Console.WriteLine($"[Docker-Bootstrap] SEEDS=[]");

return finalConfig;
}
}
}
Loading