Merge branch 'master' into feature/continuous-test-status-logs

# Conflicts:
#	Tests/DistTestCore/Logs/StatusLog.cs
This commit is contained in:
benbierens 2023-11-13 09:33:24 +01:00
commit 344d3cd44f
No known key found for this signature in database
GPG Key ID: FE44815D96D0A1AA
79 changed files with 441 additions and 305 deletions

View File

@ -14,16 +14,16 @@ on:
# - '!docker/continuous-tests-job.yaml'
workflow_dispatch:
inputs:
branch:
description: Branch (master)
required: false
type: string
source:
description: Repository with tests (current)
required: false
type: string
branch:
description: Branch with tests (master)
required: false
type: string
nameprefix:
description: Runner name prefix (codex-continuous-tests)
description: Runner name prefix (c-tests-runner)
required: false
type: string
namespace:
@ -31,7 +31,7 @@ on:
required: false
type: string
tests_target_duration:
description: Runner target duration (172800s=48h)
description: Runner target duration (172800 = 48h)
required: false
type: string
tests_filter:
@ -39,11 +39,14 @@ on:
required: false
type: string
tests_cleanup:
description: Runner tests cleanup (true)
required: false
type: string
description: Runner tests cleanup
type: choice
options:
- true
- false
default: true
deployment_namespace:
description: Deployment namespace (codex-continuous-tests)
description: Deployment namespace (c-tests-$runid)
required: false
type: string
@ -51,9 +54,9 @@ on:
env:
BRANCH: ${{ github.ref_name }}
SOURCE: ${{ format('{0}/{1}', github.server_url, github.repository) }}
NAMEPREFIX: codex-continuous-tests
NAMEPREFIX: c-tests-runner
NAMESPACE: default
DEPLOYMENT_NAMESPACE: codex-continuous-tests
DEPLOYMENT_NAMESPACE: c-tests
TESTS_TARGET_DURATION: 172800
TESTS_FILTER: ""
TESTS_CLEANUP: true
@ -72,16 +75,18 @@ jobs:
- name: Variables
run: |
[[ -n "${{ github.event.inputs.branch }}" ]] && echo "BRANCH=${{ github.event.inputs.branch }}" >>"$GITHUB_ENV" || echo "BRANCH=${{ env.BRANCH }}" >>"$GITHUB_ENV"
RUNID=$(date +%Y%m%d-%H%M%S)
echo "RUNID=${RUNID}" >> $GITHUB_ENV
echo "TESTID=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
[[ -n "${{ github.event.inputs.source }}" ]] && echo "SOURCE=${{ github.event.inputs.source }}" >>"$GITHUB_ENV" || echo "SOURCE=${{ env.SOURCE }}" >>"$GITHUB_ENV"
[[ -n "${{ github.event.inputs.branch }}" ]] && echo "BRANCH=${{ github.event.inputs.branch }}" >>"$GITHUB_ENV" || echo "BRANCH=${{ env.BRANCH }}" >>"$GITHUB_ENV"
[[ -n "${{ github.event.inputs.nameprefix }}" ]] && echo "NAMEPREFIX=${{ github.event.inputs.nameprefix }}" >>"$GITHUB_ENV" || echo "NAMEPREFIX=${{ env.NAMEPREFIX }}" >>"$GITHUB_ENV"
[[ -n "${{ github.event.inputs.namespace }}" ]] && echo "NAMESPACE=${{ github.event.inputs.namespace }}" >>"$GITHUB_ENV" || echo "NAMESPACE=${{ env.NAMESPACE }}" >>"$GITHUB_ENV"
[[ -n "${{ github.event.inputs.tests_target_duration }}" ]] && echo "TESTS_TARGET_DURATION=${{ github.event.inputs.tests_target_duration }}" >>"$GITHUB_ENV" || echo "TESTS_TARGET_DURATION=${{ env.TESTS_TARGET_DURATION }}" >>"$GITHUB_ENV"
[[ -n "${{ github.event.inputs.tests_filter }}" ]] && echo "TESTS_FILTER=${{ github.event.inputs.tests_filter }}" >>"$GITHUB_ENV" || echo "TESTS_FILTERS=${{ env.TESTS_FILTERS }}" >>"$GITHUB_ENV"
[[ -n "${{ github.event.inputs.tests_cleanup }}" ]] && echo "TESTS_CLEANUP=${{ github.event.inputs.tests_cleanup }}" >>"$GITHUB_ENV" || echo "TESTS_CLEANUP=${{ env.TESTS_CLEANUP }}" >>"$GITHUB_ENV"
[[ -n "${{ github.event.inputs.deployment_namespace }}" ]] && echo "DEPLOYMENT_NAMESPACE=${{ github.event.inputs.deployment_namespace }}" >>"$GITHUB_ENV" || echo "DEPLOYMENT_NAMESPACE=${{ env.DEPLOYMENT_NAMESPACE }}" >>"$GITHUB_ENV"
echo "RUNID=$(date +%Y%m%d-%H%M%S)" >> $GITHUB_ENV
echo "TESTID=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
[[ -n "${{ github.event.inputs.deployment_namespace }}" ]] && echo "DEPLOYMENT_NAMESPACE=${{ github.event.inputs.deployment_namespace }}" >>"$GITHUB_ENV" || echo "DEPLOYMENT_NAMESPACE=${{ env.DEPLOYMENT_NAMESPACE }}-${RUNID}" >>"$GITHUB_ENV"
- name: Kubectl - Install ${{ env.KUBE_VERSION }}
uses: azure/setup-kubectl@v3
with:
@ -91,6 +96,22 @@ jobs:
run: |
mkdir -p "${HOME}"/.kube
echo "${{ env.KUBE_CONFIG }}" | base64 -d > "${HOME}"/.kube/config
- name: Kubectl - Create Job
run: |
envsubst < ${{ env.JOB_MANIFEST }} | kubectl apply -f -
- name: Tests Identification
run: |
echo "----"
echo "Repository: ${{ env.SOURCE }}"
echo "Branch: ${{ env.BRANCH }}"
echo "Runner Pod: ${{ env.NAMEPREFIX }}-${{ env.RUNID }}"
echo "Runner namespace: ${{ env.NAMESPACE }}"
echo "----"
echo "Tests runid: ${{ env.RUNID }}"
echo "Tests namespace: ${{ env.DEPLOYMENT_NAMESPACE }}"
echo "Tests duration: ${{ env.TESTS_TARGET_DURATION }}"
echo "Tests filter: ${{ env.TESTS_FILTER }}"
echo "Tests cleanup: ${{ env.TESTS_CLEANUP }}"
echo "----"

