Cleaning up

This commit is contained in:
benbierens 2023-03-19 11:40:05 +01:00
parent 686cdc88e2
commit 63d1d9b451
No known key found for this signature in database
GPG Key ID: FE44815D96D0A1AA
3 changed files with 67 additions and 36 deletions

View File

@ -1,11 +1,13 @@
using k8s; using k8s;
using k8s.Models; using k8s.Models;
using NUnit.Framework;
namespace CodexDistTests.TestCore namespace CodexDistTests.TestCore
{ {
public interface IK8sManager public interface IK8sManager
{ {
IOnlineCodexNode BringOnline(OfflineCodexNode node); IOnlineCodexNode BringOnline(OfflineCodexNode node);
IOfflineCodexNode BringOffline(IOnlineCodexNode node);
} }
public class K8sManager : IK8sManager public class K8sManager : IK8sManager
@ -32,8 +34,8 @@ namespace CodexDistTests.TestCore
EnsureTestNamespace(client); EnsureTestNamespace(client);
var activeNode = new ActiveNode(GetFreePort(), GetNodeOrderNumber()); var activeNode = new ActiveNode(node, GetFreePort(), GetNodeOrderNumber());
var codexNode = new OnlineCodexNode(node, fileManager, activeNode.Port); var codexNode = new OnlineCodexNode(this, fileManager, activeNode.Port);
activeNodes.Add(codexNode, activeNode); activeNodes.Add(codexNode, activeNode);
CreateDeployment(activeNode, client, node); CreateDeployment(activeNode, client, node);
@ -48,15 +50,13 @@ namespace CodexDistTests.TestCore
{ {
var client = CreateClient(); var client = CreateClient();
var n = (OnlineCodexNode)node; var activeNode = GetAndRemoveActiveNodeFor(node);
var activeNode = activeNodes[n];
activeNodes.Remove(n);
var deploymentName = activeNode.Deployment.Name(); var deploymentName = activeNode.Deployment.Name();
BringOffline(activeNode, client); BringOffline(activeNode, client);
WaitUntilOffline(deploymentName, client); WaitUntilOffline(deploymentName, client);
return n.Origin; return activeNode.Origin;
} }
public void DeleteAllResources() public void DeleteAllResources()
@ -84,40 +84,46 @@ namespace CodexDistTests.TestCore
private void WaitUntilOnline(ActiveNode activeNode, Kubernetes client) private void WaitUntilOnline(ActiveNode activeNode, Kubernetes client)
{ {
while (activeNode.Deployment?.Status.AvailableReplicas == null || activeNode.Deployment.Status.AvailableReplicas != 1) WaitUntil(() =>
{ activeNode.Deployment?.Status.AvailableReplicas != null &&
Timing.WaitForServiceDelay(); activeNode.Deployment.Status.AvailableReplicas > 0);
activeNode.Deployment = client.ReadNamespacedDeployment(activeNode.Deployment.Name(), k8sNamespace);
}
} }
private void WaitUntilOffline(string deploymentName, Kubernetes client) private void WaitUntilOffline(string deploymentName, Kubernetes client)
{ {
var deployment = client.ReadNamespacedDeployment(deploymentName, k8sNamespace); WaitUntil(() =>
while (deployment != null && deployment.Status.AvailableReplicas > 0)
{ {
Timing.WaitForServiceDelay(); var deployment = client.ReadNamespacedDeployment(deploymentName, k8sNamespace);
deployment = client.ReadNamespacedDeployment(deploymentName, k8sNamespace); return deployment == null || deployment.Status.AvailableReplicas == 0;
} });
} }
private void WaitUntilZeroPods(Kubernetes client) private void WaitUntilZeroPods(Kubernetes client)
{ {
var pods = client.ListNamespacedPod(k8sNamespace); WaitUntil(() =>
while (pods.Items.Any()) !client.ListNamespacedPod(k8sNamespace).Items.Any());
{
Timing.WaitForServiceDelay();
pods = client.ListNamespacedPod(k8sNamespace);
}
} }
private void WaitUntilNamespaceDeleted(Kubernetes client) private void WaitUntilNamespaceDeleted(Kubernetes client)
{ {
var namespaces = client.ListNamespace(); WaitUntil(() =>
while (namespaces.Items.Any(n => n.Metadata.Name == k8sNamespace)) client.ListNamespace().Items.All(n => n.Metadata.Name != k8sNamespace));
}
private void WaitUntil(Func<bool> predicate)
{
var start = DateTime.UtcNow;
var state = predicate();
while (!state)
{ {
Timing.WaitForServiceDelay(); if (DateTime.UtcNow - start > Timing.K8sOperationTimeout())
namespaces = client.ListNamespace(); {
Assert.Fail("K8s operation timed out.");
throw new TimeoutException();
}
Timing.WaitForK8sServiceDelay();
state = predicate();
} }
} }
@ -250,6 +256,14 @@ namespace CodexDistTests.TestCore
return new Kubernetes(config); return new Kubernetes(config);
} }
private ActiveNode GetAndRemoveActiveNodeFor(IOnlineCodexNode node)
{
var n = (OnlineCodexNode)node;
var activeNode = activeNodes[n];
activeNodes.Remove(n);
return activeNode;
}
private int GetFreePort() private int GetFreePort()
{ {
var port = freePort; var port = freePort;
@ -266,12 +280,14 @@ namespace CodexDistTests.TestCore
public class ActiveNode public class ActiveNode
{ {
public ActiveNode(int port, int orderNumber) public ActiveNode(OfflineCodexNode origin, int port, int orderNumber)
{ {
Origin = origin;
SelectorName = orderNumber.ToString().PadLeft(6, '0'); SelectorName = orderNumber.ToString().PadLeft(6, '0');
Port = port; Port = port;
} }
public OfflineCodexNode Origin { get; }
public string SelectorName { get; } public string SelectorName { get; }
public int Port { get; } public int Port { get; }
public V1Deployment? Deployment { get; set; } public V1Deployment? Deployment { get; set; }

View File

@ -9,22 +9,27 @@ namespace CodexDistTests.TestCore
CodexDebugResponse GetDebugInfo(); CodexDebugResponse GetDebugInfo();
ContentId UploadFile(TestFile file, int retryCounter = 0); ContentId UploadFile(TestFile file, int retryCounter = 0);
TestFile? DownloadContent(ContentId contentId); TestFile? DownloadContent(ContentId contentId);
IOfflineCodexNode BringOffline();
} }
public class OnlineCodexNode : IOnlineCodexNode public class OnlineCodexNode : IOnlineCodexNode
{ {
private readonly IK8sManager k8SManager;
private readonly IFileManager fileManager; private readonly IFileManager fileManager;
private readonly int port; private readonly int port;
public OfflineCodexNode Origin { get; } public OnlineCodexNode(IK8sManager k8SManager, IFileManager fileManager, int port)
public OnlineCodexNode(OfflineCodexNode origin, IFileManager fileManager, int port)
{ {
Origin = origin; this.k8SManager = k8SManager;
this.fileManager = fileManager; this.fileManager = fileManager;
this.port = port; this.port = port;
} }
public IOfflineCodexNode BringOffline()
{
return k8SManager.BringOffline(this);
}
public CodexDebugResponse GetDebugInfo() public CodexDebugResponse GetDebugInfo()
{ {
return HttpGet<CodexDebugResponse>("debug/info"); return HttpGet<CodexDebugResponse>("debug/info");
@ -48,7 +53,7 @@ namespace CodexDistTests.TestCore
} }
catch (Exception exception) catch (Exception exception)
{ {
if (retryCounter > 5) if (retryCounter > Timing.HttpCallRetryCount())
{ {
Assert.Fail(exception.Message); Assert.Fail(exception.Message);
throw; throw;
@ -83,7 +88,7 @@ namespace CodexDistTests.TestCore
} }
catch (Exception exception) catch (Exception exception)
{ {
if (retryCounter > 5) if (retryCounter > Timing.HttpCallRetryCount())
{ {
Assert.Fail(exception.Message); Assert.Fail(exception.Message);
return null; return null;
@ -108,7 +113,7 @@ namespace CodexDistTests.TestCore
} }
catch (Exception exception) catch (Exception exception)
{ {
if (retryCounter > 5) if (retryCounter > Timing.HttpCallRetryCount())
{ {
Assert.Fail(exception.Message); Assert.Fail(exception.Message);
throw; throw;

View File

@ -4,7 +4,12 @@
{ {
public static TimeSpan HttpCallTimeout() public static TimeSpan HttpCallTimeout()
{ {
return TimeSpan.FromMinutes(10); return TimeSpan.FromSeconds(10);
}
public static int HttpCallRetryCount()
{
return 5;
} }
public static void RetryDelay() public static void RetryDelay()
@ -12,9 +17,14 @@
Utils.Sleep(TimeSpan.FromSeconds(3)); Utils.Sleep(TimeSpan.FromSeconds(3));
} }
public static void WaitForServiceDelay() public static void WaitForK8sServiceDelay()
{ {
Utils.Sleep(TimeSpan.FromSeconds(1)); Utils.Sleep(TimeSpan.FromSeconds(1));
} }
public static TimeSpan K8sOperationTimeout()
{
return TimeSpan.FromMinutes(5);
}
} }
} }