too much for one commit
This commit is contained in:
183
tests/EntKube.Clusters.Tests/Features/ClusterSettingsTests.cs
Normal file
183
tests/EntKube.Clusters.Tests/Features/ClusterSettingsTests.cs
Normal file
@@ -0,0 +1,183 @@
|
||||
using EntKube.Clusters.Domain;
|
||||
using EntKube.Clusters.Features.ClusterSettings;
|
||||
using EntKube.Clusters.Infrastructure;
|
||||
using EntKube.SharedKernel.Domain;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
|
||||
namespace EntKube.Clusters.Tests.Features;
|
||||
|
||||
/// <summary>
|
||||
/// Cluster settings let operators view and edit configuration that lives on the
|
||||
/// live cluster — like the list of allowed container registries in the Kyverno
|
||||
/// restrict-image-registries policy. These tests verify the handler logic without
|
||||
/// touching a real cluster. The actual Kubernetes interaction is behind an
|
||||
/// IClusterSettingsReader abstraction so we can mock it in tests.
|
||||
/// </summary>
|
||||
public class ClusterSettingsTests
|
||||
{
|
||||
private readonly InMemoryClusterRepository repository;
|
||||
private readonly Mock<IClusterSettingsReader> settingsReader;
|
||||
private readonly Mock<IClusterSettingsWriter> settingsWriter;
|
||||
private readonly GetClusterSettingsHandler getHandler;
|
||||
private readonly UpdateClusterSettingsHandler updateHandler;
|
||||
|
||||
public ClusterSettingsTests()
|
||||
{
|
||||
repository = new InMemoryClusterRepository();
|
||||
settingsReader = new Mock<IClusterSettingsReader>();
|
||||
settingsWriter = new Mock<IClusterSettingsWriter>();
|
||||
getHandler = new GetClusterSettingsHandler(repository, settingsReader.Object);
|
||||
updateHandler = new UpdateClusterSettingsHandler(repository, settingsWriter.Object);
|
||||
}
|
||||
|
||||
// ─── GET ───────────────────────────────────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public async Task GetSettings_WithConnectedCluster_ReturnsSettings()
|
||||
{
|
||||
// Arrange — a connected cluster with some registries configured.
|
||||
|
||||
KubernetesCluster cluster = KubernetesCluster.Register(
|
||||
"prod", "https://k8s.example.com:6443", "kubeconfig", Guid.NewGuid(), "ctx", Guid.NewGuid());
|
||||
cluster.MarkConnected();
|
||||
await repository.AddAsync(cluster);
|
||||
|
||||
List<string> registries = new() { "docker.io", "ghcr.io", "registry.k8s.io" };
|
||||
settingsReader
|
||||
.Setup(r => r.ReadAllowedRegistriesAsync(cluster, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(registries);
|
||||
|
||||
// Act
|
||||
|
||||
Result<ClusterSettingsDto> result = await getHandler.HandleAsync(cluster.Id);
|
||||
|
||||
// Assert — the returned settings should include the registries from the live cluster.
|
||||
|
||||
result.IsSuccess.Should().BeTrue();
|
||||
result.Value!.AllowedRegistries.Should().BeEquivalentTo(registries);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetSettings_WithNonExistentCluster_ReturnsFailure()
|
||||
{
|
||||
// Act
|
||||
|
||||
Result<ClusterSettingsDto> result = await getHandler.HandleAsync(Guid.NewGuid());
|
||||
|
||||
// Assert
|
||||
|
||||
result.IsFailure.Should().BeTrue();
|
||||
result.Error.Should().Contain("not found");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetSettings_WithDisconnectedCluster_ReturnsFailure()
|
||||
{
|
||||
// Arrange — a cluster that hasn't been connected yet.
|
||||
|
||||
KubernetesCluster cluster = KubernetesCluster.Register(
|
||||
"pending", "https://k8s.example.com:6443", "kubeconfig", Guid.NewGuid(), "ctx", Guid.NewGuid());
|
||||
await repository.AddAsync(cluster);
|
||||
|
||||
// Act
|
||||
|
||||
Result<ClusterSettingsDto> result = await getHandler.HandleAsync(cluster.Id);
|
||||
|
||||
// Assert
|
||||
|
||||
result.IsFailure.Should().BeTrue();
|
||||
result.Error.Should().Contain("connected");
|
||||
}
|
||||
|
||||
// ─── UPDATE ────────────────────────────────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateSettings_WithValidRegistries_CallsWriter()
|
||||
{
|
||||
// Arrange — a connected cluster.
|
||||
|
||||
KubernetesCluster cluster = KubernetesCluster.Register(
|
||||
"prod", "https://k8s.example.com:6443", "kubeconfig", Guid.NewGuid(), "ctx", Guid.NewGuid());
|
||||
cluster.MarkConnected();
|
||||
await repository.AddAsync(cluster);
|
||||
|
||||
List<string> newRegistries = new() { "docker.io", "ghcr.io", "myregistry.com" };
|
||||
settingsWriter
|
||||
.Setup(w => w.UpdateAllowedRegistriesAsync(cluster, newRegistries, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(Result.Success());
|
||||
|
||||
UpdateClusterSettingsRequest request = new(AllowedRegistries: newRegistries);
|
||||
|
||||
// Act
|
||||
|
||||
Result result = await updateHandler.HandleAsync(cluster.Id, request);
|
||||
|
||||
// Assert
|
||||
|
||||
result.IsSuccess.Should().BeTrue();
|
||||
settingsWriter.Verify(
|
||||
w => w.UpdateAllowedRegistriesAsync(cluster, newRegistries, It.IsAny<CancellationToken>()),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateSettings_WithEmptyRegistries_ReturnsFailure()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
KubernetesCluster cluster = KubernetesCluster.Register(
|
||||
"prod", "https://k8s.example.com:6443", "kubeconfig", Guid.NewGuid(), "ctx", Guid.NewGuid());
|
||||
cluster.MarkConnected();
|
||||
await repository.AddAsync(cluster);
|
||||
|
||||
UpdateClusterSettingsRequest request = new(AllowedRegistries: new List<string>());
|
||||
|
||||
// Act
|
||||
|
||||
Result result = await updateHandler.HandleAsync(cluster.Id, request);
|
||||
|
||||
// Assert — can't have zero allowed registries, that would block all pods.
|
||||
|
||||
result.IsFailure.Should().BeTrue();
|
||||
result.Error.Should().Contain("at least one");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateSettings_WithNonExistentCluster_ReturnsFailure()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
UpdateClusterSettingsRequest request = new(AllowedRegistries: new List<string> { "docker.io" });
|
||||
|
||||
// Act
|
||||
|
||||
Result result = await updateHandler.HandleAsync(Guid.NewGuid(), request);
|
||||
|
||||
// Assert
|
||||
|
||||
result.IsFailure.Should().BeTrue();
|
||||
result.Error.Should().Contain("not found");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateSettings_WithDisconnectedCluster_ReturnsFailure()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
KubernetesCluster cluster = KubernetesCluster.Register(
|
||||
"pending", "https://k8s.example.com:6443", "kubeconfig", Guid.NewGuid(), "ctx", Guid.NewGuid());
|
||||
await repository.AddAsync(cluster);
|
||||
|
||||
UpdateClusterSettingsRequest request = new(AllowedRegistries: new List<string> { "docker.io" });
|
||||
|
||||
// Act
|
||||
|
||||
Result result = await updateHandler.HandleAsync(cluster.Id, request);
|
||||
|
||||
// Assert
|
||||
|
||||
result.IsFailure.Should().BeTrue();
|
||||
result.Error.Should().Contain("connected");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user