View File

@ -14,16 +14,16 @@ on:
# - '!docker/dist-tests-job.yaml'
workflow_dispatch:
inputs:
branch:
description: Branch (master)
required: false
type: string
source:
description: Repository with tests (current)
required: false
type: string
branch:
description: Branch with tests (master)
required: false
type: string
nameprefix:
description: Runner prefix (codex-dist-tests)
description: Runner name prefix (d-tests-runner)
required: false
type: string
namespace:
@ -31,7 +31,7 @@ on:
required: false
type: string
command:
description: Runner command (dotnet test Tests)
description: Command (dotnet test Tests/CodexTests)
required: false
type: string
@ -39,7 +39,7 @@ on:
env:
BRANCH: ${{ github.ref_name }}
SOURCE: ${{ format('{0}/{1}', github.server_url, github.repository) }}
NAMEPREFIX: codex-dist-tests
NAMEPREFIX: d-tests-runner
NAMESPACE: default
COMMAND: dotnet test Tests/CodexTests
JOB_MANIFEST: docker/dist-tests-job.yaml
@ -79,3 +79,15 @@ jobs:
- name: Kubectl - Create Job
run: |
envsubst < ${{ env.JOB_MANIFEST }} | kubectl apply -f -
- name: Tests Identification
run: |
echo "----"
echo "Repository: ${{ env.SOURCE }}"
echo "Branch: ${{ env.BRANCH }}"
echo "Runner Pod: ${{ env.NAMEPREFIX }}-${{ env.RUNID }}"
echo "Runner namespace: ${{ env.NAMESPACE }}"
echo "----"
echo "Tests runid: ${{ env.RUNID }}"
echo "Tests command: `jq -r '. | join(" ")' <<< '${{ env.COMMAND }}'`"
echo "----"

View File

@ -1,4 +1,5 @@
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
namespace Core
{

View File

@ -54,16 +54,4 @@ namespace KubernetesWorkflow
}
}
}
public class K8sNodeLabel
{
public K8sNodeLabel(string key, string value)
{
Key = key;
Value = value;
}
public string Key { get; }
public string Value { get; }
}
}

View File

