Skip to content

Commit

Permalink
[Discovery.Kubernetes] Add settings and setup classes
Browse files Browse the repository at this point in the history
  • Loading branch information
Arkatufus committed Sep 8, 2022
1 parent 86cd5cb commit 6f52857
Show file tree
Hide file tree
Showing 4 changed files with 309 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
// -----------------------------------------------------------------------
// <copyright file="KubernetesDiscoverySettingsSpec.cs" company="Akka.NET Project">
// Copyright (C) 2009-2022 Lightbend Inc. <http://www.lightbend.com>
// Copyright (C) 2013-2022 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
// -----------------------------------------------------------------------

using Akka.Actor;
using Akka.Actor.Setup;
using Akka.Configuration;
using FluentAssertions;
using Xunit;
using static FluentAssertions.FluentActions;

namespace Akka.Discovery.KubernetesApi.Tests
{
public class KubernetesDiscoverySettingsSpec
{
[Fact(DisplayName = "Default settings should contain default values")]
public void DefaultSettingsTest()
{
var settings = KubernetesDiscoverySettings.Create(KubernetesDiscovery.DefaultConfiguration()
.GetConfig("akka.discovery.kubernetes-api"));

settings.ApiCaPath.Should().Be("/var/run/secrets/kubernetes.io/serviceaccount/ca.crt");
settings.ApiTokenPath.Should().Be("/var/run/secrets/kubernetes.io/serviceaccount/token");
settings.ApiServiceHostEnvName.Should().Be("KUBERNETES_SERVICE_HOST");
settings.ApiServicePortEnvName.Should().Be("KUBERNETES_SERVICE_PORT");
settings.PodNamespacePath.Should().Be("/var/run/secrets/kubernetes.io/serviceaccount/namespace");
settings.PodNamespace.Should().BeNull();
settings.PodDomain.Should().Be("cluster.local");
settings.PodLabelSelector("a").Should().Be("app=a");
settings.RawIp.Should().BeTrue();
settings.ContainerName.Should().BeNull();
}

[Fact(DisplayName = "Empty settings should contain default values")]
public void EmptySettingsTest()
{
var empty = KubernetesDiscoverySettings.Empty;
var settings = KubernetesDiscoverySettings.Create(KubernetesDiscovery.DefaultConfiguration()
.GetConfig("akka.discovery.kubernetes-api"));

empty.ApiCaPath.Should().Be(settings.ApiCaPath);
empty.ApiTokenPath.Should().Be(settings.ApiTokenPath);
empty.ApiServiceHostEnvName.Should().Be(settings.ApiServiceHostEnvName);
empty.ApiServicePortEnvName.Should().Be(settings.ApiServicePortEnvName);
empty.PodNamespacePath.Should().Be(settings.PodNamespacePath);
empty.PodNamespace.Should().Be(settings.PodNamespace);
empty.PodDomain.Should().Be(settings.PodDomain);
empty.PodLabelSelector("a").Should().Be(settings.PodLabelSelector("a"));
empty.RawIp.Should().Be(settings.RawIp);
empty.ContainerName.Should().Be(settings.ContainerName);
}

[Fact(DisplayName = "Illegal pod-label-selector must throw")]
public void IllegalPodLabelSelectorTest()
{
var settings = KubernetesDiscoverySettings.Empty;

Invoking(() => settings.WithPodLabelSelector("={0}"))
.Should().ThrowExactly<ConfigurationException>();

Invoking(() => settings.WithPodLabelSelector("a="))
.Should().ThrowExactly<ConfigurationException>();

Invoking(() => settings.WithPodLabelSelector("a=={0}"))
.Should().ThrowExactly<ConfigurationException>();

Invoking(() => settings.WithPodLabelSelector("a{1}={0}"))
.Should().ThrowExactly<ConfigurationException>();

Invoking(() => settings.WithPodLabelSelector("a={0}b"))
.Should().ThrowExactly<ConfigurationException>();
}

[Fact(DisplayName = "Settings With override must work")]
public void WithOverrideTest()
{
var settings = KubernetesDiscoverySettings.Empty
.WithApiCaPath("a")
.WithApiTokenPath("b")
.WithApiServiceHostEnvName("c")
.WithApiServicePortEnvName("d")
.WithPodNamespacePath("e")
.WithPodNamespace("f")
.WithPodDomain("g")
.WithPodLabelSelector("h={0}")
.WithRawIp(false)
.WithContainerName("i");

settings.ApiCaPath.Should().Be("a");
settings.ApiTokenPath.Should().Be("b");
settings.ApiServiceHostEnvName.Should().Be("c");
settings.ApiServicePortEnvName.Should().Be("d");
settings.PodNamespacePath.Should().Be("e");
settings.PodNamespace.Should().Be("f");
settings.PodDomain.Should().Be("g");
settings.PodLabelSelector("a").Should().Be("h=a");
settings.RawIp.Should().BeFalse();
settings.ContainerName.Should().Be("i");
}

[Fact(DisplayName = "Setup override should work")]
public void SetupOverrideTest()
{
var setup = new KubernetesDiscoverySetup
{
ApiCaPath = "a",
ApiTokenPath = "b",
ApiServiceHostEnvName = "c",
ApiServicePortEnvName = "d",
PodNamespacePath = "e",
PodNamespace = "f",
PodDomain = "g",
PodLabelSelector = "h={0}",
RawIp = false,
ContainerName = "i"
};
var settings = setup.Apply(KubernetesDiscoverySettings.Empty);

settings.ApiCaPath.Should().Be("a");
settings.ApiTokenPath.Should().Be("b");
settings.ApiServiceHostEnvName.Should().Be("c");
settings.ApiServicePortEnvName.Should().Be("d");
settings.PodNamespacePath.Should().Be("e");
settings.PodNamespace.Should().Be("f");
settings.PodDomain.Should().Be("g");
settings.PodLabelSelector("a").Should().Be("h=a");
settings.RawIp.Should().BeFalse();
settings.ContainerName.Should().Be("i");
}

[Fact(DisplayName = "Setup override should work inside the module")]
public void ModuleSetupTest()
{
var setup = ActorSystemSetup.Empty
.And(new KubernetesDiscoverySetup
{
ApiCaPath = "a",
ApiTokenPath = "b",
ApiServiceHostEnvName = "c",
ApiServicePortEnvName = "d",
PodNamespacePath = "e",
PodNamespace = "f",
PodDomain = "g",
PodLabelSelector = "h={0}",
RawIp = false,
ContainerName = "i"
});

using (var sys = ActorSystem.Create(nameof(KubernetesDiscoverySettingsSpec), setup))
{
var settings = KubernetesDiscovery.Get(sys).Settings;

settings.ApiCaPath.Should().Be("a");
settings.ApiTokenPath.Should().Be("b");
settings.ApiServiceHostEnvName.Should().Be("c");
settings.ApiServicePortEnvName.Should().Be("d");
settings.PodNamespacePath.Should().Be("e");
settings.PodNamespace.Should().Be("f");
settings.PodDomain.Should().Be("g");
settings.PodLabelSelector("a").Should().Be("h=a");
settings.RawIp.Should().BeFalse();
settings.ContainerName.Should().Be("i");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ public static KubernetesDiscovery Get(ActorSystem system)
public KubernetesDiscovery(ExtendedActorSystem system)
{
system.Settings.InjectTopLevelFallback(DefaultConfiguration());
Settings = new KubernetesDiscoverySettings(system);
Settings = KubernetesDiscoverySettings.Create(system);

var setup = system.Settings.Setup.Get<KubernetesDiscoverySetup>();
if (setup.HasValue)
Settings = setup.Value.Apply(Settings);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,66 @@
// </copyright>
//-----------------------------------------------------------------------

using System.Linq;
using Akka.Actor;
using Akka.Configuration;

#nullable enable
namespace Akka.Discovery.KubernetesApi
{
public sealed class KubernetesDiscoverySettings
{
public static readonly KubernetesDiscoverySettings Empty =
Create(KubernetesDiscovery.DefaultConfiguration().GetConfig("akka.discovery.kubernetes-api"));

public static KubernetesDiscoverySettings Create(ActorSystem system)
=> Create(system.Settings.Config.GetConfig("akka.discovery.kubernetes-api"));

public static KubernetesDiscoverySettings Create(Configuration.Config config)
=> new KubernetesDiscoverySettings(
config.GetString("api-ca-path"),
config.GetString("api-token-path"),
config.GetString("api-service-host-env-name"),
config.GetString("api-service-port-env-name"),
config.GetString("pod-namespace-path"),
config.GetStringIfDefined("pod-namespace"),
config.GetString("pod-domain"),
config.GetString("pod-label-selector"),
config.GetBoolean("use-raw-ip"),
config.GetString("container-name")
);

private readonly string _podLabelSelector;

public KubernetesDiscoverySettings(ExtendedActorSystem system)
private KubernetesDiscoverySettings(
string apiCaPath,
string apiTokenPath,
string apiServiceHostEnvName,
string apiServicePortEnvName,
string podNamespacePath,
string podNamespace,
string podDomain,
string podLabelSelector,
bool rawIp,
string? containerName)
{
var kubernetesApi = system.Settings.Config.GetConfig("akka.discovery.kubernetes-api");
ApiCaPath = kubernetesApi.GetString("api-ca-path");
ApiTokenPath = kubernetesApi.GetString("api-token-path");
ApiServiceHostEnvName = kubernetesApi.GetString("api-service-host-env-name");
ApiServicePortEnvName = kubernetesApi.GetString("api-service-port-env-name");
PodNamespacePath = kubernetesApi.GetString("pod-namespace-path");
PodNamespace = kubernetesApi.GetStringIfDefined("pod-namespace");
PodDomain = kubernetesApi.GetString("pod-domain");
_podLabelSelector = kubernetesApi.GetString("pod-label-selector");
RawIp = kubernetesApi.GetBoolean("use-raw-ip");
var containerName = kubernetesApi.GetString("container-name");
ApiCaPath = apiCaPath;
ApiTokenPath = apiTokenPath;
ApiServiceHostEnvName = apiServiceHostEnvName;
ApiServicePortEnvName = apiServicePortEnvName;
PodNamespacePath = podNamespacePath;
PodNamespace = podNamespace;
PodDomain = podDomain;
if (!podLabelSelector.EndsWith("={0}") ||
podLabelSelector.StartsWith("=") ||
podLabelSelector.Count(c => c == '{') != 1 ||
podLabelSelector.Count(c => c == '}') != 1 ||
podLabelSelector.Count(c => c == '=') != 1)
{
throw new ConfigurationException("pod-label-selector value must be in the form of \"podLabel={0}\"");
}
_podLabelSelector = podLabelSelector;
RawIp = rawIp;
ContainerName = string.IsNullOrWhiteSpace(containerName) ? null : containerName;
}

Expand All @@ -42,6 +80,51 @@ public string PodLabelSelector(string name)
public bool RawIp { get; }
public string? ContainerName { get; }

public KubernetesDiscoverySettings WithApiCaPath(string apiCaPath)
=> Copy(apiCaPath: apiCaPath);
public KubernetesDiscoverySettings WithApiTokenPath(string apiTokenPath)
=> Copy(apiTokenPath: apiTokenPath);
public KubernetesDiscoverySettings WithApiServiceHostEnvName(string apiServiceHostEnvName)
=> Copy(apiServiceHostEnvName: apiServiceHostEnvName);
public KubernetesDiscoverySettings WithApiServicePortEnvName(string apiServicePortEnvName)
=> Copy(apiServicePortEnvName: apiServicePortEnvName);
public KubernetesDiscoverySettings WithPodNamespacePath(string podNamespacePath)
=> Copy(podNamespacePath: podNamespacePath);
public KubernetesDiscoverySettings WithPodNamespace(string podNamespace)
=> Copy(podNamespace: podNamespace);
public KubernetesDiscoverySettings WithPodDomain(string podDomain)
=> Copy(podDomain: podDomain);
public KubernetesDiscoverySettings WithPodLabelSelector(string podLabelSelector)
=> Copy(podLabelSelector: podLabelSelector);
public KubernetesDiscoverySettings WithRawIp(bool rawIp)
=> Copy(rawIp: rawIp);
public KubernetesDiscoverySettings WithContainerName(string containerName)
=> Copy(containerName: containerName);

internal KubernetesDiscoverySettings Copy(
string? apiCaPath = null,
string? apiTokenPath = null,
string? apiServiceHostEnvName = null,
string? apiServicePortEnvName = null,
string? podNamespacePath = null,
string? podNamespace = null,
string? podDomain = null,
string? podLabelSelector = null,
bool? rawIp = null,
string? containerName = null)
=> new KubernetesDiscoverySettings(
apiCaPath: apiCaPath?? ApiCaPath,
apiTokenPath: apiTokenPath?? ApiTokenPath,
apiServiceHostEnvName: apiServiceHostEnvName ?? ApiServiceHostEnvName,
apiServicePortEnvName: apiServicePortEnvName ?? ApiServicePortEnvName,
podNamespacePath: podNamespacePath ?? PodNamespacePath,
podNamespace: podNamespace ?? PodNamespace,
podDomain: podDomain ?? PodDomain,
podLabelSelector: podLabelSelector ?? _podLabelSelector,
rawIp: rawIp ?? RawIp,
containerName: containerName ?? ContainerName
);

public override string ToString()
=> $"Settings({ApiCaPath}, {ApiTokenPath}, {ApiServiceHostEnvName}, {ApiServicePortEnvName}, " +
$"{PodNamespacePath}, {PodNamespace}, {PodDomain})";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// -----------------------------------------------------------------------
// <copyright file="KubernetesDiscoverySetup.cs" company="Akka.NET Project">
// Copyright (C) 2009-2022 Lightbend Inc. <http://www.lightbend.com>
// Copyright (C) 2013-2022 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
// -----------------------------------------------------------------------

using Akka.Actor.Setup;

#nullable enable
namespace Akka.Discovery.KubernetesApi
{
public class KubernetesDiscoverySetup: Setup
{
public string? ApiCaPath { get; set; }
public string? ApiTokenPath { get; set; }
public string? ApiServiceHostEnvName { get; set; }
public string? ApiServicePortEnvName { get; set; }
public string? PodNamespacePath { get; set; }
public string? PodNamespace { get; set; }
public string? PodDomain { get; set; }
public string? PodLabelSelector { get; set; }
public bool? RawIp { get; set; }
public string? ContainerName { get; set; }

internal KubernetesDiscoverySettings Apply(KubernetesDiscoverySettings settings)
=> settings.Copy(
apiCaPath: ApiCaPath,
apiTokenPath: ApiTokenPath,
apiServiceHostEnvName: ApiServiceHostEnvName,
apiServicePortEnvName: ApiServicePortEnvName,
podNamespacePath: PodNamespacePath,
podNamespace: PodNamespace,
podDomain: PodDomain,
podLabelSelector: PodLabelSelector,
rawIp: RawIp,
containerName: ContainerName);

}
}

0 comments on commit 6f52857

Please sign in to comment.