mirror of
https://github.com/logos-storage/logos-storage-nim-cs-dist-tests.git
synced 2026-01-08 00:13:08 +00:00
Merge branch 'master' into feature/public-testnet-deploying
This commit is contained in:
commit
a81f0b9145
53
.github/workflows/continuous-tests.yaml
vendored
53
.github/workflows/continuous-tests.yaml
vendored
@ -14,16 +14,16 @@ on:
|
|||||||
# - '!docker/continuous-tests-job.yaml'
|
# - '!docker/continuous-tests-job.yaml'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
branch:
|
|
||||||
description: Branch (master)
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
source:
|
source:
|
||||||
description: Repository with tests (current)
|
description: Repository with tests (current)
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
|
branch:
|
||||||
|
description: Branch with tests (master)
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
nameprefix:
|
nameprefix:
|
||||||
description: Runner name prefix (codex-continuous-tests)
|
description: Runner name prefix (c-tests-runner)
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
namespace:
|
namespace:
|
||||||
@ -31,7 +31,7 @@ on:
|
|||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
tests_target_duration:
|
tests_target_duration:
|
||||||
description: Runner target duration (172800s=48h)
|
description: Runner target duration (172800 = 48h)
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
tests_filter:
|
tests_filter:
|
||||||
@ -39,11 +39,14 @@ on:
|
|||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
tests_cleanup:
|
tests_cleanup:
|
||||||
description: Runner tests cleanup (true)
|
description: Runner tests cleanup
|
||||||
required: false
|
type: choice
|
||||||
type: string
|
options:
|
||||||
|
- true
|
||||||
|
- false
|
||||||
|
default: true
|
||||||
deployment_namespace:
|
deployment_namespace:
|
||||||
description: Deployment namespace (codex-continuous-tests)
|
description: Deployment namespace (c-tests-$runid)
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
@ -51,9 +54,9 @@ on:
|
|||||||
env:
|
env:
|
||||||
BRANCH: ${{ github.ref_name }}
|
BRANCH: ${{ github.ref_name }}
|
||||||
SOURCE: ${{ format('{0}/{1}', github.server_url, github.repository) }}
|
SOURCE: ${{ format('{0}/{1}', github.server_url, github.repository) }}
|
||||||
NAMEPREFIX: codex-continuous-tests
|
NAMEPREFIX: c-tests-runner
|
||||||
NAMESPACE: default
|
NAMESPACE: default
|
||||||
DEPLOYMENT_NAMESPACE: codex-continuous-tests
|
DEPLOYMENT_NAMESPACE: c-tests
|
||||||
TESTS_TARGET_DURATION: 172800
|
TESTS_TARGET_DURATION: 172800
|
||||||
TESTS_FILTER: ""
|
TESTS_FILTER: ""
|
||||||
TESTS_CLEANUP: true
|
TESTS_CLEANUP: true
|
||||||
@ -72,16 +75,18 @@ jobs:
|
|||||||
|
|
||||||
- name: Variables
|
- name: Variables
|
||||||
run: |
|
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.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.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.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_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_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.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"
|
[[ -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"
|
||||||
echo "RUNID=$(date +%Y%m%d-%H%M%S)" >> $GITHUB_ENV
|
|
||||||
echo "TESTID=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
|
|
||||||
- name: Kubectl - Install ${{ env.KUBE_VERSION }}
|
- name: Kubectl - Install ${{ env.KUBE_VERSION }}
|
||||||
uses: azure/setup-kubectl@v3
|
uses: azure/setup-kubectl@v3
|
||||||
with:
|
with:
|
||||||
@ -91,6 +96,22 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir -p "${HOME}"/.kube
|
mkdir -p "${HOME}"/.kube
|
||||||
echo "${{ env.KUBE_CONFIG }}" | base64 -d > "${HOME}"/.kube/config
|
echo "${{ env.KUBE_CONFIG }}" | base64 -d > "${HOME}"/.kube/config
|
||||||
|
|
||||||
- name: Kubectl - Create Job
|
- name: Kubectl - Create Job
|
||||||
run: |
|
run: |
|
||||||
envsubst < ${{ env.JOB_MANIFEST }} | kubectl apply -f -
|
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 "----"
|
||||||
|
|||||||
26
.github/workflows/dist-tests.yaml
vendored
26
.github/workflows/dist-tests.yaml
vendored
@ -14,16 +14,16 @@ on:
|
|||||||
# - '!docker/dist-tests-job.yaml'
|
# - '!docker/dist-tests-job.yaml'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
branch:
|
|
||||||
description: Branch (master)
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
source:
|
source:
|
||||||
description: Repository with tests (current)
|
description: Repository with tests (current)
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
|
branch:
|
||||||
|
description: Branch with tests (master)
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
nameprefix:
|
nameprefix:
|
||||||
description: Runner prefix (codex-dist-tests)
|
description: Runner name prefix (d-tests-runner)
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
namespace:
|
namespace:
|
||||||
@ -31,7 +31,7 @@ on:
|
|||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
command:
|
command:
|
||||||
description: Runner command (dotnet test Tests)
|
description: Command (dotnet test Tests/CodexTests)
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ on:
|
|||||||
env:
|
env:
|
||||||
BRANCH: ${{ github.ref_name }}
|
BRANCH: ${{ github.ref_name }}
|
||||||
SOURCE: ${{ format('{0}/{1}', github.server_url, github.repository) }}
|
SOURCE: ${{ format('{0}/{1}', github.server_url, github.repository) }}
|
||||||
NAMEPREFIX: codex-dist-tests
|
NAMEPREFIX: d-tests-runner
|
||||||
NAMESPACE: default
|
NAMESPACE: default
|
||||||
COMMAND: dotnet test Tests/CodexTests
|
COMMAND: dotnet test Tests/CodexTests
|
||||||
JOB_MANIFEST: docker/dist-tests-job.yaml
|
JOB_MANIFEST: docker/dist-tests-job.yaml
|
||||||
@ -79,3 +79,15 @@ jobs:
|
|||||||
- name: Kubectl - Create Job
|
- name: Kubectl - Create Job
|
||||||
run: |
|
run: |
|
||||||
envsubst < ${{ env.JOB_MANIFEST }} | kubectl apply -f -
|
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 "----"
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow;
|
||||||
|
using KubernetesWorkflow.Types;
|
||||||
|
|
||||||
namespace Core
|
namespace Core
|
||||||
{
|
{
|
||||||
|
|||||||
@ -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; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
using k8s;
|
using k8s;
|
||||||
using k8s.Models;
|
using k8s.Models;
|
||||||
|
using KubernetesWorkflow.Recipe;
|
||||||
|
using KubernetesWorkflow.Types;
|
||||||
using Logging;
|
using Logging;
|
||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
@ -623,11 +625,28 @@ namespace KubernetesWorkflow
|
|||||||
}
|
}
|
||||||
|
|
||||||
private V1Pod GetPodForDeployment(RunningDeployment deployment)
|
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 allPods = client.Run(c => c.ListNamespacedPod(K8sNamespace));
|
||||||
var pods = allPods.Items.Where(p => p.GetLabel(PodLabelKey) == deployment.PodLabel).ToArray();
|
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];
|
return pods[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
namespace KubernetesWorkflow
|
using KubernetesWorkflow.Recipe;
|
||||||
|
using KubernetesWorkflow.Types;
|
||||||
|
|
||||||
|
namespace KubernetesWorkflow
|
||||||
{
|
{
|
||||||
public interface IK8sHooks
|
public interface IK8sHooks
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
namespace KubernetesWorkflow
|
using KubernetesWorkflow.Types;
|
||||||
|
|
||||||
|
namespace KubernetesWorkflow
|
||||||
{
|
{
|
||||||
public interface ILocation
|
public interface ILocation
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using Logging;
|
using KubernetesWorkflow.Types;
|
||||||
|
using Logging;
|
||||||
|
|
||||||
namespace KubernetesWorkflow
|
namespace KubernetesWorkflow
|
||||||
{
|
{
|
||||||
|
|||||||
23
Framework/KubernetesWorkflow/LogHandler.cs
Normal file
23
Framework/KubernetesWorkflow/LogHandler.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
namespace KubernetesWorkflow
|
namespace KubernetesWorkflow.Recipe
|
||||||
{
|
{
|
||||||
public class ContainerAdditionals
|
public class ContainerAdditionals
|
||||||
{
|
{
|
||||||
@ -20,7 +20,7 @@ namespace KubernetesWorkflow
|
|||||||
{
|
{
|
||||||
var typeName = GetTypeName(typeof(T));
|
var typeName = GetTypeName(typeof(T));
|
||||||
var userData = Additionals.SingleOrDefault(a => a.Type == typeName);
|
var userData = Additionals.SingleOrDefault(a => a.Type == typeName);
|
||||||
if (userData == null) return default(T);
|
if (userData == null) return default;
|
||||||
var jobject = (JObject)userData.UserData;
|
var jobject = (JObject)userData.UserData;
|
||||||
return jobject.ToObject<T>();
|
return jobject.ToObject<T>();
|
||||||
}
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace KubernetesWorkflow
|
namespace KubernetesWorkflow.Recipe
|
||||||
{
|
{
|
||||||
public class ContainerRecipe
|
public class ContainerRecipe
|
||||||
{
|
{
|
||||||
@ -1,6 +1,6 @@
|
|||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
namespace KubernetesWorkflow
|
namespace KubernetesWorkflow.Recipe
|
||||||
{
|
{
|
||||||
public abstract class ContainerRecipeFactory
|
public abstract class ContainerRecipeFactory
|
||||||
{
|
{
|
||||||
@ -1,6 +1,6 @@
|
|||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
namespace KubernetesWorkflow
|
namespace KubernetesWorkflow.Recipe
|
||||||
{
|
{
|
||||||
public class ContainerResources
|
public class ContainerResources
|
||||||
{
|
{
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace KubernetesWorkflow
|
namespace KubernetesWorkflow.Recipe
|
||||||
{
|
{
|
||||||
public class PodAnnotations
|
public class PodAnnotations
|
||||||
{
|
{
|
||||||
@ -1,4 +1,4 @@
|
|||||||
namespace KubernetesWorkflow
|
namespace KubernetesWorkflow.Recipe
|
||||||
{
|
{
|
||||||
public class PodLabels
|
public class PodLabels
|
||||||
{
|
{
|
||||||
@ -1,7 +1,7 @@
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
namespace KubernetesWorkflow
|
namespace KubernetesWorkflow.Recipe
|
||||||
{
|
{
|
||||||
public class RecipeComponentFactory
|
public class RecipeComponentFactory
|
||||||
{
|
{
|
||||||
@ -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()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,5 +1,7 @@
|
|||||||
using k8s;
|
using k8s;
|
||||||
using k8s.Models;
|
using k8s.Models;
|
||||||
|
using KubernetesWorkflow.Recipe;
|
||||||
|
using KubernetesWorkflow.Types;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace KubernetesWorkflow
|
namespace KubernetesWorkflow
|
||||||
@ -64,76 +66,4 @@ namespace KubernetesWorkflow
|
|||||||
return Array.Empty<Port>();
|
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; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
using Logging;
|
using KubernetesWorkflow.Recipe;
|
||||||
|
using KubernetesWorkflow.Types;
|
||||||
|
using Logging;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Utils;
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
24
Framework/KubernetesWorkflow/Types/ContainerAddress.cs
Normal file
24
Framework/KubernetesWorkflow/Types/ContainerAddress.cs
Normal 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}'";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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; }
|
||||||
|
}
|
||||||
|
}
|
||||||
14
Framework/KubernetesWorkflow/Types/K8sNodeLabel.cs
Normal file
14
Framework/KubernetesWorkflow/Types/K8sNodeLabel.cs
Normal 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; }
|
||||||
|
}
|
||||||
|
}
|
||||||
16
Framework/KubernetesWorkflow/Types/PodInfo.cs
Normal file
16
Framework/KubernetesWorkflow/Types/PodInfo.cs
Normal 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; }
|
||||||
|
}
|
||||||
|
}
|
||||||
54
Framework/KubernetesWorkflow/Types/RunningContainer.cs
Normal file
54
Framework/KubernetesWorkflow/Types/RunningContainer.cs
Normal 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.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
44
Framework/KubernetesWorkflow/Types/RunningContainers.cs
Normal file
44
Framework/KubernetesWorkflow/Types/RunningContainers.cs
Normal 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()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
Framework/KubernetesWorkflow/Types/RunningDeployment.cs
Normal file
14
Framework/KubernetesWorkflow/Types/RunningDeployment.cs
Normal 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; }
|
||||||
|
}
|
||||||
|
}
|
||||||
29
Framework/KubernetesWorkflow/Types/RunningService.cs
Normal file
29
Framework/KubernetesWorkflow/Types/RunningService.cs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -56,12 +56,12 @@
|
|||||||
|
|
||||||
public static void Retry(Action action, int maxRetries, string description)
|
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)
|
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)
|
public static void Retry(Action action, int maxRetries, TimeSpan retryTime, string description)
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using GethPlugin;
|
using GethPlugin;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow;
|
||||||
|
using KubernetesWorkflow.Recipe;
|
||||||
using Logging;
|
using Logging;
|
||||||
|
|
||||||
namespace CodexContractsPlugin
|
namespace CodexContractsPlugin
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
using Core;
|
using Core;
|
||||||
using GethPlugin;
|
using GethPlugin;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow;
|
||||||
|
using KubernetesWorkflow.Types;
|
||||||
using Logging;
|
using Logging;
|
||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow;
|
||||||
|
using KubernetesWorkflow.Types;
|
||||||
using Logging;
|
using Logging;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using Core;
|
using Core;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow;
|
||||||
|
using KubernetesWorkflow.Types;
|
||||||
|
|
||||||
namespace CodexDiscordBotPlugin
|
namespace CodexDiscordBotPlugin
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using Core;
|
using Core;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow.Types;
|
||||||
|
|
||||||
namespace CodexDiscordBotPlugin
|
namespace CodexDiscordBotPlugin
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow;
|
||||||
|
using KubernetesWorkflow.Recipe;
|
||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
namespace CodexDiscordBotPlugin
|
namespace CodexDiscordBotPlugin
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using Core;
|
using Core;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow;
|
||||||
|
using KubernetesWorkflow.Types;
|
||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
namespace CodexPlugin
|
namespace CodexPlugin
|
||||||
@ -62,14 +63,17 @@ namespace CodexPlugin
|
|||||||
|
|
||||||
public string UploadFile(FileStream fileStream)
|
public string UploadFile(FileStream fileStream)
|
||||||
{
|
{
|
||||||
// private const string UploadFailedMessage = "Unable to store block";
|
return Http().HttpPostStream("data", fileStream);
|
||||||
|
|
||||||
return Http().HttpPostStream("upload", fileStream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream DownloadFile(string contentId)
|
public Stream DownloadFile(string contentId)
|
||||||
{
|
{
|
||||||
return Http().HttpGetStream("download/" + contentId);
|
return Http().HttpGetStream("data/" + contentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CodexLocalDataResponse[] LocalFiles()
|
||||||
|
{
|
||||||
|
return Http().HttpGetJson<CodexLocalDataResponse[]>("local");
|
||||||
}
|
}
|
||||||
|
|
||||||
public CodexSalesAvailabilityResponse SalesAvailability(CodexSalesAvailabilityRequest request)
|
public CodexSalesAvailabilityResponse SalesAvailability(CodexSalesAvailabilityRequest request)
|
||||||
|
|||||||
@ -76,12 +76,7 @@ namespace CodexPlugin
|
|||||||
|
|
||||||
public string peerId { get; set; } = string.Empty;
|
public string peerId { get; set; } = string.Empty;
|
||||||
public long seqNo { get; set; }
|
public long seqNo { get; set; }
|
||||||
public CodexDebugPeerAddressResponse[] addresses { get; set; } = Array.Empty<CodexDebugPeerAddressResponse>();
|
public string[] addresses { get; set; } = Array.Empty<string>();
|
||||||
}
|
|
||||||
|
|
||||||
public class CodexDebugPeerAddressResponse
|
|
||||||
{
|
|
||||||
public string address { get; set; } = string.Empty;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CodexDebugThresholdBreaches
|
public class CodexDebugThresholdBreaches
|
||||||
@ -170,4 +165,30 @@ namespace CodexPlugin
|
|||||||
{
|
{
|
||||||
public string cid { get; set; } = string.Empty;
|
public string cid { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class CodexLocalData
|
||||||
|
{
|
||||||
|
public CodexLocalData(ContentId cid, CodexLocalDataManifestResponse manifest)
|
||||||
|
{
|
||||||
|
Cid = cid;
|
||||||
|
Manifest = manifest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContentId Cid { get; }
|
||||||
|
public CodexLocalDataManifestResponse Manifest { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CodexLocalDataResponse
|
||||||
|
{
|
||||||
|
public string cid { get; set; } = string.Empty;
|
||||||
|
public CodexLocalDataManifestResponse manifest { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CodexLocalDataManifestResponse
|
||||||
|
{
|
||||||
|
public string rootHash { get; set; } = string.Empty;
|
||||||
|
public int originalBytes { get; set; }
|
||||||
|
public int blockSize { get; set; }
|
||||||
|
public bool @protected { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using GethPlugin;
|
using GethPlugin;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow;
|
||||||
|
using KubernetesWorkflow.Recipe;
|
||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
namespace CodexPlugin
|
namespace CodexPlugin
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
using CodexContractsPlugin;
|
using CodexContractsPlugin;
|
||||||
using GethPlugin;
|
using GethPlugin;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow.Types;
|
||||||
|
|
||||||
namespace CodexPlugin
|
namespace CodexPlugin
|
||||||
{
|
{
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
using FileUtils;
|
using FileUtils;
|
||||||
using GethPlugin;
|
using GethPlugin;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow;
|
||||||
|
using KubernetesWorkflow.Types;
|
||||||
using Logging;
|
using Logging;
|
||||||
using MetricsPlugin;
|
using MetricsPlugin;
|
||||||
using Utils;
|
using Utils;
|
||||||
@ -18,6 +19,7 @@ namespace CodexPlugin
|
|||||||
//CodexDebugRepoStoreResponse[] GetDebugRepoStore();
|
//CodexDebugRepoStoreResponse[] GetDebugRepoStore();
|
||||||
ContentId UploadFile(TrackedFile file);
|
ContentId UploadFile(TrackedFile file);
|
||||||
TrackedFile? DownloadContent(ContentId contentId, string fileLabel = "");
|
TrackedFile? DownloadContent(ContentId contentId, string fileLabel = "");
|
||||||
|
CodexLocalData[] LocalFiles();
|
||||||
void ConnectToPeer(ICodexNode node);
|
void ConnectToPeer(ICodexNode node);
|
||||||
CodexDebugVersionResponse Version { get; }
|
CodexDebugVersionResponse Version { get; }
|
||||||
IMarketplaceAccess Marketplace { get; }
|
IMarketplaceAccess Marketplace { get; }
|
||||||
@ -121,6 +123,11 @@ namespace CodexPlugin
|
|||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CodexLocalData[] LocalFiles()
|
||||||
|
{
|
||||||
|
return CodexAccess.LocalFiles().Select(l => new CodexLocalData(new ContentId(l.cid), l.manifest)).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
public void ConnectToPeer(ICodexNode node)
|
public void ConnectToPeer(ICodexNode node)
|
||||||
{
|
{
|
||||||
var peer = (CodexNode)node;
|
var peer = (CodexNode)node;
|
||||||
@ -158,8 +165,9 @@ namespace CodexPlugin
|
|||||||
throw new Exception($"Invalid version information received from Codex node {GetName()}: {debugInfo.codex}");
|
throw new Exception($"Invalid version information received from Codex node {GetName()}: {debugInfo.codex}");
|
||||||
}
|
}
|
||||||
|
|
||||||
//lifecycle.Log.AddStringReplace(nodePeerId, nodeName);
|
var log = tools.GetLog();
|
||||||
//lifecycle.Log.AddStringReplace(debugInfo.table.localNode.nodeId, nodeName);
|
log.AddStringReplace(nodePeerId, nodeName);
|
||||||
|
log.AddStringReplace(debugInfo.table.localNode.nodeId, nodeName);
|
||||||
Version = debugInfo.codex;
|
Version = debugInfo.codex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,5 +213,15 @@ namespace CodexPlugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
public string Id { get; }
|
public string Id { get; }
|
||||||
|
|
||||||
|
public override bool Equals(object? obj)
|
||||||
|
{
|
||||||
|
return obj is ContentId id && Id == id.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return HashCode.Combine(Id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
using Core;
|
using Core;
|
||||||
using GethPlugin;
|
using GethPlugin;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow;
|
||||||
|
using KubernetesWorkflow.Types;
|
||||||
|
|
||||||
namespace CodexPlugin
|
namespace CodexPlugin
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using Core;
|
using Core;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow.Types;
|
||||||
using MetricsPlugin;
|
using MetricsPlugin;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using Core;
|
using Core;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow.Types;
|
||||||
|
|
||||||
namespace CodexPlugin
|
namespace CodexPlugin
|
||||||
{
|
{
|
||||||
@ -19,12 +19,13 @@ namespace CodexPlugin
|
|||||||
|
|
||||||
public void Announce()
|
public void Announce()
|
||||||
{
|
{
|
||||||
tools.GetLog().Log($"Loaded with Codex ID: '{codexStarter.GetCodexId()}'");
|
tools.GetLog().Log($"Loaded with Codex ID: '{codexStarter.GetCodexId()}' - Revision: {codexStarter.GetCodexRevision()}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddMetadata(IAddMetadata metadata)
|
public void AddMetadata(IAddMetadata metadata)
|
||||||
{
|
{
|
||||||
metadata.Add("codexid", codexStarter.GetCodexId());
|
metadata.Add("codexid", codexStarter.GetCodexId());
|
||||||
|
metadata.Add("codexrevision", codexStarter.GetCodexRevision());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Decommission()
|
public void Decommission()
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using Core;
|
using Core;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow;
|
||||||
|
using KubernetesWorkflow.Types;
|
||||||
using Logging;
|
using Logging;
|
||||||
|
|
||||||
namespace CodexPlugin
|
namespace CodexPlugin
|
||||||
@ -65,6 +66,12 @@ namespace CodexPlugin
|
|||||||
return recipe.Image;
|
return recipe.Image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetCodexRevision()
|
||||||
|
{
|
||||||
|
if (versionResponse != null) return versionResponse.revision;
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
private StartupConfig CreateStartupConfig(CodexSetup codexSetup)
|
private StartupConfig CreateStartupConfig(CodexSetup codexSetup)
|
||||||
{
|
{
|
||||||
var startupConfig = new StartupConfig();
|
var startupConfig = new StartupConfig();
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using Core;
|
using Core;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow.Types;
|
||||||
|
|
||||||
namespace CodexPlugin
|
namespace CodexPlugin
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using Core;
|
using Core;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow.Types;
|
||||||
|
|
||||||
namespace DeployAndRunPlugin
|
namespace DeployAndRunPlugin
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow;
|
||||||
|
using KubernetesWorkflow.Recipe;
|
||||||
|
|
||||||
namespace DeployAndRunPlugin
|
namespace DeployAndRunPlugin
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using Core;
|
using Core;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow;
|
||||||
|
using KubernetesWorkflow.Types;
|
||||||
|
|
||||||
namespace DeployAndRunPlugin
|
namespace DeployAndRunPlugin
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow;
|
||||||
|
using KubernetesWorkflow.Types;
|
||||||
using Logging;
|
using Logging;
|
||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow;
|
||||||
|
using KubernetesWorkflow.Recipe;
|
||||||
|
|
||||||
namespace GethPlugin
|
namespace GethPlugin
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using Core;
|
using Core;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow.Recipe;
|
||||||
|
using KubernetesWorkflow.Types;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace GethPlugin
|
namespace GethPlugin
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using Core;
|
using Core;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow.Types;
|
||||||
using Logging;
|
using Logging;
|
||||||
using Nethereum.Contracts;
|
using Nethereum.Contracts;
|
||||||
using NethereumWorkflow;
|
using NethereumWorkflow;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using Core;
|
using Core;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow.Types;
|
||||||
using Logging;
|
using Logging;
|
||||||
|
|
||||||
namespace MetricsPlugin
|
namespace MetricsPlugin
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using Core;
|
using Core;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow.Types;
|
||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
namespace MetricsPlugin
|
namespace MetricsPlugin
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using Core;
|
using Core;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow.Types;
|
||||||
using Logging;
|
using Logging;
|
||||||
|
|
||||||
namespace MetricsPlugin
|
namespace MetricsPlugin
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using Core;
|
using Core;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow.Types;
|
||||||
using Logging;
|
using Logging;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow.Types;
|
||||||
|
|
||||||
namespace MetricsPlugin
|
namespace MetricsPlugin
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow;
|
||||||
|
using KubernetesWorkflow.Recipe;
|
||||||
|
|
||||||
namespace MetricsPlugin
|
namespace MetricsPlugin
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using Core;
|
using Core;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow;
|
||||||
|
using KubernetesWorkflow.Types;
|
||||||
using Logging;
|
using Logging;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using DistTestCore.Logs;
|
using DistTestCore;
|
||||||
|
using DistTestCore.Logs;
|
||||||
using Logging;
|
using Logging;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Utils;
|
using Utils;
|
||||||
@ -28,7 +29,7 @@ namespace ContinuousTests
|
|||||||
new FixtureLog(logConfig, startTime, "Overview"),
|
new FixtureLog(logConfig, startTime, "Overview"),
|
||||||
new ConsoleLog()
|
new ConsoleLog()
|
||||||
);
|
);
|
||||||
var statusLog = new StatusLog(logConfig, startTime, "ContinuousTestRun");
|
var statusLog = new StatusLog(logConfig, startTime, "continuous-tests", "ContinuousTestRun");
|
||||||
|
|
||||||
overviewLog.Log("Initializing...");
|
overviewLog.Log("Initializing...");
|
||||||
|
|
||||||
@ -43,6 +44,7 @@ namespace ContinuousTests
|
|||||||
var taskFactory = new TaskFactory();
|
var taskFactory = new TaskFactory();
|
||||||
overviewLog.Log("Startup checks passed. Configuration:");
|
overviewLog.Log("Startup checks passed. Configuration:");
|
||||||
overviewLog.Log(JsonConvert.SerializeObject(config, Formatting.Indented));
|
overviewLog.Log(JsonConvert.SerializeObject(config, Formatting.Indented));
|
||||||
|
overviewLog.Log("Test framework revision: " + GitInfo.GetStatus());
|
||||||
overviewLog.Log("Continuous tests starting...");
|
overviewLog.Log("Continuous tests starting...");
|
||||||
overviewLog.Log("");
|
overviewLog.Log("");
|
||||||
var allTests = testFactory.CreateTests();
|
var allTests = testFactory.CreateTests();
|
||||||
@ -57,7 +59,7 @@ namespace ContinuousTests
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var testLoops = filteredTests.Select(t => new TestLoop(entryPointFactory, taskFactory, config, overviewLog, t.GetType(), t.RunTestEvery, startupChecker, cancelToken)).ToArray();
|
var testLoops = filteredTests.Select(t => new TestLoop(entryPointFactory, taskFactory, config, overviewLog, statusLog, t.GetType(), t.RunTestEvery, startupChecker, cancelToken)).ToArray();
|
||||||
|
|
||||||
foreach (var testLoop in testLoops)
|
foreach (var testLoop in testLoops)
|
||||||
{
|
{
|
||||||
@ -109,6 +111,7 @@ namespace ContinuousTests
|
|||||||
Cancellation.Cts.Cancel();
|
Cancellation.Cts.Cancel();
|
||||||
overviewLog.Log($"Congratulations! The targer duration has been reached! ({Time.FormatDuration(targetDuration)})");
|
overviewLog.Log($"Congratulations! The targer duration has been reached! ({Time.FormatDuration(targetDuration)})");
|
||||||
statusLog.ConcludeTest("Passed", testDuration, testData);
|
statusLog.ConcludeTest("Passed", testDuration, testData);
|
||||||
|
Environment.ExitCode = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,6 +120,7 @@ namespace ContinuousTests
|
|||||||
cancelToken.WaitHandle.WaitOne();
|
cancelToken.WaitHandle.WaitOne();
|
||||||
}
|
}
|
||||||
statusLog.ConcludeTest("Failed", testDuration, testData);
|
statusLog.ConcludeTest("Failed", testDuration, testData);
|
||||||
|
Environment.ExitCode = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dictionary<string, string> FormatTestRuns(TestLoop[] testLoops)
|
private Dictionary<string, string> FormatTestRuns(TestLoop[] testLoops)
|
||||||
@ -124,7 +128,8 @@ namespace ContinuousTests
|
|||||||
var result = new Dictionary<string, string>();
|
var result = new Dictionary<string, string>();
|
||||||
foreach (var testLoop in testLoops)
|
foreach (var testLoop in testLoops)
|
||||||
{
|
{
|
||||||
result.Add($"ctest-{testLoop.Name}", $"passes: {testLoop.NumberOfPasses} - failures: {testLoop.NumberOfFailures}");
|
result.Add("testname", testLoop.Name);
|
||||||
|
result.Add($"summary", $"passes: {testLoop.NumberOfPasses} - failures: {testLoop.NumberOfFailures}");
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using Core;
|
using Core;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow.Types;
|
||||||
using Logging;
|
using Logging;
|
||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
using KubernetesWorkflow;
|
using NUnit.Framework;
|
||||||
using NUnit.Framework;
|
|
||||||
using Logging;
|
using Logging;
|
||||||
using Utils;
|
using Utils;
|
||||||
using Core;
|
using Core;
|
||||||
using CodexPlugin;
|
using CodexPlugin;
|
||||||
|
using KubernetesWorkflow.Types;
|
||||||
|
|
||||||
namespace ContinuousTests
|
namespace ContinuousTests
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
using Logging;
|
using Logging;
|
||||||
using Utils;
|
using Utils;
|
||||||
using KubernetesWorkflow;
|
|
||||||
using NUnit.Framework.Internal;
|
using NUnit.Framework.Internal;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using CodexPlugin;
|
using CodexPlugin;
|
||||||
using DistTestCore.Logs;
|
using DistTestCore.Logs;
|
||||||
using Core;
|
using Core;
|
||||||
|
using KubernetesWorkflow.Types;
|
||||||
|
|
||||||
namespace ContinuousTests
|
namespace ContinuousTests
|
||||||
{
|
{
|
||||||
@ -16,6 +16,7 @@ namespace ContinuousTests
|
|||||||
private readonly TaskFactory taskFactory;
|
private readonly TaskFactory taskFactory;
|
||||||
private readonly Configuration config;
|
private readonly Configuration config;
|
||||||
private readonly ILog overviewLog;
|
private readonly ILog overviewLog;
|
||||||
|
private readonly StatusLog statusLog;
|
||||||
private readonly TestHandle handle;
|
private readonly TestHandle handle;
|
||||||
private readonly CancellationToken cancelToken;
|
private readonly CancellationToken cancelToken;
|
||||||
private readonly ICodexNode[] nodes;
|
private readonly ICodexNode[] nodes;
|
||||||
@ -23,11 +24,12 @@ namespace ContinuousTests
|
|||||||
private readonly string testName;
|
private readonly string testName;
|
||||||
private static int failureCount = 0;
|
private static int failureCount = 0;
|
||||||
|
|
||||||
public SingleTestRun(EntryPointFactory entryPointFactory, TaskFactory taskFactory, Configuration config, ILog overviewLog, TestHandle handle, StartupChecker startupChecker, CancellationToken cancelToken)
|
public SingleTestRun(EntryPointFactory entryPointFactory, TaskFactory taskFactory, Configuration config, ILog overviewLog, StatusLog statusLog, TestHandle handle, StartupChecker startupChecker, CancellationToken cancelToken)
|
||||||
{
|
{
|
||||||
this.taskFactory = taskFactory;
|
this.taskFactory = taskFactory;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.overviewLog = overviewLog;
|
this.overviewLog = overviewLog;
|
||||||
|
this.statusLog = statusLog;
|
||||||
this.handle = handle;
|
this.handle = handle;
|
||||||
this.cancelToken = cancelToken;
|
this.cancelToken = cancelToken;
|
||||||
testName = handle.Test.GetType().Name;
|
testName = handle.Test.GetType().Name;
|
||||||
@ -63,13 +65,15 @@ namespace ContinuousTests
|
|||||||
private void RunTest(Action<bool> resultHandler)
|
private void RunTest(Action<bool> resultHandler)
|
||||||
{
|
{
|
||||||
var testStart = DateTime.UtcNow;
|
var testStart = DateTime.UtcNow;
|
||||||
|
TimeSpan duration = TimeSpan.Zero;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
RunTestMoments();
|
RunTestMoments();
|
||||||
|
duration = DateTime.UtcNow - testStart;
|
||||||
|
|
||||||
var duration = DateTime.UtcNow - testStart;
|
|
||||||
OverviewLog($" > Test passed. ({Time.FormatDuration(duration)})");
|
OverviewLog($" > Test passed. ({Time.FormatDuration(duration)})");
|
||||||
|
UpdateStatusLogPassed(testStart, duration);
|
||||||
|
|
||||||
if (!config.KeepPassedTestLogs)
|
if (!config.KeepPassedTestLogs)
|
||||||
{
|
{
|
||||||
@ -81,6 +85,7 @@ namespace ContinuousTests
|
|||||||
{
|
{
|
||||||
fixtureLog.Error("Test run failed with exception: " + ex);
|
fixtureLog.Error("Test run failed with exception: " + ex);
|
||||||
fixtureLog.MarkAsFailed();
|
fixtureLog.MarkAsFailed();
|
||||||
|
UpdateStatusLogFailed(testStart, duration, ex.ToString());
|
||||||
|
|
||||||
DownloadContainerLogs(testStart);
|
DownloadContainerLogs(testStart);
|
||||||
|
|
||||||
@ -170,6 +175,25 @@ namespace ContinuousTests
|
|||||||
throw new Exception(exceptionsMessage);
|
throw new Exception(exceptionsMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdateStatusLogFailed(DateTime testStart, TimeSpan duration, string error)
|
||||||
|
{
|
||||||
|
statusLog.ConcludeTest("Failed", duration, CreateStatusLogData(testStart, error));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateStatusLogPassed(DateTime testStart, TimeSpan duration)
|
||||||
|
{
|
||||||
|
statusLog.ConcludeTest("Passed", duration, CreateStatusLogData(testStart, "OK"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dictionary<string, string> CreateStatusLogData(DateTime testStart, string message)
|
||||||
|
{
|
||||||
|
var result = entryPoint.GetPluginMetadata();
|
||||||
|
result.Add("teststart", testStart.ToString("o"));
|
||||||
|
result.Add("testname", testName);
|
||||||
|
result.Add("message", message);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private string GetCombinedExceptionsMessage(Exception[] exceptions)
|
private string GetCombinedExceptionsMessage(Exception[] exceptions)
|
||||||
{
|
{
|
||||||
return string.Join(Environment.NewLine, exceptions.Select(ex => ex.ToString()));
|
return string.Join(Environment.NewLine, exceptions.Select(ex => ex.ToString()));
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using Logging;
|
using DistTestCore.Logs;
|
||||||
|
using Logging;
|
||||||
|
|
||||||
namespace ContinuousTests
|
namespace ContinuousTests
|
||||||
{
|
{
|
||||||
@ -8,6 +9,7 @@ namespace ContinuousTests
|
|||||||
private readonly TaskFactory taskFactory;
|
private readonly TaskFactory taskFactory;
|
||||||
private readonly Configuration config;
|
private readonly Configuration config;
|
||||||
private readonly ILog overviewLog;
|
private readonly ILog overviewLog;
|
||||||
|
private readonly StatusLog statusLog;
|
||||||
private readonly Type testType;
|
private readonly Type testType;
|
||||||
private readonly TimeSpan runsEvery;
|
private readonly TimeSpan runsEvery;
|
||||||
private readonly StartupChecker startupChecker;
|
private readonly StartupChecker startupChecker;
|
||||||
@ -15,12 +17,13 @@ namespace ContinuousTests
|
|||||||
private readonly EventWaitHandle runFinishedHandle = new EventWaitHandle(true, EventResetMode.ManualReset);
|
private readonly EventWaitHandle runFinishedHandle = new EventWaitHandle(true, EventResetMode.ManualReset);
|
||||||
private static object testLock = new object();
|
private static object testLock = new object();
|
||||||
|
|
||||||
public TestLoop(EntryPointFactory entryPointFactory, TaskFactory taskFactory, Configuration config, ILog overviewLog, Type testType, TimeSpan runsEvery, StartupChecker startupChecker, CancellationToken cancelToken)
|
public TestLoop(EntryPointFactory entryPointFactory, TaskFactory taskFactory, Configuration config, ILog overviewLog, StatusLog statusLog, Type testType, TimeSpan runsEvery, StartupChecker startupChecker, CancellationToken cancelToken)
|
||||||
{
|
{
|
||||||
this.entryPointFactory = entryPointFactory;
|
this.entryPointFactory = entryPointFactory;
|
||||||
this.taskFactory = taskFactory;
|
this.taskFactory = taskFactory;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.overviewLog = overviewLog;
|
this.overviewLog = overviewLog;
|
||||||
|
this.statusLog = statusLog;
|
||||||
this.testType = testType;
|
this.testType = testType;
|
||||||
this.runsEvery = runsEvery;
|
this.runsEvery = runsEvery;
|
||||||
this.startupChecker = startupChecker;
|
this.startupChecker = startupChecker;
|
||||||
@ -73,7 +76,7 @@ namespace ContinuousTests
|
|||||||
{
|
{
|
||||||
var test = (ContinuousTest)Activator.CreateInstance(testType)!;
|
var test = (ContinuousTest)Activator.CreateInstance(testType)!;
|
||||||
var handle = new TestHandle(test);
|
var handle = new TestHandle(test);
|
||||||
var run = new SingleTestRun(entryPointFactory, taskFactory, config, overviewLog, handle, startupChecker, cancelToken);
|
var run = new SingleTestRun(entryPointFactory, taskFactory, config, overviewLog, statusLog, handle, startupChecker, cancelToken);
|
||||||
|
|
||||||
runFinishedHandle.Reset();
|
runFinishedHandle.Reset();
|
||||||
run.Run(runFinishedHandle, result =>
|
run.Run(runFinishedHandle, result =>
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
using CodexPlugin;
|
using CodexPlugin;
|
||||||
using DistTestCore.Helpers;
|
using CodexTests.Helpers;
|
||||||
|
using ContinuousTests;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace ContinuousTests.Tests
|
namespace CodexContinuousTests.Tests
|
||||||
{
|
{
|
||||||
public class PeersTest : ContinuousTest
|
public class PeersTest : ContinuousTest
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
using CodexContractsPlugin;
|
using CodexContractsPlugin;
|
||||||
using CodexPlugin;
|
using CodexPlugin;
|
||||||
using GethPlugin;
|
using GethPlugin;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow.Types;
|
||||||
using Logging;
|
using Logging;
|
||||||
using MetricsPlugin;
|
using MetricsPlugin;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|||||||
@ -16,7 +16,10 @@ namespace CodexTests.BasicTests
|
|||||||
{
|
{
|
||||||
var primary = AddCodex(s => s.WithLogLevel(CodexLogLevel.Trace, new CodexLogCustomTopics(CodexLogLevel.Warn, CodexLogLevel.Warn)));
|
var primary = AddCodex(s => s.WithLogLevel(CodexLogLevel.Trace, new CodexLogCustomTopics(CodexLogLevel.Warn, CodexLogLevel.Warn)));
|
||||||
|
|
||||||
primary.UploadFile(GenerateTestFile(5.MB()));
|
var cid = primary.UploadFile(GenerateTestFile(5.MB()));
|
||||||
|
|
||||||
|
var content = primary.LocalFiles();
|
||||||
|
CollectionAssert.Contains(content.Select(c => c.Cid), cid);
|
||||||
|
|
||||||
var log = Ci.DownloadLog(primary);
|
var log = Ci.DownloadLog(primary);
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
using CodexContractsPlugin;
|
using CodexContractsPlugin;
|
||||||
using CodexNetDeployer;
|
using CodexNetDeployer;
|
||||||
using CodexPlugin;
|
using CodexPlugin;
|
||||||
|
using CodexTests.Helpers;
|
||||||
using Core;
|
using Core;
|
||||||
using DistTestCore;
|
using DistTestCore;
|
||||||
using DistTestCore.Helpers;
|
using DistTestCore.Helpers;
|
||||||
using DistTestCore.Logs;
|
using DistTestCore.Logs;
|
||||||
using GethPlugin;
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NUnit.Framework.Constraints;
|
using NUnit.Framework.Constraints;
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
using CodexContractsPlugin;
|
using CodexContractsPlugin;
|
||||||
using CodexTests;
|
|
||||||
using GethPlugin;
|
using GethPlugin;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
namespace Tests.DownloadConnectivityTests
|
namespace CodexTests.DownloadConnectivityTests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class FullyConnectedDownloadTests : AutoBootstrapDistTest
|
public class FullyConnectedDownloadTests : AutoBootstrapDistTest
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
using Logging;
|
using Logging;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace DistTestCore.Helpers
|
namespace CodexTests.Helpers
|
||||||
{
|
{
|
||||||
public interface IFullConnectivityImplementation
|
public interface IFullConnectivityImplementation
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
using CodexPlugin;
|
using CodexPlugin;
|
||||||
using Logging;
|
using Logging;
|
||||||
using static DistTestCore.Helpers.FullConnectivityHelper;
|
using static CodexTests.Helpers.FullConnectivityHelper;
|
||||||
|
|
||||||
namespace DistTestCore.Helpers
|
namespace CodexTests.Helpers
|
||||||
{
|
{
|
||||||
public class PeerConnectionTestHelpers : IFullConnectivityImplementation
|
public class PeerConnectionTestHelpers : IFullConnectivityImplementation
|
||||||
{
|
{
|
||||||
|
|||||||
@ -2,9 +2,9 @@
|
|||||||
using FileUtils;
|
using FileUtils;
|
||||||
using Logging;
|
using Logging;
|
||||||
using Utils;
|
using Utils;
|
||||||
using static DistTestCore.Helpers.FullConnectivityHelper;
|
using static CodexTests.Helpers.FullConnectivityHelper;
|
||||||
|
|
||||||
namespace DistTestCore.Helpers
|
namespace CodexTests.Helpers
|
||||||
{
|
{
|
||||||
public class PeerDownloadTestHelpers : IFullConnectivityImplementation
|
public class PeerDownloadTestHelpers : IFullConnectivityImplementation
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
using CodexPlugin;
|
using CodexPlugin;
|
||||||
using CodexTests;
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace Tests.PeerDiscoveryTests
|
namespace CodexTests.PeerDiscoveryTests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class LayeredDiscoveryTests : CodexDistTest
|
public class LayeredDiscoveryTests : CodexDistTest
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
using CodexContractsPlugin;
|
using CodexContractsPlugin;
|
||||||
using CodexTests;
|
using CodexPlugin;
|
||||||
using GethPlugin;
|
using GethPlugin;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace Tests.PeerDiscoveryTests
|
namespace CodexTests.PeerDiscoveryTests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class PeerDiscoveryTests : AutoBootstrapDistTest
|
public class PeerDiscoveryTests : AutoBootstrapDistTest
|
||||||
@ -49,7 +49,45 @@ namespace Tests.PeerDiscoveryTests
|
|||||||
|
|
||||||
private void AssertAllNodesConnected()
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,7 +29,7 @@ namespace DistTestCore
|
|||||||
var logConfig = configuration.GetLogConfig();
|
var logConfig = configuration.GetLogConfig();
|
||||||
var startTime = DateTime.UtcNow;
|
var startTime = DateTime.UtcNow;
|
||||||
fixtureLog = new FixtureLog(logConfig, startTime);
|
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());
|
globalEntryPoint = new EntryPoint(fixtureLog, configuration.GetK8sConfiguration(new DefaultTimeSet(), TestNamespacePrefix), configuration.GetFileManagerFolder());
|
||||||
|
|
||||||
@ -58,6 +58,7 @@ namespace DistTestCore
|
|||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fixtureLog.Log("Test framework revision: " + GitInfo.GetStatus());
|
||||||
fixtureLog.Log("Global setup cleanup successful");
|
fixtureLog.Log("Global setup cleanup successful");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="LibGit2Sharp" Version="0.28.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="nunit" Version="3.13.3" />
|
<PackageReference Include="nunit" Version="3.13.3" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.4.2" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.4.2" />
|
||||||
|
|||||||
39
Tests/DistTestCore/GitInfo.cs
Normal file
39
Tests/DistTestCore/GitInfo.cs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
using KubernetesWorkflow;
|
||||||
|
using LibGit2Sharp;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace DistTestCore
|
||||||
|
{
|
||||||
|
public static class GitInfo
|
||||||
|
{
|
||||||
|
private static string? status = null;
|
||||||
|
|
||||||
|
public static string GetStatus()
|
||||||
|
{
|
||||||
|
if (status == null) status = DetermineStatus();
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string DetermineStatus()
|
||||||
|
{
|
||||||
|
var path = FindGitPath();
|
||||||
|
if (path == null) return "unknown";
|
||||||
|
|
||||||
|
using var repo = new Repository(path);
|
||||||
|
var sha = repo.Head.Tip.Sha.Substring(0, 7);
|
||||||
|
|
||||||
|
return K8sNameUtils.Format(sha);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string? FindGitPath()
|
||||||
|
{
|
||||||
|
var path = Repository.Discover(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
|
||||||
|
if (!string.IsNullOrEmpty(path)) return path;
|
||||||
|
|
||||||
|
path = Repository.Discover(Directory.GetCurrentDirectory());
|
||||||
|
if (!string.IsNullOrEmpty(path)) return path;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
using Logging;
|
using Logging;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using Utils;
|
||||||
|
|
||||||
namespace DistTestCore.Logs
|
namespace DistTestCore.Logs
|
||||||
{
|
{
|
||||||
@ -8,11 +9,18 @@ namespace DistTestCore.Logs
|
|||||||
private readonly object fileLock = new object();
|
private readonly object fileLock = new object();
|
||||||
private readonly string fullName;
|
private readonly string fullName;
|
||||||
private readonly string fixtureName;
|
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";
|
fullName = NameUtils.GetFixtureFullName(config, start, name) + "_STATUS.log";
|
||||||
fixtureName = NameUtils.GetRawFixtureName();
|
fixtureName = NameUtils.GetRawFixtureName();
|
||||||
|
this.testType = testType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ConcludeTest(string resultStatus, TimeSpan testDuration, Dictionary<string, string> data)
|
||||||
|
{
|
||||||
|
ConcludeTest(resultStatus, Time.FormatDuration(testDuration), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ConcludeTest(string resultStatus, string testDuration, Dictionary<string, string> data)
|
public void ConcludeTest(string resultStatus, string testDuration, Dictionary<string, string> data)
|
||||||
@ -20,11 +28,13 @@ namespace DistTestCore.Logs
|
|||||||
data.Add("timestamp", DateTime.UtcNow.ToString("o"));
|
data.Add("timestamp", DateTime.UtcNow.ToString("o"));
|
||||||
data.Add("runid", NameUtils.GetRunId());
|
data.Add("runid", NameUtils.GetRunId());
|
||||||
data.Add("status", resultStatus);
|
data.Add("status", resultStatus);
|
||||||
data.Add("testid", NameUtils.GetTestId());
|
|
||||||
data.Add("category", NameUtils.GetCategoryName());
|
data.Add("category", NameUtils.GetCategoryName());
|
||||||
data.Add("fixturename", fixtureName);
|
data.Add("fixturename", fixtureName);
|
||||||
data.Add("testname", NameUtils.GetTestMethodName());
|
if (!data.ContainsKey("testname")) data.Add("testname", NameUtils.GetTestMethodName());
|
||||||
|
data.Add("testid", NameUtils.GetTestId());
|
||||||
|
data.Add("testtype", testType);
|
||||||
data.Add("testduration", testDuration);
|
data.Add("testduration", testDuration);
|
||||||
|
data.Add("testframeworkrevision", GitInfo.GetStatus());
|
||||||
Write(data);
|
Write(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,8 @@
|
|||||||
using DistTestCore.Logs;
|
using DistTestCore.Logs;
|
||||||
using FileUtils;
|
using FileUtils;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow;
|
||||||
|
using KubernetesWorkflow.Recipe;
|
||||||
|
using KubernetesWorkflow.Types;
|
||||||
using Utils;
|
using Utils;
|
||||||
|
|
||||||
namespace DistTestCore
|
namespace DistTestCore
|
||||||
@ -80,6 +82,7 @@ namespace DistTestCore
|
|||||||
recipe.PodLabels.Add("category", NameUtils.GetCategoryName());
|
recipe.PodLabels.Add("category", NameUtils.GetCategoryName());
|
||||||
recipe.PodLabels.Add("fixturename", NameUtils.GetRawFixtureName());
|
recipe.PodLabels.Add("fixturename", NameUtils.GetRawFixtureName());
|
||||||
recipe.PodLabels.Add("testname", NameUtils.GetTestMethodName());
|
recipe.PodLabels.Add("testname", NameUtils.GetTestMethodName());
|
||||||
|
recipe.PodLabels.Add("testframeworkrevision", GitInfo.GetStatus());
|
||||||
|
|
||||||
foreach (var pair in metadata)
|
foreach (var pair in metadata)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -3,7 +3,7 @@ using CodexDiscordBotPlugin;
|
|||||||
using CodexPlugin;
|
using CodexPlugin;
|
||||||
using Core;
|
using Core;
|
||||||
using GethPlugin;
|
using GethPlugin;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow.Types;
|
||||||
using Logging;
|
using Logging;
|
||||||
using MetricsPlugin;
|
using MetricsPlugin;
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
using DistTestCore;
|
using DistTestCore;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow;
|
||||||
|
using KubernetesWorkflow.Recipe;
|
||||||
|
using KubernetesWorkflow.Types;
|
||||||
|
|
||||||
namespace CodexNetDeployer
|
namespace CodexNetDeployer
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
using DistTestCore.Helpers;
|
using CodexTests.Helpers;
|
||||||
using Logging;
|
using Logging;
|
||||||
|
|
||||||
namespace CodexNetDeployer
|
namespace CodexNetDeployer
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow.Types;
|
||||||
|
|
||||||
namespace TestClusterStarter
|
namespace TestClusterStarter
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
using ArgsUniform;
|
using ArgsUniform;
|
||||||
using Core;
|
using Core;
|
||||||
using DeployAndRunPlugin;
|
using DeployAndRunPlugin;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow.Types;
|
||||||
using Logging;
|
using Logging;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using TestClusterStarter;
|
using TestClusterStarter;
|
||||||
|
|||||||
@ -30,7 +30,7 @@ spec:
|
|||||||
- name: KUBECONFIG
|
- name: KUBECONFIG
|
||||||
value: "/opt/kubeconfig.yaml"
|
value: "/opt/kubeconfig.yaml"
|
||||||
- name: LOGPATH
|
- name: LOGPATH
|
||||||
value: "/var/log/codex-continuous-tests"
|
value: "/var/log/codex-continuous-tests/${DEPLOYMENT_NAMESPACE}"
|
||||||
- name: NAMESPACE
|
- name: NAMESPACE
|
||||||
value: "${NAMESPACE}"
|
value: "${NAMESPACE}"
|
||||||
- name: BRANCH
|
- name: BRANCH
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user