@ -1,5 +1,7 @@
using k8s;
using k8s.Models;
using KubernetesWorkflow.Recipe;
using KubernetesWorkflow.Types;
using Logging;
using Utils;
@ -623,11 +625,28 @@ namespace KubernetesWorkflow
}
private V1Pod GetPodForDeployment(RunningDeployment deployment)
{
return Time.Retry(() => GetPodForDeplomentInternal(deployment),
maxRetries: 2,
retryTime: TimeSpan.FromSeconds(10),
description: "Find pod by label for deployment.");
}
private V1Pod GetPodForDeplomentInternal(RunningDeployment deployment)
{
var allPods = client.Run(c => c.ListNamespacedPod(K8sNamespace));
var pods = allPods.Items.Where(p => p.GetLabel(PodLabelKey) == deployment.PodLabel).ToArray();
if (pods.Length != 1) throw new Exception("Expected to find only 1 pod by podLabel.");
if (pods.Length != 1)
{
var allLabels = allPods.Items.Select(p =>
{
var labels = string.Join(",", p.Labels().Select(l => $"{l.Key}={l.Value}"));
return $"pod:'{p.Name()}' has labels: [{labels}]";
});
throw new Exception($"Expected to find 1 pod by podLabel '{deployment.PodLabel}'. Found: {pods.Length}. " +
$"Total number of pods: {allPods.Items.Count}. Their labels: {string.Join(Environment.NewLine, allLabels)}");
}
return pods[0];
}

View File

