too much for one commit
This commit is contained in:
@@ -0,0 +1,212 @@
|
||||
using EntKube.Clusters.Domain;
|
||||
using EntKube.Clusters.Features.AdoptCluster;
|
||||
using EntKube.Clusters.Features.AdoptCluster.UninstallComponent;
|
||||
using EntKube.Clusters.Infrastructure;
|
||||
using EntKube.SharedKernel.Domain;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
|
||||
namespace EntKube.Clusters.Tests.Features;
|
||||
|
||||
public class UninstallComponentHandlerTests
|
||||
{
|
||||
private readonly InMemoryClusterRepository repository;
|
||||
private readonly Mock<IComponentInstaller> kyvernoInstaller;
|
||||
private readonly Mock<IComponentInstaller> monitoringInstaller;
|
||||
private readonly UninstallComponentHandler handler;
|
||||
|
||||
public UninstallComponentHandlerTests()
|
||||
{
|
||||
repository = new InMemoryClusterRepository();
|
||||
kyvernoInstaller = new Mock<IComponentInstaller>();
|
||||
monitoringInstaller = new Mock<IComponentInstaller>();
|
||||
|
||||
kyvernoInstaller.Setup(i => i.ComponentName).Returns("kyverno");
|
||||
monitoringInstaller.Setup(i => i.ComponentName).Returns("monitoring");
|
||||
|
||||
List<IComponentInstaller> installers = new() { kyvernoInstaller.Object, monitoringInstaller.Object };
|
||||
handler = new UninstallComponentHandler(repository, installers, Microsoft.Extensions.Logging.Abstractions.NullLogger<UninstallComponentHandler>.Instance);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HandleAsync_ClusterNotFound_ReturnsFailure()
|
||||
{
|
||||
// Arrange — request an uninstall on a cluster that doesn't exist.
|
||||
|
||||
UninstallComponentRequest request = new("kyverno");
|
||||
|
||||
// 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_ClusterNotConnected_ReturnsFailure()
|
||||
{
|
||||
// Arrange — Cluster is Pending, can't uninstall from it.
|
||||
|
||||
KubernetesCluster cluster = KubernetesCluster.Register(
|
||||
"pending-cluster", "https://k8s.dev:6443", "kubeconfig-data", Guid.NewGuid(), "ctx", Guid.NewGuid());
|
||||
await repository.AddAsync(cluster);
|
||||
|
||||
UninstallComponentRequest request = new("kyverno");
|
||||
|
||||
// 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_UnknownComponent_ReturnsFailureWithAvailable()
|
||||
{
|
||||
// Arrange — Requesting an uninstall for a component that has no installer.
|
||||
|
||||
KubernetesCluster cluster = KubernetesCluster.Register(
|
||||
"test-cluster", "https://k8s.test:6443", "kubeconfig-data", Guid.NewGuid(), "ctx", Guid.NewGuid());
|
||||
cluster.MarkConnected();
|
||||
await repository.AddAsync(cluster);
|
||||
|
||||
UninstallComponentRequest request = new("nonexistent-thing");
|
||||
|
||||
// Act
|
||||
|
||||
Result<InstallResult> result = await handler.HandleAsync(cluster.Id, request);
|
||||
|
||||
// Assert — Should list available installers.
|
||||
|
||||
result.IsFailure.Should().BeTrue();
|
||||
result.Error.Should().Contain("kyverno");
|
||||
result.Error.Should().Contain("monitoring");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HandleAsync_ValidComponent_DelegatesToInstallerUninstall()
|
||||
{
|
||||
// Arrange — Uninstall Kyverno from a connected cluster.
|
||||
|
||||
KubernetesCluster cluster = KubernetesCluster.Register(
|
||||
"prod-cluster", "https://k8s.prod:6443", "kubeconfig-data", Guid.NewGuid(), "prod-ctx", Guid.NewGuid());
|
||||
cluster.MarkConnected();
|
||||
await repository.AddAsync(cluster);
|
||||
|
||||
kyvernoInstaller.Setup(i => i.UninstallAsync(cluster, It.IsAny<ComponentInstallOptions>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new InstallResult(
|
||||
Success: true,
|
||||
ComponentName: "kyverno",
|
||||
Message: "Kyverno uninstalled successfully",
|
||||
Actions: new List<string> { "Helm uninstall kyverno" }));
|
||||
|
||||
UninstallComponentRequest request = new("kyverno");
|
||||
|
||||
// Act
|
||||
|
||||
Result<InstallResult> result = await handler.HandleAsync(cluster.Id, request);
|
||||
|
||||
// Assert — Should succeed and return the uninstall result.
|
||||
|
||||
result.IsSuccess.Should().BeTrue();
|
||||
result.Value!.Success.Should().BeTrue();
|
||||
result.Value.ComponentName.Should().Be("kyverno");
|
||||
result.Value.Actions.Should().Contain("Helm uninstall kyverno");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HandleAsync_InstallerFails_ReturnsFailure()
|
||||
{
|
||||
// Arrange — The uninstall encounters an error.
|
||||
|
||||
KubernetesCluster cluster = KubernetesCluster.Register(
|
||||
"flaky-cluster", "https://k8s.flaky:6443", "kubeconfig-data", Guid.NewGuid(), "ctx", Guid.NewGuid());
|
||||
cluster.MarkConnected();
|
||||
await repository.AddAsync(cluster);
|
||||
|
||||
kyvernoInstaller.Setup(i => i.UninstallAsync(cluster, It.IsAny<ComponentInstallOptions>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new InstallResult(
|
||||
Success: false,
|
||||
ComponentName: "kyverno",
|
||||
Message: "Helm uninstall failed: resources still in use",
|
||||
Actions: new List<string> { "Error: resources still in use" }));
|
||||
|
||||
UninstallComponentRequest request = new("kyverno");
|
||||
|
||||
// Act
|
||||
|
||||
Result<InstallResult> result = await handler.HandleAsync(cluster.Id, request);
|
||||
|
||||
// Assert
|
||||
|
||||
result.IsFailure.Should().BeTrue();
|
||||
result.Error.Should().Contain("resources still in use");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HandleAsync_PassesOptionsToInstaller()
|
||||
{
|
||||
// Arrange — Uninstall monitoring with a custom namespace.
|
||||
|
||||
KubernetesCluster cluster = KubernetesCluster.Register(
|
||||
"config-cluster", "https://k8s.cfg:6443", "kubeconfig-data", Guid.NewGuid(), "ctx", Guid.NewGuid());
|
||||
cluster.MarkConnected();
|
||||
await repository.AddAsync(cluster);
|
||||
|
||||
ComponentInstallOptions? capturedOptions = null;
|
||||
|
||||
monitoringInstaller.Setup(i => i.UninstallAsync(cluster, It.IsAny<ComponentInstallOptions>(), It.IsAny<CancellationToken>()))
|
||||
.Callback<KubernetesCluster, ComponentInstallOptions, CancellationToken>((_, opts, _) => capturedOptions = opts)
|
||||
.ReturnsAsync(new InstallResult(
|
||||
Success: true,
|
||||
ComponentName: "monitoring",
|
||||
Message: "Monitoring uninstalled",
|
||||
Actions: new List<string>()));
|
||||
|
||||
UninstallComponentRequest request = new("monitoring", Namespace: "custom-monitoring");
|
||||
|
||||
// Act
|
||||
|
||||
Result<InstallResult> result = await handler.HandleAsync(cluster.Id, request);
|
||||
|
||||
// Assert — The handler should forward the namespace to the installer.
|
||||
|
||||
result.IsSuccess.Should().BeTrue();
|
||||
capturedOptions.Should().NotBeNull();
|
||||
capturedOptions!.Namespace.Should().Be("custom-monitoring");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HandleAsync_ComponentNameIsCaseInsensitive()
|
||||
{
|
||||
// Arrange — Use mixed case for the component name.
|
||||
|
||||
KubernetesCluster cluster = KubernetesCluster.Register(
|
||||
"case-cluster", "https://k8s.case:6443", "kubeconfig-data", Guid.NewGuid(), "ctx", Guid.NewGuid());
|
||||
cluster.MarkConnected();
|
||||
await repository.AddAsync(cluster);
|
||||
|
||||
kyvernoInstaller.Setup(i => i.UninstallAsync(cluster, It.IsAny<ComponentInstallOptions>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new InstallResult(
|
||||
Success: true,
|
||||
ComponentName: "kyverno",
|
||||
Message: "Uninstalled",
|
||||
Actions: new List<string>()));
|
||||
|
||||
UninstallComponentRequest request = new("Kyverno");
|
||||
|
||||
// Act
|
||||
|
||||
Result<InstallResult> result = await handler.HandleAsync(cluster.Id, request);
|
||||
|
||||
// Assert
|
||||
|
||||
result.IsSuccess.Should().BeTrue();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user