Merge branch 'feature/codex-net-deployer' into feature/continuous-testing
This commit is contained in:
commit
a21078f4a9
|
@ -0,0 +1,93 @@
|
|||
namespace CodexNetDeployer
|
||||
{
|
||||
public class ArgOrVar
|
||||
{
|
||||
public static readonly ArgVar CodexImage = new ArgVar("codex-image", "CODEXIMAGE", "Docker image of Codex.");
|
||||
public static readonly ArgVar GethImage = new ArgVar("geth-image", "GETHIMAGE", "Docker image of Geth.");
|
||||
public static readonly ArgVar ContractsImage = new ArgVar("contracts-image", "CONTRACTSIMAGE", "Docker image of Codex Contracts deployer.");
|
||||
public static readonly ArgVar KubeConfigFile = new ArgVar("kube-config", "KUBECONFIG", "Path to Kubeconfig file.");
|
||||
public static readonly ArgVar KubeNamespace = new ArgVar("kube-namespace", "KUBENAMESPACE", "Kubernetes namespace to be used for deployment.");
|
||||
public static readonly ArgVar NumberOfCodexNodes = new ArgVar("nodes", "NODES", "Number of Codex nodes to be created.");
|
||||
public static readonly ArgVar NumberOfValidatorNodes = new ArgVar("validators", "VALIDATORS", "Number of Codex nodes that will be validating.");
|
||||
public static readonly ArgVar StorageQuota = new ArgVar("storage-quota", "STORAGEQUOTA", "Storage quota in megabytes used by each Codex node.");
|
||||
public static readonly ArgVar LogLevel = new ArgVar("log-level", "LOGLEVEL", "Log level used by each Codex node. [Trace, Debug*, Info, Warn, Error]");
|
||||
|
||||
private readonly string[] args;
|
||||
|
||||
public ArgOrVar(string[] args)
|
||||
{
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public string Get(ArgVar key, string defaultValue = "")
|
||||
{
|
||||
var argKey = $"--{key.Arg}=";
|
||||
var arg = args.FirstOrDefault(a => a.StartsWith(argKey));
|
||||
if (arg != null)
|
||||
{
|
||||
return arg.Substring(argKey.Length);
|
||||
}
|
||||
|
||||
var env = Environment.GetEnvironmentVariable(key.Var);
|
||||
if (env != null)
|
||||
{
|
||||
return env;
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public int? GetInt(ArgVar key)
|
||||
{
|
||||
var str = Get(key);
|
||||
if (string.IsNullOrEmpty(str)) return null;
|
||||
if (int.TryParse(str, out int result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void PrintHelp()
|
||||
{
|
||||
var nl = Environment.NewLine;
|
||||
Console.WriteLine("CodexNetDeployer allows you to easily deploy multiple Codex nodes in a Kubernetes cluster. " +
|
||||
"The deployer will set up the required supporting services, deploy the Codex on-chain contracts, start and bootstrap the Codex instances. " +
|
||||
"All Kubernetes objects will be created in the namespace provided, allowing you to easily find, modify, and delete them afterwards." + nl);
|
||||
|
||||
Console.WriteLine("CodexNetDeployer assumes you are running this tool from *inside* the Kubernetes cluster you want to deploy to. " +
|
||||
"If you are not running this from a container inside the cluster, add the argument '--external'." + nl);
|
||||
|
||||
Console.Write("\t[ CLI argument ] or [ Environment variable ]");
|
||||
Console.CursorLeft = 70;
|
||||
Console.Write("(Description)" + nl);
|
||||
var fields = GetType().GetFields();
|
||||
foreach (var field in fields)
|
||||
{
|
||||
var value = (ArgVar)field.GetValue(null)!;
|
||||
value.PrintHelp();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ArgVar
|
||||
{
|
||||
public ArgVar(string arg, string var, string description)
|
||||
{
|
||||
Arg = arg;
|
||||
Var = var;
|
||||
Description = description;
|
||||
}
|
||||
|
||||
public string Arg { get; }
|
||||
public string Var { get; }
|
||||
public string Description { get; }
|
||||
|
||||
public void PrintHelp()
|
||||
{
|
||||
Console.Write($"\t[ --{Arg}=... ] or [ {Var}=... ]");
|
||||
Console.CursorLeft = 70;
|
||||
Console.Write(Description + Environment.NewLine);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DistTestCore\DistTestCore.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,75 @@
|
|||
using DistTestCore;
|
||||
using DistTestCore.Codex;
|
||||
using DistTestCore.Marketplace;
|
||||
using KubernetesWorkflow;
|
||||
using Logging;
|
||||
|
||||
namespace CodexNetDeployer
|
||||
{
|
||||
public class CodexNodeStarter
|
||||
{
|
||||
private readonly Configuration config;
|
||||
private readonly WorkflowCreator workflowCreator;
|
||||
private readonly TestLifecycle lifecycle;
|
||||
private readonly BaseLog log;
|
||||
private readonly ITimeSet timeSet;
|
||||
private readonly GethStartResult gethResult;
|
||||
private string bootstrapSpr = "";
|
||||
private int validatorsLeft;
|
||||
|
||||
public CodexNodeStarter(Configuration config, WorkflowCreator workflowCreator, TestLifecycle lifecycle, BaseLog log, ITimeSet timeSet, GethStartResult gethResult, int numberOfValidators)
|
||||
{
|
||||
this.config = config;
|
||||
this.workflowCreator = workflowCreator;
|
||||
this.lifecycle = lifecycle;
|
||||
this.log = log;
|
||||
this.timeSet = timeSet;
|
||||
this.gethResult = gethResult;
|
||||
this.validatorsLeft = numberOfValidators;
|
||||
}
|
||||
|
||||
public RunningContainer? Start(int i)
|
||||
{
|
||||
Console.Write($" - {i} = ");
|
||||
var workflow = workflowCreator.CreateWorkflow();
|
||||
var workflowStartup = new StartupConfig();
|
||||
workflowStartup.Add(gethResult);
|
||||
workflowStartup.Add(CreateCodexStartupConfig(bootstrapSpr, i, validatorsLeft));
|
||||
|
||||
var containers = workflow.Start(1, Location.Unspecified, new CodexContainerRecipe(), workflowStartup);
|
||||
|
||||
var container = containers.Containers.First();
|
||||
var address = lifecycle.Configuration.GetAddress(container);
|
||||
var codexNode = new CodexNode(log, timeSet, address);
|
||||
var debugInfo = codexNode.GetDebugInfo();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(debugInfo.spr))
|
||||
{
|
||||
var pod = container.Pod.PodInfo;
|
||||
Console.Write($"Online ({pod.Name} at {pod.Ip} on '{pod.K8SNodeName}')" + Environment.NewLine);
|
||||
|
||||
if (string.IsNullOrEmpty(bootstrapSpr)) bootstrapSpr = debugInfo.spr;
|
||||
validatorsLeft--;
|
||||
return container;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Write("Unknown failure." + Environment.NewLine);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private CodexStartupConfig CreateCodexStartupConfig(string bootstrapSpr, int i, int validatorsLeft)
|
||||
{
|
||||
var codexStart = new CodexStartupConfig(config.CodexLogLevel);
|
||||
|
||||
if (!string.IsNullOrEmpty(bootstrapSpr)) codexStart.BootstrapSpr = bootstrapSpr;
|
||||
codexStart.StorageQuota = config.StorageQuota!.Value.MB();
|
||||
var marketplaceConfig = new MarketplaceInitialConfig(100000.Eth(), 0.TestTokens(), validatorsLeft > 0);
|
||||
marketplaceConfig.AccountIndexOverride = i;
|
||||
codexStart.MarketplaceConfig = marketplaceConfig;
|
||||
|
||||
return codexStart;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
using DistTestCore;
|
||||
using DistTestCore.Codex;
|
||||
|
||||
namespace CodexNetDeployer
|
||||
{
|
||||
public class Configuration
|
||||
{
|
||||
public Configuration(
|
||||
string codexImage,
|
||||
string gethImage,
|
||||
string contractsImage,
|
||||
string kubeConfigFile,
|
||||
string kubeNamespace,
|
||||
int? numberOfCodexNodes,
|
||||
int? numberOfValidators,
|
||||
int? storageQuota,
|
||||
CodexLogLevel codexLogLevel,
|
||||
TestRunnerLocation runnerLocation)
|
||||
{
|
||||
CodexImage = codexImage;
|
||||
GethImage = gethImage;
|
||||
ContractsImage = contractsImage;
|
||||
KubeConfigFile = kubeConfigFile;
|
||||
KubeNamespace = kubeNamespace;
|
||||
NumberOfCodexNodes = numberOfCodexNodes;
|
||||
NumberOfValidators = numberOfValidators;
|
||||
StorageQuota = storageQuota;
|
||||
CodexLogLevel = codexLogLevel;
|
||||
RunnerLocation = runnerLocation;
|
||||
}
|
||||
|
||||
public string CodexImage { get; }
|
||||
public string GethImage { get; }
|
||||
public string ContractsImage { get; }
|
||||
public string KubeConfigFile { get; }
|
||||
public string KubeNamespace { get; }
|
||||
public int? NumberOfCodexNodes { get; }
|
||||
public int? NumberOfValidators { get; }
|
||||
public int? StorageQuota { get; }
|
||||
public CodexLogLevel CodexLogLevel { get; }
|
||||
public TestRunnerLocation RunnerLocation { get; }
|
||||
|
||||
public void PrintConfig()
|
||||
{
|
||||
ForEachProperty(onString: Print, onInt: Print);
|
||||
}
|
||||
|
||||
public List<string> Validate()
|
||||
{
|
||||
var errors = new List<string>();
|
||||
|
||||
ForEachProperty(
|
||||
onString: (n, v) => StringIsSet(n, v, errors),
|
||||
onInt: (n, v) => IntIsOverZero(n, v, errors));
|
||||
|
||||
if (NumberOfValidators > NumberOfCodexNodes)
|
||||
{
|
||||
errors.Add($"{nameof(NumberOfValidators)} ({NumberOfValidators}) may not be greater than {nameof(NumberOfCodexNodes)} ({NumberOfCodexNodes}).");
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
private void ForEachProperty(Action<string, string> onString, Action<string, int?> onInt)
|
||||
{
|
||||
var properties = GetType().GetProperties();
|
||||
foreach (var p in properties)
|
||||
{
|
||||
if (p.PropertyType == typeof(string)) onString(p.Name, (string)p.GetValue(this)!);
|
||||
if (p.PropertyType == typeof(int?)) onInt(p.Name, (int?)p.GetValue(this)!);
|
||||
}
|
||||
}
|
||||
|
||||
private static void IntIsOverZero(string variable, int? value, List<string> errors)
|
||||
{
|
||||
if (value == null || value.Value < 1)
|
||||
{
|
||||
errors.Add($"{variable} is must be set and must be greater than 0.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void StringIsSet(string variable, string value, List<string> errors)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
errors.Add($"{variable} is must be set.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void Print(string variable, string value)
|
||||
{
|
||||
Console.WriteLine($"\t{variable}: '{value}'");
|
||||
}
|
||||
|
||||
private static void Print(string variable, int? value)
|
||||
{
|
||||
if (value != null) Print(variable, value.ToString()!);
|
||||
else Print(variable, "<NONE>");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
using DistTestCore;
|
||||
using DistTestCore.Codex;
|
||||
using KubernetesWorkflow;
|
||||
|
||||
namespace CodexNetDeployer
|
||||
{
|
||||
public class Deployer
|
||||
{
|
||||
private readonly Configuration config;
|
||||
private readonly NullLog log;
|
||||
private readonly DefaultTimeSet timeset;
|
||||
|
||||
public Deployer(Configuration config)
|
||||
{
|
||||
this.config = config;
|
||||
log = new NullLog();
|
||||
timeset = new DefaultTimeSet();
|
||||
}
|
||||
|
||||
public CodexDeployment Deploy()
|
||||
{
|
||||
Log("Initializing...");
|
||||
var (workflowCreator, lifecycle) = CreateFacilities();
|
||||
|
||||
Log("Preparing configuration...");
|
||||
// We trick the Geth companion node into unlocking all of its accounts, by saying we want to start 999 codex nodes.
|
||||
var setup = new CodexSetup(999, config.CodexLogLevel);
|
||||
setup.WithStorageQuota(config.StorageQuota!.Value.MB()).EnableMarketplace(0.TestTokens());
|
||||
|
||||
Log("Creating Geth instance and deploying contracts...");
|
||||
var gethStarter = new GethStarter(lifecycle, workflowCreator);
|
||||
var gethResults = gethStarter.BringOnlineMarketplaceFor(setup);
|
||||
|
||||
Log("Geth started. Codex contracts deployed.");
|
||||
Log("Warning: It can take up to 45 minutes for the Geth node to finish unlocking all if its 1000 preconfigured accounts.");
|
||||
|
||||
Log("Starting Codex nodes...");
|
||||
|
||||
// Each node must have its own IP, so it needs it own pod. Start them 1 at a time.
|
||||
var codexStarter = new CodexNodeStarter(config, workflowCreator, lifecycle, log, timeset, gethResults, config.NumberOfValidators!.Value);
|
||||
var codexContainers = new List<RunningContainer>();
|
||||
for (var i = 0; i < config.NumberOfCodexNodes; i++)
|
||||
{
|
||||
var container = codexStarter.Start(i);
|
||||
if (container != null) codexContainers.Add(container);
|
||||
}
|
||||
|
||||
return new CodexDeployment(gethResults, codexContainers.ToArray());
|
||||
}
|
||||
|
||||
private (WorkflowCreator, TestLifecycle) CreateFacilities()
|
||||
{
|
||||
var lifecycleConfig = new DistTestCore.Configuration
|
||||
(
|
||||
kubeConfigFile: config.KubeConfigFile,
|
||||
logPath: "null",
|
||||
logDebug: false,
|
||||
dataFilesPath: "notUsed",
|
||||
codexLogLevel: config.CodexLogLevel,
|
||||
runnerLocation: config.RunnerLocation
|
||||
);
|
||||
|
||||
var kubeConfig = new KubernetesWorkflow.Configuration(
|
||||
k8sNamespacePrefix: config.KubeNamespace,
|
||||
kubeConfigFile: config.KubeConfigFile,
|
||||
operationTimeout: timeset.K8sOperationTimeout(),
|
||||
retryDelay: timeset.WaitForK8sServiceDelay());
|
||||
|
||||
var workflowCreator = new WorkflowCreator(log, kubeConfig);
|
||||
var lifecycle = new TestLifecycle(log, lifecycleConfig, timeset, workflowCreator);
|
||||
|
||||
return (workflowCreator, lifecycle);
|
||||
}
|
||||
|
||||
private void Log(string msg)
|
||||
{
|
||||
Console.WriteLine(msg);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
using Logging;
|
||||
|
||||
namespace CodexNetDeployer
|
||||
{
|
||||
public class NullLog : TestLog
|
||||
{
|
||||
public NullLog() : base("NULL", false, "NULL")
|
||||
{
|
||||
}
|
||||
|
||||
protected override LogFile CreateLogFile()
|
||||
{
|
||||
return null!;
|
||||
}
|
||||
|
||||
public override void Log(string message)
|
||||
{
|
||||
//Console.WriteLine(message);
|
||||
}
|
||||
|
||||
public override void Debug(string message = "", int skipFrames = 0)
|
||||
{
|
||||
//Console.WriteLine(message);
|
||||
}
|
||||
|
||||
public override void Error(string message)
|
||||
{
|
||||
Console.WriteLine("Error: " + message);
|
||||
}
|
||||
|
||||
public override void MarkAsFailed()
|
||||
{
|
||||
}
|
||||
|
||||
public override void AddStringReplace(string from, string to)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Delete()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
using CodexNetDeployer;
|
||||
using DistTestCore;
|
||||
using DistTestCore.Codex;
|
||||
using DistTestCore.Marketplace;
|
||||
using Newtonsoft.Json;
|
||||
using Utils;
|
||||
using Configuration = CodexNetDeployer.Configuration;
|
||||
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var nl = Environment.NewLine;
|
||||
Console.WriteLine("CodexNetDeployer" + nl + nl);
|
||||
|
||||
var argOrVar = new ArgOrVar(args);
|
||||
|
||||
if (args.Any(a => a == "-h" || a == "--help" || a == "-?"))
|
||||
{
|
||||
argOrVar.PrintHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
var location = TestRunnerLocation.InternalToCluster;
|
||||
if (args.Any(a => a == "--external"))
|
||||
{
|
||||
location = TestRunnerLocation.ExternalToCluster;
|
||||
}
|
||||
|
||||
var config = new Configuration(
|
||||
codexImage: argOrVar.Get(ArgOrVar.CodexImage, CodexContainerRecipe.DockerImage),
|
||||
gethImage: argOrVar.Get(ArgOrVar.GethImage, GethContainerRecipe.DockerImage),
|
||||
contractsImage: argOrVar.Get(ArgOrVar.ContractsImage, CodexContractsContainerRecipe.DockerImage),
|
||||
kubeConfigFile: argOrVar.Get(ArgOrVar.KubeConfigFile),
|
||||
kubeNamespace: argOrVar.Get(ArgOrVar.KubeNamespace),
|
||||
numberOfCodexNodes: argOrVar.GetInt(ArgOrVar.NumberOfCodexNodes),
|
||||
numberOfValidators: argOrVar.GetInt(ArgOrVar.NumberOfValidatorNodes),
|
||||
storageQuota: argOrVar.GetInt(ArgOrVar.StorageQuota),
|
||||
codexLogLevel: ParseEnum.Parse<CodexLogLevel>(argOrVar.Get(ArgOrVar.LogLevel, nameof(CodexLogLevel.Debug))),
|
||||
runnerLocation: location
|
||||
);
|
||||
|
||||
Console.WriteLine("Using:");
|
||||
config.PrintConfig();
|
||||
Console.WriteLine(nl);
|
||||
|
||||
var errors = config.Validate();
|
||||
if (errors.Any())
|
||||
{
|
||||
Console.WriteLine($"Configuration errors: ({errors.Count})");
|
||||
foreach ( var error in errors ) Console.WriteLine("\t" + error);
|
||||
Console.WriteLine(nl);
|
||||
argOrVar.PrintHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
var deployer = new Deployer(config);
|
||||
var deployment = deployer.Deploy();
|
||||
|
||||
Console.WriteLine("Writing codex-deployment.json...");
|
||||
|
||||
File.WriteAllText("codex-deployment.json", JsonConvert.SerializeObject(deployment, Formatting.Indented));
|
||||
|
||||
Console.WriteLine("Done!");
|
||||
}
|
||||
}
|
|
@ -50,7 +50,7 @@ namespace DistTestCore.Codex
|
|||
{
|
||||
var gethConfig = startupConfig.Get<GethStartResult>();
|
||||
var companionNode = gethConfig.CompanionNode;
|
||||
var companionNodeAccount = companionNode.Accounts[Index];
|
||||
var companionNodeAccount = companionNode.Accounts[GetAccountIndex(config.MarketplaceConfig)];
|
||||
Additional(companionNodeAccount);
|
||||
|
||||
var ip = companionNode.RunningContainer.Pod.PodInfo.Ip;
|
||||
|
@ -60,7 +60,18 @@ namespace DistTestCore.Codex
|
|||
AddEnvVar("ETH_ACCOUNT", companionNodeAccount.Account);
|
||||
AddEnvVar("ETH_MARKETPLACE_ADDRESS", gethConfig.MarketplaceNetwork.Marketplace.Address);
|
||||
AddEnvVar("PERSISTENCE", "1");
|
||||
|
||||
if (config.MarketplaceConfig.IsValidator)
|
||||
{
|
||||
AddEnvVar("VALIDATOR", "1");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int GetAccountIndex(MarketplaceInitialConfig marketplaceConfig)
|
||||
{
|
||||
if (marketplaceConfig.AccountIndexOverride != null) return marketplaceConfig.AccountIndexOverride.Value;
|
||||
return Index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
using DistTestCore.Marketplace;
|
||||
using KubernetesWorkflow;
|
||||
|
||||
namespace DistTestCore.Codex
|
||||
{
|
||||
public class CodexDeployment
|
||||
{
|
||||
public CodexDeployment(GethStartResult gethStartResult, RunningContainer[] codexContainers)
|
||||
{
|
||||
GethStartResult = gethStartResult;
|
||||
CodexContainers = codexContainers;
|
||||
}
|
||||
|
||||
public GethStartResult GethStartResult { get; }
|
||||
public RunningContainer[] CodexContainers { get; }
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@ namespace DistTestCore
|
|||
ICodexSetup EnableMetrics();
|
||||
ICodexSetup EnableMarketplace(TestToken initialBalance);
|
||||
ICodexSetup EnableMarketplace(TestToken initialBalance, Ether initialEther);
|
||||
ICodexSetup EnableMarketplace(TestToken initialBalance, Ether initialEther, bool isValidator);
|
||||
}
|
||||
|
||||
public class CodexSetup : CodexStartupConfig, ICodexSetup
|
||||
|
@ -62,7 +63,12 @@ namespace DistTestCore
|
|||
|
||||
public ICodexSetup EnableMarketplace(TestToken initialBalance, Ether initialEther)
|
||||
{
|
||||
MarketplaceConfig = new MarketplaceInitialConfig(initialEther, initialBalance);
|
||||
return EnableMarketplace(initialBalance, initialEther, false);
|
||||
}
|
||||
|
||||
public ICodexSetup EnableMarketplace(TestToken initialBalance, Ether initialEther, bool isValidator)
|
||||
{
|
||||
MarketplaceConfig = new MarketplaceInitialConfig(initialEther, initialBalance, isValidator);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,10 +17,20 @@ namespace DistTestCore
|
|||
{
|
||||
kubeConfigFile = GetNullableEnvVarOrDefault("KUBECONFIG", null);
|
||||
logPath = GetEnvVarOrDefault("LOGPATH", "CodexTestLogs");
|
||||
logDebug = GetEnvVarOrDefault("LOGDEBUG", "false").ToLowerInvariant() == "true";
|
||||
logDebug = GetEnvVarOrDefault("LOGDEBUG", "true").ToLowerInvariant() == "true";
|
||||
dataFilesPath = GetEnvVarOrDefault("DATAFILEPATH", "TestDataFiles");
|
||||
codexLogLevel = ParseEnum<CodexLogLevel>(GetEnvVarOrDefault("LOGLEVEL", nameof(CodexLogLevel.Trace)));
|
||||
runnerLocation = ParseEnum<TestRunnerLocation>(GetEnvVarOrDefault("RUNNERLOCATION", nameof(TestRunnerLocation.ExternalToCluster)));
|
||||
codexLogLevel = ParseEnum.Parse<CodexLogLevel>(GetEnvVarOrDefault("LOGLEVEL", nameof(CodexLogLevel.Trace)));
|
||||
runnerLocation = ParseEnum.Parse<TestRunnerLocation>(GetEnvVarOrDefault("RUNNERLOCATION", nameof(TestRunnerLocation.ExternalToCluster)));
|
||||
}
|
||||
|
||||
public Configuration(string? kubeConfigFile, string logPath, bool logDebug, string dataFilesPath, CodexLogLevel codexLogLevel, TestRunnerLocation runnerLocation)
|
||||
{
|
||||
this.kubeConfigFile = kubeConfigFile;
|
||||
this.logPath = logPath;
|
||||
this.logDebug = logDebug;
|
||||
this.dataFilesPath = dataFilesPath;
|
||||
this.codexLogLevel = codexLogLevel;
|
||||
this.runnerLocation = runnerLocation;
|
||||
}
|
||||
|
||||
public KubernetesWorkflow.Configuration GetK8sConfiguration(ITimeSet timeSet)
|
||||
|
@ -75,11 +85,6 @@ namespace DistTestCore
|
|||
if (v == null) return defaultValue;
|
||||
return v;
|
||||
}
|
||||
|
||||
private static T ParseEnum<T>(string value)
|
||||
{
|
||||
return (T)Enum.Parse(typeof(T), value, true);
|
||||
}
|
||||
}
|
||||
|
||||
public enum TestRunnerLocation
|
||||
|
|
|
@ -33,6 +33,8 @@ namespace DistTestCore
|
|||
|
||||
private void TransferInitialBalance(MarketplaceNetwork marketplaceNetwork, MarketplaceInitialConfig marketplaceConfig, GethCompanionNodeInfo companionNode)
|
||||
{
|
||||
if (marketplaceConfig.InitialTestTokens.Amount == 0) return;
|
||||
|
||||
var interaction = marketplaceNetwork.StartInteraction(lifecycle);
|
||||
var tokenAddress = marketplaceNetwork.Marketplace.TokenAddress;
|
||||
|
||||
|
|
|
@ -2,13 +2,16 @@
|
|||
{
|
||||
public class MarketplaceInitialConfig
|
||||
{
|
||||
public MarketplaceInitialConfig(Ether initialEth, TestToken initialTestTokens)
|
||||
public MarketplaceInitialConfig(Ether initialEth, TestToken initialTestTokens, bool isValidator)
|
||||
{
|
||||
InitialEth = initialEth;
|
||||
InitialTestTokens = initialTestTokens;
|
||||
IsValidator = isValidator;
|
||||
}
|
||||
|
||||
public Ether InitialEth { get; }
|
||||
public TestToken InitialTestTokens { get; }
|
||||
public bool IsValidator { get; }
|
||||
public int? AccountIndexOverride { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,15 +7,18 @@ namespace DistTestCore
|
|||
{
|
||||
public class TestLifecycle
|
||||
{
|
||||
private readonly WorkflowCreator workflowCreator;
|
||||
private DateTime testStart = DateTime.MinValue;
|
||||
|
||||
public TestLifecycle(TestLog log, Configuration configuration, ITimeSet timeSet)
|
||||
: this(log, configuration, timeSet, new WorkflowCreator(log, configuration.GetK8sConfiguration(timeSet)))
|
||||
{
|
||||
}
|
||||
|
||||
public TestLifecycle(TestLog log, Configuration configuration, ITimeSet timeSet, WorkflowCreator workflowCreator)
|
||||
{
|
||||
Log = log;
|
||||
Configuration = configuration;
|
||||
TimeSet = timeSet;
|
||||
workflowCreator = new WorkflowCreator(log, configuration.GetK8sConfiguration(timeSet));
|
||||
|
||||
FileManager = new FileManager(Log, configuration);
|
||||
CodexStarter = new CodexStarter(this, workflowCreator);
|
||||
|
|
|
@ -25,12 +25,12 @@ namespace Logging
|
|||
}
|
||||
}
|
||||
|
||||
public void Log(string message)
|
||||
public virtual void Log(string message)
|
||||
{
|
||||
LogFile.Write(ApplyReplacements(message));
|
||||
}
|
||||
|
||||
public void Debug(string message = "", int skipFrames = 0)
|
||||
public virtual void Debug(string message = "", int skipFrames = 0)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
|
@ -40,25 +40,25 @@ namespace Logging
|
|||
}
|
||||
}
|
||||
|
||||
public void Error(string message)
|
||||
public virtual void Error(string message)
|
||||
{
|
||||
Log($"[ERROR] {message}");
|
||||
}
|
||||
|
||||
public void MarkAsFailed()
|
||||
public virtual void MarkAsFailed()
|
||||
{
|
||||
if (hasFailed) return;
|
||||
hasFailed = true;
|
||||
LogFile.ConcatToFilename("_FAILED");
|
||||
}
|
||||
|
||||
public void AddStringReplace(string from, string to)
|
||||
public virtual void AddStringReplace(string from, string to)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(from)) return;
|
||||
replacements.Add(new BaseLogStringReplacement(from, to));
|
||||
}
|
||||
|
||||
public void Delete()
|
||||
public virtual void Delete()
|
||||
{
|
||||
File.Delete(LogFile.FullFilename);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
namespace Utils
|
||||
{
|
||||
public static class ParseEnum
|
||||
{
|
||||
public static T Parse<T>(string value)
|
||||
{
|
||||
return (T)Enum.Parse(typeof(T), value, true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,7 +17,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Logging", "Logging\Logging.
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NethereumWorkflow", "Nethereum\NethereumWorkflow.csproj", "{D6C3555E-D52D-4993-A87B-71AB650398FD}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContinuousTests", "ContinuousTests\ContinuousTests.csproj", "{025B7074-0A09-4FCC-9BB9-03AE2A961EA1}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ContinuousTests", "ContinuousTests\ContinuousTests.csproj", "{025B7074-0A09-4FCC-9BB9-03AE2A961EA1}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodexNetDeployer", "CodexNetDeployer\CodexNetDeployer.csproj", "{871CAF12-14BE-4509-BC6E-20FDF0B1083A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
@ -57,6 +59,10 @@ Global
|
|||
{025B7074-0A09-4FCC-9BB9-03AE2A961EA1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{025B7074-0A09-4FCC-9BB9-03AE2A961EA1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{025B7074-0A09-4FCC-9BB9-03AE2A961EA1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{871CAF12-14BE-4509-BC6E-20FDF0B1083A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{871CAF12-14BE-4509-BC6E-20FDF0B1083A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{871CAF12-14BE-4509-BC6E-20FDF0B1083A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{871CAF12-14BE-4509-BC6E-20FDF0B1083A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
Loading…
Reference in New Issue