@ -1,4 +1,7 @@
namespace KubernetesWorkflow
using KubernetesWorkflow.Recipe;
using KubernetesWorkflow.Types;
namespace KubernetesWorkflow
{
public interface IK8sHooks
{

View File

@ -1,4 +1,6 @@
namespace KubernetesWorkflow
using KubernetesWorkflow.Types;
namespace KubernetesWorkflow
{
public interface ILocation
{

View File

@ -1,4 +1,5 @@
using Logging;
using KubernetesWorkflow.Types;
using Logging;
namespace KubernetesWorkflow
{

View File

@ -0,0 +1,23 @@
namespace KubernetesWorkflow
{
public interface ILogHandler
{
void Log(Stream log);
}
public abstract class LogHandler : ILogHandler
{
public void Log(Stream log)
{
using var reader = new StreamReader(log);
var line = reader.ReadLine();
while (line != null)
{
ProcessLine(line);
line = reader.ReadLine();
}
}
protected abstract void ProcessLine(string line);
}
}

View File

@ -1,6 +1,6 @@
using Newtonsoft.Json.Linq;
namespace KubernetesWorkflow
namespace KubernetesWorkflow.Recipe
{
public class ContainerAdditionals
{
@ -20,7 +20,7 @@ namespace KubernetesWorkflow
{
var typeName = GetTypeName(typeof(T));
var userData = Additionals.SingleOrDefault(a => a.Type == typeName);
if (userData == null) return default(T);
if (userData == null) return default;
var jobject = (JObject)userData.UserData;
return jobject.ToObject<T>();
}

View File

@ -1,4 +1,4 @@
namespace KubernetesWorkflow
namespace KubernetesWorkflow.Recipe
{
public class ContainerRecipe
{

View File

@ -1,6 +1,6 @@
using Utils;
namespace KubernetesWorkflow
namespace KubernetesWorkflow.Recipe
{
public abstract class ContainerRecipeFactory
{

View File

@ -1,6 +1,6 @@
using Utils;
namespace KubernetesWorkflow
namespace KubernetesWorkflow.Recipe
{
public class ContainerResources
{

View File

@ -1,4 +1,4 @@
namespace KubernetesWorkflow
namespace KubernetesWorkflow.Recipe
{
public class PodAnnotations
{

View File

@ -1,4 +1,4 @@
namespace KubernetesWorkflow
namespace KubernetesWorkflow.Recipe
{
public class PodLabels
{

View File

@ -1,7 +1,7 @@
using System.Globalization;
using Utils;
namespace KubernetesWorkflow
namespace KubernetesWorkflow.Recipe
{
public class RecipeComponentFactory
{

View File

@ -1,113 +0,0 @@
using Logging;
using Newtonsoft.Json;
using Utils;
namespace KubernetesWorkflow
{
public class RunningContainers
{
public RunningContainers(StartupConfig startupConfig, StartResult startResult, RunningContainer[] containers)
{
StartupConfig = startupConfig;
StartResult = startResult;
Containers = containers;
foreach (var c in containers) c.RunningContainers = this;
}
public StartupConfig StartupConfig { get; }
public StartResult StartResult { get; }
public RunningContainer[] Containers { get; }
[JsonIgnore]
public string Name
{
get { return $"{Containers.Length}x '{Containers.First().Name}'"; }
}
public string Describe()
{
return string.Join(",", Containers.Select(c => c.Name));
}
}
public class RunningContainer
{
public RunningContainer(string name, ContainerRecipe recipe, ContainerAddress[] addresses)
{
Name = name;
Recipe = recipe;
Addresses = addresses;
}
public string Name { get; }
public ContainerRecipe Recipe { get; }
public ContainerAddress[] Addresses { get; }
[JsonIgnore]
public RunningContainers RunningContainers { get; internal set; } = null!;
public Address GetAddress(ILog log, string portTag)
{
var addresses = Addresses.Where(a => a.PortTag == portTag).ToArray();
if (!addresses.Any()) throw new Exception("No addresses found for portTag: " + portTag);
var select = SelectAddress(addresses);
log.Log($"Container '{Name}' selected for tag '{portTag}' address: '{select}'");
return select.Address;
}
public Address GetInternalAddress(string portTag)
{
var containerAddress = Addresses.Single(a => a.PortTag == portTag && a.IsInteral);
return containerAddress.Address;
}
private ContainerAddress SelectAddress(ContainerAddress[] addresses)
{
var location = RunnerLocationUtils.GetRunnerLocation();
if (location == RunnerLocation.InternalToCluster)
{
return addresses.Single(a => a.IsInteral);
}
if (location == RunnerLocation.ExternalToCluster)
{
return addresses.Single(a => !a.IsInteral);
}
throw new Exception("Running location not known.");
}
}
public class ContainerAddress
{
public ContainerAddress(string portTag, Address address, bool isInteral)
{
PortTag = portTag;
Address = address;
IsInteral = isInteral;
}
public string PortTag { get; }
public Address Address { get; }
public bool IsInteral { get; }
public override string ToString()
{
var indicator = IsInteral ? "int" : "ext";
return $"{indicator} {PortTag} -> '{Address}'";
}
}
public static class RunningContainersExtensions
{
public static RunningContainer[] Containers(this RunningContainers[] runningContainers)
{
return runningContainers.SelectMany(c => c.Containers).ToArray();
}
public static string Describe(this RunningContainers[] runningContainers)
{
return string.Join(",", runningContainers.Select(c => c.Describe()));
}
}
}

View File

@ -1,5 +1,7 @@
using k8s;
using k8s.Models;
using KubernetesWorkflow.Recipe;
using KubernetesWorkflow.Types;
using Newtonsoft.Json;
namespace KubernetesWorkflow
@ -64,76 +66,4 @@ namespace KubernetesWorkflow
return Array.Empty<Port>();
}
}
public class RunningDeployment
{
public RunningDeployment(string name, string podLabel)
{
Name = name;
PodLabel = podLabel;
}
public string Name { get; }
public string PodLabel { get; }
public V1Pod GetPod(K8sClient client, string k8sNamespace)
{
var allPods = client.Run(c => c.ListNamespacedPod(k8sNamespace));
var pods = allPods.Items.Where(p => p.GetLabel(K8sController.PodLabelKey) == PodLabel).ToArray();
if (pods.Length != 1) throw new Exception("Expected to find only 1 pod by podLabel.");
return pods[0];
}
}
public class RunningService
{
public RunningService(string name, List<ContainerRecipePortMapEntry> result)
{
Name = name;
Result = result;
}
public string Name { get; }
public List<ContainerRecipePortMapEntry> Result { get; }
public Port? GetServicePortForRecipeAndTag(ContainerRecipe recipe, string tag)
{
return GetServicePortsForRecipe(recipe).SingleOrDefault(p => p.Tag == tag);
}
public Port[] GetServicePortsForRecipe(ContainerRecipe recipe)
{
return Result
.Where(p => p.RecipeNumber == recipe.Number)
.SelectMany(p => p.Ports)
.ToArray();
}
}
public class ContainerRecipePortMapEntry
{
public ContainerRecipePortMapEntry(int recipeNumber, Port[] ports)
{
RecipeNumber = recipeNumber;
Ports = ports;
}
public int RecipeNumber { get; }
public Port[] Ports { get; }
}
public class PodInfo
{
public PodInfo(string name, string ip, string k8sNodeName)
{
Name = name;
Ip = ip;
K8SNodeName = k8sNodeName;
}
public string Name { get; }
public string Ip { get; }
public string K8SNodeName { get; }
}
}

View File

@ -1,4 +1,6 @@
using Logging;
using KubernetesWorkflow.Recipe;
using KubernetesWorkflow.Types;
using Logging;
using Newtonsoft.Json;
using Utils;
@ -241,25 +243,4 @@ namespace KubernetesWorkflow
}
}
}
public interface ILogHandler
{
void Log(Stream log);
}
public abstract class LogHandler : ILogHandler
{
public void Log(Stream log)
{
using var reader = new StreamReader(log);
var line = reader.ReadLine();
while (line != null)
{
ProcessLine(line);
line = reader.ReadLine();
}
}
protected abstract void ProcessLine(string line);
}
}

View File

@ -0,0 +1,24 @@
using Utils;
namespace KubernetesWorkflow.Types
{
public class ContainerAddress
{
public ContainerAddress(string portTag, Address address, bool isInteral)
{
PortTag = portTag;
Address = address;
IsInteral = isInteral;
}
public string PortTag { get; }
public Address Address { get; }
public bool IsInteral { get; }
public override string ToString()
{
var indicator = IsInteral ? "int" : "ext";
return $"{indicator} {PortTag} -> '{Address}'";
}
}
}

View File

@ -0,0 +1,16 @@
using KubernetesWorkflow.Recipe;
namespace KubernetesWorkflow.Types
{
public class ContainerRecipePortMapEntry
{
public ContainerRecipePortMapEntry(int recipeNumber, Port[] ports)
{
RecipeNumber = recipeNumber;
Ports = ports;
}
public int RecipeNumber { get; }
public Port[] Ports { get; }
}
}

View File

@ -0,0 +1,14 @@
namespace KubernetesWorkflow.Types
{
public class K8sNodeLabel
{
public K8sNodeLabel(string key, string value)
{
Key = key;
Value = value;
}
public string Key { get; }
public string Value { get; }
}
}

View File

@ -0,0 +1,16 @@
namespace KubernetesWorkflow.Types
{
public class PodInfo
{
public PodInfo(string name, string ip, string k8sNodeName)
{
Name = name;
Ip = ip;
K8SNodeName = k8sNodeName;
}
public string Name { get; }
public string Ip { get; }
public string K8SNodeName { get; }
}
}

View File

@ -0,0 +1,54 @@
using KubernetesWorkflow.Recipe;
using Logging;
using Newtonsoft.Json;
using Utils;
namespace KubernetesWorkflow.Types
{
public class RunningContainer
{
public RunningContainer(string name, ContainerRecipe recipe, ContainerAddress[] addresses)
{
Name = name;
Recipe = recipe;
Addresses = addresses;
}
public string Name { get; }
public ContainerRecipe Recipe { get; }
public ContainerAddress[] Addresses { get; }
[JsonIgnore]
public RunningContainers RunningContainers { get; internal set; } = null!;
public Address GetAddress(ILog log, string portTag)
{
var addresses = Addresses.Where(a => a.PortTag == portTag).ToArray();
if (!addresses.Any()) throw new Exception("No addresses found for portTag: " + portTag);
var select = SelectAddress(addresses);
log.Debug($"Container '{Name}' selected for tag '{portTag}' address: '{select}'");
return select.Address;
}
public Address GetInternalAddress(string portTag)
{
var containerAddress = Addresses.Single(a => a.PortTag == portTag && a.IsInteral);
return containerAddress.Address;
}
private ContainerAddress SelectAddress(ContainerAddress[] addresses)
{
var location = RunnerLocationUtils.GetRunnerLocation();
if (location == RunnerLocation.InternalToCluster)
{
return addresses.Single(a => a.IsInteral);
}
if (location == RunnerLocation.ExternalToCluster)
{
return addresses.Single(a => !a.IsInteral);
}
throw new Exception("Running location not known.");
}
}
}

View File

@ -0,0 +1,44 @@
using Newtonsoft.Json;
namespace KubernetesWorkflow.Types
{
public class RunningContainers
{
public RunningContainers(StartupConfig startupConfig, StartResult startResult, RunningContainer[] containers)
{
StartupConfig = startupConfig;
StartResult = startResult;
Containers = containers;
foreach (var c in containers) c.RunningContainers = this;
}
public StartupConfig StartupConfig { get; }
public StartResult StartResult { get; }
public RunningContainer[] Containers { get; }
[JsonIgnore]
public string Name
{
get { return $"{Containers.Length}x '{Containers.First().Name}'"; }
}
public string Describe()
{
return string.Join(",", Containers.Select(c => c.Name));
}
}
public static class RunningContainersExtensions
{
public static RunningContainer[] Containers(this RunningContainers[] runningContainers)
{
return runningContainers.SelectMany(c => c.Containers).ToArray();
}
public static string Describe(this RunningContainers[] runningContainers)
{
return string.Join(",", runningContainers.Select(c => c.Describe()));
}
}
}

View File

@ -0,0 +1,14 @@
namespace KubernetesWorkflow.Types
{
public class RunningDeployment
{
public RunningDeployment(string name, string podLabel)
{
Name = name;
PodLabel = podLabel;
}
public string Name { get; }
public string PodLabel { get; }
}
}

View File

@ -0,0 +1,29 @@
using KubernetesWorkflow.Recipe;
namespace KubernetesWorkflow.Types
{
public class RunningService
{
public RunningService(string name, List<ContainerRecipePortMapEntry> result)
{
Name = name;
Result = result;
}
public string Name { get; }
public List<ContainerRecipePortMapEntry> Result { get; }
public Port? GetServicePortForRecipeAndTag(ContainerRecipe recipe, string tag)
{
return GetServicePortsForRecipe(recipe).SingleOrDefault(p => p.Tag == tag);
}
public Port[] GetServicePortsForRecipe(ContainerRecipe recipe)
{
return Result
.Where(p => p.RecipeNumber == recipe.Number)
.SelectMany(p => p.Ports)
.ToArray();
}
}
}

View File

@ -56,12 +56,12 @@
public static void Retry(Action action, int maxRetries, string description)
{
Retry(action, maxRetries, TimeSpan.FromSeconds(1), description);
Retry(action, maxRetries, TimeSpan.FromSeconds(5), description);
}
public static T Retry<T>(Func<T> action, int maxRetries, string description)
{
return Retry(action, maxRetries, TimeSpan.FromSeconds(1), description);
return Retry(action, maxRetries, TimeSpan.FromSeconds(5), description);
}
public static void Retry(Action action, int maxRetries, TimeSpan retryTime, string description)

View File

@ -1,5 +1,6 @@
using GethPlugin;
using KubernetesWorkflow;
using KubernetesWorkflow.Recipe;
using Logging;
namespace CodexContractsPlugin

View File

@ -1,6 +1,7 @@
using Core;
using GethPlugin;
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
using Logging;
using Utils;

View File

@ -1,4 +1,5 @@
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
using Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

View File

@ -1,5 +1,6 @@
using Core;
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
namespace CodexDiscordBotPlugin
{

View File

@ -1,5 +1,5 @@
using Core;
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
namespace CodexDiscordBotPlugin
{

View File

@ -1,4 +1,5 @@
using KubernetesWorkflow;
using KubernetesWorkflow.Recipe;
using Utils;
namespace CodexDiscordBotPlugin

View File

@ -1,5 +1,6 @@
using Core;
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
using Utils;
namespace CodexPlugin

View File

@ -76,12 +76,7 @@ namespace CodexPlugin
public string peerId { get; set; } = string.Empty;
public long seqNo { get; set; }
public CodexDebugPeerAddressResponse[] addresses { get; set; } = Array.Empty<CodexDebugPeerAddressResponse>();
}
public class CodexDebugPeerAddressResponse
{
public string address { get; set; } = string.Empty;
public string[] addresses { get; set; } = Array.Empty<string>();
}
public class CodexDebugThresholdBreaches

View File

@ -1,5 +1,6 @@
using GethPlugin;
using KubernetesWorkflow;
using KubernetesWorkflow.Recipe;
using Utils;
namespace CodexPlugin

View File

@ -1,6 +1,6 @@
using CodexContractsPlugin;
using GethPlugin;
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
namespace CodexPlugin
{

View File

@ -2,6 +2,7 @@
using FileUtils;
using GethPlugin;
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
using Logging;
using MetricsPlugin;
using Utils;
@ -164,8 +165,9 @@ namespace CodexPlugin
throw new Exception($"Invalid version information received from Codex node {GetName()}: {debugInfo.codex}");
}
//lifecycle.Log.AddStringReplace(nodePeerId, nodeName);
//lifecycle.Log.AddStringReplace(debugInfo.table.localNode.nodeId, nodeName);
var log = tools.GetLog();
log.AddStringReplace(nodePeerId, nodeName);
log.AddStringReplace(debugInfo.table.localNode.nodeId, nodeName);
Version = debugInfo.codex;
}

View File

@ -1,6 +1,7 @@
using Core;
using GethPlugin;
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
namespace CodexPlugin
{

View File

@ -1,5 +1,5 @@
using Core;
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
using MetricsPlugin;
using System.Collections;

View File

@ -1,5 +1,5 @@
using Core;
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
namespace CodexPlugin
{

View File

@ -1,5 +1,6 @@
using Core;
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
using Logging;
namespace CodexPlugin

View File

@ -1,5 +1,5 @@
using Core;
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
namespace CodexPlugin
{

View File

@ -1,5 +1,5 @@
using Core;
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
namespace DeployAndRunPlugin
{

View File

@ -1,4 +1,5 @@
using KubernetesWorkflow;
using KubernetesWorkflow.Recipe;
namespace DeployAndRunPlugin
{

View File

@ -1,5 +1,6 @@
using Core;
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
namespace DeployAndRunPlugin
{

View File

@ -1,4 +1,5 @@
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
using Logging;
using Utils;

View File

@ -1,4 +1,5 @@
using KubernetesWorkflow;
using KubernetesWorkflow.Recipe;
namespace GethPlugin
{

View File

@ -1,5 +1,6 @@
using Core;
using KubernetesWorkflow;
using KubernetesWorkflow.Recipe;
using KubernetesWorkflow.Types;
using Newtonsoft.Json;
namespace GethPlugin

View File

@ -1,5 +1,5 @@
using Core;
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
using Logging;
using Nethereum.Contracts;
using NethereumWorkflow;

View File

@ -1,5 +1,5 @@
using Core;
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
using Logging;
namespace MetricsPlugin

View File

@ -1,5 +1,5 @@
using Core;
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
using Utils;
namespace MetricsPlugin

View File

@ -1,5 +1,5 @@
using Core;
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
using Logging;
namespace MetricsPlugin

View File

@ -1,5 +1,5 @@
using Core;
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
using Logging;
using System.Globalization;

View File

@ -1,4 +1,4 @@
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
namespace MetricsPlugin
{

View File

@ -1,4 +1,5 @@
using KubernetesWorkflow;
using KubernetesWorkflow.Recipe;
namespace MetricsPlugin
{

View File

@ -1,5 +1,6 @@
using Core;
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
using Logging;
using System.Text;

View File

@ -28,7 +28,7 @@ namespace ContinuousTests
new FixtureLog(logConfig, startTime, "Overview"),
new ConsoleLog()
);
var statusLog = new StatusLog(logConfig, startTime, "ContinuousTestRun");
var statusLog = new StatusLog(logConfig, startTime, "continuous-tests", "ContinuousTestRun");
overviewLog.Log("Initializing...");

View File

@ -1,5 +1,5 @@
using Core;
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
using Logging;
using Utils;

View File

@ -1,9 +1,9 @@
using KubernetesWorkflow;
using NUnit.Framework;
using NUnit.Framework;
using Logging;
using Utils;
using Core;
using CodexPlugin;
using KubernetesWorkflow.Types;
namespace ContinuousTests
{

View File

@ -1,11 +1,11 @@
using Logging;
using Utils;
using KubernetesWorkflow;
using NUnit.Framework.Internal;
using System.Reflection;
using CodexPlugin;
using DistTestCore.Logs;
using Core;
using KubernetesWorkflow.Types;
namespace ContinuousTests
{

View File

@ -1,8 +1,9 @@
using CodexPlugin;
using DistTestCore.Helpers;
using CodexTests.Helpers;
using ContinuousTests;
using NUnit.Framework;
namespace ContinuousTests.Tests
namespace CodexContinuousTests.Tests
{
public class PeersTest : ContinuousTest
{

View File

@ -1,7 +1,7 @@
using CodexContractsPlugin;
using CodexPlugin;
using GethPlugin;
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
using Logging;
using MetricsPlugin;
using NUnit.Framework;

View File

@ -1,11 +1,11 @@
using CodexContractsPlugin;
using CodexNetDeployer;
using CodexPlugin;
using CodexTests.Helpers;
using Core;
using DistTestCore;
using DistTestCore.Helpers;
using DistTestCore.Logs;
using GethPlugin;
using NUnit.Framework;
using NUnit.Framework.Constraints;

View File

@ -1,10 +1,9 @@
using CodexContractsPlugin;
using CodexTests;
using GethPlugin;
using NUnit.Framework;
using Utils;
namespace Tests.DownloadConnectivityTests
namespace CodexTests.DownloadConnectivityTests
{
[TestFixture]
public class FullyConnectedDownloadTests : AutoBootstrapDistTest

View File

@ -2,7 +2,7 @@
using Logging;
using NUnit.Framework;
namespace DistTestCore.Helpers
namespace CodexTests.Helpers
{
public interface IFullConnectivityImplementation
{

View File

@ -1,8 +1,8 @@
using CodexPlugin;
using Logging;
using static DistTestCore.Helpers.FullConnectivityHelper;
using static CodexTests.Helpers.FullConnectivityHelper;
namespace DistTestCore.Helpers
namespace CodexTests.Helpers
{
public class PeerConnectionTestHelpers : IFullConnectivityImplementation
{

View File

@ -2,9 +2,9 @@
using FileUtils;
using Logging;
using Utils;
using static DistTestCore.Helpers.FullConnectivityHelper;
using static CodexTests.Helpers.FullConnectivityHelper;
namespace DistTestCore.Helpers
namespace CodexTests.Helpers
{
public class PeerDownloadTestHelpers : IFullConnectivityImplementation
{

View File

@ -1,8 +1,7 @@
using CodexPlugin;
using CodexTests;
using NUnit.Framework;
namespace Tests.PeerDiscoveryTests
namespace CodexTests.PeerDiscoveryTests
{
[TestFixture]
public class LayeredDiscoveryTests : CodexDistTest

View File

@ -1,9 +1,9 @@
using CodexContractsPlugin;
using CodexTests;
using CodexPlugin;
using GethPlugin;
using NUnit.Framework;
namespace Tests.PeerDiscoveryTests
namespace CodexTests.PeerDiscoveryTests
{
[TestFixture]
public class PeerDiscoveryTests : AutoBootstrapDistTest
@ -49,7 +49,45 @@ namespace Tests.PeerDiscoveryTests
private void AssertAllNodesConnected()
{
CreatePeerConnectionTestHelpers().AssertFullyConnected(GetAllOnlineCodexNodes());
var allNodes = GetAllOnlineCodexNodes();
CreatePeerConnectionTestHelpers().AssertFullyConnected(allNodes);
CheckRoutingTable(allNodes);
}
private void CheckRoutingTable(IEnumerable<ICodexNode> allNodes)
{
var allResponses = allNodes.Select(n => n.GetDebugInfo()).ToArray();
var errors = new List<string>();
foreach (var response in allResponses)
{
var error = AreAllPresent(response, allResponses);
if (!string.IsNullOrEmpty(error)) errors.Add(error);
}
if (errors.Any())
{
Assert.Fail(string.Join(Environment.NewLine, errors));
}
}
private string AreAllPresent(CodexDebugResponse info, CodexDebugResponse[] allResponses)
{
var knownIds = info.table.nodes.Select(n => n.nodeId).ToArray();
var allOthers = GetAllOtherResponses(info, allResponses);
var expectedIds = allOthers.Select(i => i.table.localNode.nodeId).ToArray();
if (!expectedIds.All(ex => knownIds.Contains(ex)))
{
return $"Node {info.id}: Not all of '{string.Join(",", expectedIds)}' were present in routing table: '{string.Join(",", knownIds)}'";
}
return string.Empty;
}
private CodexDebugResponse[] GetAllOtherResponses(CodexDebugResponse exclude, CodexDebugResponse[] allResponses)
{
return allResponses.Where(r => r.id != exclude.id).ToArray();
}
}
}

View File

@ -29,7 +29,7 @@ namespace DistTestCore
var logConfig = configuration.GetLogConfig();
var startTime = DateTime.UtcNow;
fixtureLog = new FixtureLog(logConfig, startTime);
statusLog = new StatusLog(logConfig, startTime);
statusLog = new StatusLog(logConfig, startTime, "dist-tests");
globalEntryPoint = new EntryPoint(fixtureLog, configuration.GetK8sConfiguration(new DefaultTimeSet(), TestNamespacePrefix), configuration.GetFileManagerFolder());

View File

@ -9,11 +9,13 @@ namespace DistTestCore.Logs
private readonly object fileLock = new object();
private readonly string fullName;
private readonly string fixtureName;
private readonly string testType;
public StatusLog(LogConfig config, DateTime start, string name = "")
public StatusLog(LogConfig config, DateTime start, string testType, string name = "")
{
fullName = NameUtils.GetFixtureFullName(config, start, name) + "_STATUS.log";
fixtureName = NameUtils.GetRawFixtureName();
this.testType = testType;
}
public void ConcludeTest(string resultStatus, TimeSpan testDuration, Dictionary<string, string> data)
@ -26,10 +28,11 @@ namespace DistTestCore.Logs
data.Add("timestamp", DateTime.UtcNow.ToString("o"));
data.Add("runid", NameUtils.GetRunId());
data.Add("status", resultStatus);
data.Add("testid", NameUtils.GetTestId());
data.Add("category", NameUtils.GetCategoryName());
data.Add("fixturename", fixtureName);
if (!data.ContainsKey("testname")) data.Add("testname", NameUtils.GetTestMethodName());
data.Add("testid", NameUtils.GetTestId());
data.Add("testtype", testType);
data.Add("testduration", testDuration);
Write(data);
}

View File

@ -2,6 +2,8 @@
using DistTestCore.Logs;
using FileUtils;
using KubernetesWorkflow;
using KubernetesWorkflow.Recipe;
using KubernetesWorkflow.Types;
using Utils;
namespace DistTestCore

View File

@ -3,7 +3,7 @@ using CodexDiscordBotPlugin;
using CodexPlugin;
using Core;
using GethPlugin;
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
using Logging;
using MetricsPlugin;

View File

@ -1,5 +1,7 @@
using DistTestCore;
using KubernetesWorkflow;
using KubernetesWorkflow.Recipe;
using KubernetesWorkflow.Types;
namespace CodexNetDeployer
{

View File

@ -1,4 +1,4 @@
using DistTestCore.Helpers;
using CodexTests.Helpers;
using Logging;
namespace CodexNetDeployer

View File

@ -1,4 +1,4 @@
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
namespace TestClusterStarter
{

View File

@ -1,7 +1,7 @@
using ArgsUniform;
using Core;
using DeployAndRunPlugin;
using KubernetesWorkflow;
using KubernetesWorkflow.Types;
using Logging;
using Newtonsoft.Json;
using TestClusterStarter;