198 lines
6.8 KiB
C#
198 lines
6.8 KiB
C#
using EntKube.Clusters.Domain;
|
|
using EntKube.Clusters.Features.AdoptCluster;
|
|
using EntKube.Clusters.Features.AdoptCluster.ConfigureComponent;
|
|
using EntKube.Clusters.Infrastructure;
|
|
using EntKube.SharedKernel.Domain;
|
|
using FluentAssertions;
|
|
using Moq;
|
|
|
|
namespace EntKube.Clusters.Tests.Features;
|
|
|
|
public class ConfigureComponentHandlerTests
|
|
{
|
|
private readonly InMemoryClusterRepository repository;
|
|
private readonly Mock<IComponentInstaller> monitoringInstaller;
|
|
private readonly Mock<IComponentInstaller> kyvernoInstaller;
|
|
private readonly ConfigureComponentHandler handler;
|
|
|
|
public ConfigureComponentHandlerTests()
|
|
{
|
|
repository = new InMemoryClusterRepository();
|
|
|
|
monitoringInstaller = new Mock<IComponentInstaller>();
|
|
monitoringInstaller.Setup(i => i.ComponentName).Returns("monitoring");
|
|
|
|
kyvernoInstaller = new Mock<IComponentInstaller>();
|
|
kyvernoInstaller.Setup(i => i.ComponentName).Returns("kyverno");
|
|
|
|
List<IComponentInstaller> installers = new() { monitoringInstaller.Object, kyvernoInstaller.Object };
|
|
handler = new ConfigureComponentHandler(repository, installers);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task HandleAsync_WithValidComponent_CallsConfigureAsync()
|
|
{
|
|
// Arrange — A connected cluster and a request to change Prometheus retention.
|
|
|
|
KubernetesCluster cluster = KubernetesCluster.Register(
|
|
"prod-cluster", "https://k8s.example.com:6443", "kubeconfig", Guid.NewGuid(), "ctx", Guid.NewGuid());
|
|
cluster.MarkConnected();
|
|
await repository.AddAsync(cluster);
|
|
|
|
monitoringInstaller
|
|
.Setup(i => i.ConfigureAsync(cluster, It.IsAny<ComponentConfiguration>(), It.IsAny<CancellationToken>()))
|
|
.ReturnsAsync(new InstallResult(true, "monitoring", "Reconfigured", new List<string> { "retention=90d" }));
|
|
|
|
ConfigureComponentRequest request = new("monitoring", Values: new Dictionary<string, string>
|
|
{
|
|
["retention"] = "90d"
|
|
});
|
|
|
|
// Act
|
|
|
|
Result<InstallResult> result = await handler.HandleAsync(cluster.Id, request);
|
|
|
|
// Assert
|
|
|
|
result.IsSuccess.Should().BeTrue();
|
|
result.Value!.Success.Should().BeTrue();
|
|
result.Value.Message.Should().Be("Reconfigured");
|
|
|
|
monitoringInstaller.Verify(
|
|
i => i.ConfigureAsync(cluster, It.Is<ComponentConfiguration>(c => c.Values["retention"] == "90d"), It.IsAny<CancellationToken>()),
|
|
Times.Once);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task HandleAsync_WithNonExistentCluster_ReturnsFailure()
|
|
{
|
|
// Arrange
|
|
|
|
ConfigureComponentRequest request = new("monitoring", Values: new Dictionary<string, string>
|
|
{
|
|
["retention"] = "90d"
|
|
});
|
|
|
|
// Act
|
|
|
|
Result<InstallResult> result = await handler.HandleAsync(Guid.NewGuid(), request);
|
|
|
|
// Assert
|
|
|
|
result.IsFailure.Should().BeTrue();
|
|
result.Error.Should().Contain("not found");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task HandleAsync_WithDisconnectedCluster_ReturnsFailure()
|
|
{
|
|
// Arrange — Cluster that isn't connected can't be configured.
|
|
|
|
KubernetesCluster cluster = KubernetesCluster.Register(
|
|
"offline-cluster", "https://k8s.example.com:6443", "kubeconfig", Guid.NewGuid(), "ctx", Guid.NewGuid());
|
|
await repository.AddAsync(cluster);
|
|
|
|
ConfigureComponentRequest request = new("monitoring", Values: new Dictionary<string, string>
|
|
{
|
|
["retention"] = "90d"
|
|
});
|
|
|
|
// Act
|
|
|
|
Result<InstallResult> result = await handler.HandleAsync(cluster.Id, request);
|
|
|
|
// Assert
|
|
|
|
result.IsFailure.Should().BeTrue();
|
|
result.Error.Should().Contain("connected");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task HandleAsync_WithUnknownComponent_ReturnsFailure()
|
|
{
|
|
// Arrange — Request an installer that doesn't exist.
|
|
|
|
KubernetesCluster cluster = KubernetesCluster.Register(
|
|
"prod-cluster", "https://k8s.example.com:6443", "kubeconfig", Guid.NewGuid(), "ctx", Guid.NewGuid());
|
|
cluster.MarkConnected();
|
|
await repository.AddAsync(cluster);
|
|
|
|
ConfigureComponentRequest request = new("nonexistent-thing", Values: new Dictionary<string, string>
|
|
{
|
|
["foo"] = "bar"
|
|
});
|
|
|
|
// Act
|
|
|
|
Result<InstallResult> result = await handler.HandleAsync(cluster.Id, request);
|
|
|
|
// Assert
|
|
|
|
result.IsFailure.Should().BeTrue();
|
|
result.Error.Should().Contain("No installer found");
|
|
result.Error.Should().Contain("monitoring");
|
|
result.Error.Should().Contain("kyverno");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task HandleAsync_WhenConfigureFails_ReturnsFailure()
|
|
{
|
|
// Arrange — The installer reports a failure.
|
|
|
|
KubernetesCluster cluster = KubernetesCluster.Register(
|
|
"broken-cluster", "https://k8s.example.com:6443", "kubeconfig", Guid.NewGuid(), "ctx", Guid.NewGuid());
|
|
cluster.MarkConnected();
|
|
await repository.AddAsync(cluster);
|
|
|
|
kyvernoInstaller
|
|
.Setup(i => i.ConfigureAsync(cluster, It.IsAny<ComponentConfiguration>(), It.IsAny<CancellationToken>()))
|
|
.ReturnsAsync(new InstallResult(false, "kyverno", "Helm upgrade failed: timeout", new List<string> { "Error: timeout" }));
|
|
|
|
ConfigureComponentRequest request = new("kyverno", Values: new Dictionary<string, string>
|
|
{
|
|
["admissionReplicas"] = "4"
|
|
});
|
|
|
|
// Act
|
|
|
|
Result<InstallResult> result = await handler.HandleAsync(cluster.Id, request);
|
|
|
|
// Assert
|
|
|
|
result.IsFailure.Should().BeTrue();
|
|
result.Error.Should().Contain("Helm upgrade failed");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task HandleAsync_PassesNamespaceToConfiguration()
|
|
{
|
|
// Arrange — Verify the namespace from the request reaches the installer.
|
|
|
|
KubernetesCluster cluster = KubernetesCluster.Register(
|
|
"prod-cluster", "https://k8s.example.com:6443", "kubeconfig", Guid.NewGuid(), "ctx", Guid.NewGuid());
|
|
cluster.MarkConnected();
|
|
await repository.AddAsync(cluster);
|
|
|
|
monitoringInstaller
|
|
.Setup(i => i.ConfigureAsync(cluster, It.IsAny<ComponentConfiguration>(), It.IsAny<CancellationToken>()))
|
|
.ReturnsAsync(new InstallResult(true, "monitoring", "Done", new List<string>()));
|
|
|
|
ConfigureComponentRequest request = new("monitoring", Namespace: "custom-monitoring", Values: new Dictionary<string, string>
|
|
{
|
|
["retention"] = "7d"
|
|
});
|
|
|
|
// Act
|
|
|
|
Result<InstallResult> result = await handler.HandleAsync(cluster.Id, request);
|
|
|
|
// Assert
|
|
|
|
result.IsSuccess.Should().BeTrue();
|
|
|
|
monitoringInstaller.Verify(
|
|
i => i.ConfigureAsync(cluster, It.Is<ComponentConfiguration>(c => c.Namespace == "custom-monitoring"), It.IsAny<CancellationToken>()),
|
|
Times.Once);
|
|
}
|
|
}
|