Merge branch 'feature/continuous-testing'
This commit is contained in:
commit
4cda3ad22f
|
@ -0,0 +1,235 @@
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace ArgsUniform
|
||||||
|
{
|
||||||
|
public class ArgsUniform<T>
|
||||||
|
{
|
||||||
|
private readonly object? defaultsProvider;
|
||||||
|
private readonly IEnv.IEnv env;
|
||||||
|
private readonly string[] args;
|
||||||
|
private const int cliStart = 8;
|
||||||
|
private const int shortStart = 38;
|
||||||
|
private const int envStart = 48;
|
||||||
|
private const int descStart = 80;
|
||||||
|
|
||||||
|
public ArgsUniform(params string[] args)
|
||||||
|
: this(new IEnv.Env(), args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArgsUniform(object defaultsProvider, params string[] args)
|
||||||
|
: this(defaultsProvider, new IEnv.Env(), args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArgsUniform(IEnv.IEnv env, params string[] args)
|
||||||
|
: this(null!, env, args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArgsUniform(object defaultsProvider, IEnv.IEnv env, params string[] args)
|
||||||
|
{
|
||||||
|
this.defaultsProvider = defaultsProvider;
|
||||||
|
this.env = env;
|
||||||
|
this.args = args;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Parse(bool printResult = false)
|
||||||
|
{
|
||||||
|
var result = Activator.CreateInstance<T>();
|
||||||
|
var uniformProperties = typeof(T).GetProperties().Where(m => m.GetCustomAttributes(typeof(UniformAttribute), false).Length == 1).ToArray();
|
||||||
|
var missingRequired = new List<PropertyInfo>();
|
||||||
|
foreach (var uniformProperty in uniformProperties)
|
||||||
|
{
|
||||||
|
var attr = uniformProperty.GetCustomAttribute<UniformAttribute>();
|
||||||
|
if (attr != null)
|
||||||
|
{
|
||||||
|
if (!UniformAssign(result, attr, uniformProperty) && attr.Required)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
missingRequired.Add(uniformProperty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (missingRequired.Any())
|
||||||
|
{
|
||||||
|
PrintResults(result, uniformProperties);
|
||||||
|
Print("");
|
||||||
|
foreach (var missing in missingRequired)
|
||||||
|
{
|
||||||
|
var attr = missing.GetCustomAttribute<UniformAttribute>()!;
|
||||||
|
var exampleArg = $"--{attr.Arg}=...";
|
||||||
|
var exampleEnvVar = $"{attr.EnvVar}=...";
|
||||||
|
Print($" ! Missing required input. Use argument: '{exampleArg}' or environment variable: '{exampleEnvVar}'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintHelp();
|
||||||
|
throw new ArgumentException("Unable to assemble all required arguments");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (printResult)
|
||||||
|
{
|
||||||
|
PrintResults(result, uniformProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PrintResults(T result, PropertyInfo[] uniformProperties)
|
||||||
|
{
|
||||||
|
Print("");
|
||||||
|
foreach (var p in uniformProperties)
|
||||||
|
{
|
||||||
|
Print($"\t{p.Name} = {p.GetValue(result)}");
|
||||||
|
}
|
||||||
|
Print("");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PrintHelp()
|
||||||
|
{
|
||||||
|
Print("");
|
||||||
|
PrintAligned("CLI option:", "(short)", "Environment variable:", "Description");
|
||||||
|
var attrs = typeof(T).GetProperties().Where(m => m.GetCustomAttributes(typeof(UniformAttribute), false).Length == 1).Select(p => p.GetCustomAttribute<UniformAttribute>()).Where(a => a != null).ToArray();
|
||||||
|
foreach (var attr in attrs)
|
||||||
|
{
|
||||||
|
var a = attr!;
|
||||||
|
var optional = !a.Required ? " *" : "";
|
||||||
|
PrintAligned($"--{a.Arg}=...", $"({a.ArgShort})", a.EnvVar, a.Description + optional);
|
||||||
|
}
|
||||||
|
Print("");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Print(string msg)
|
||||||
|
{
|
||||||
|
Console.WriteLine(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PrintAligned(string cli, string s, string env, string desc)
|
||||||
|
{
|
||||||
|
Console.CursorLeft = cliStart;
|
||||||
|
Console.Write(cli);
|
||||||
|
Console.CursorLeft = shortStart;
|
||||||
|
Console.Write(s);
|
||||||
|
Console.CursorLeft = envStart;
|
||||||
|
Console.Write(env);
|
||||||
|
Console.CursorLeft = descStart;
|
||||||
|
Console.Write(desc + Environment.NewLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
private object GetDefaultValue(Type t)
|
||||||
|
{
|
||||||
|
if (t.IsValueType) return Activator.CreateInstance(t)!;
|
||||||
|
return null!;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool UniformAssign(T result, UniformAttribute attr, PropertyInfo uniformProperty)
|
||||||
|
{
|
||||||
|
if (AssignFromArgsIfAble(result, attr, uniformProperty)) return true;
|
||||||
|
if (AssignFromEnvVarIfAble(result, attr, uniformProperty)) return true;
|
||||||
|
if (AssignFromDefaultsIfAble(result, uniformProperty)) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool AssignFromDefaultsIfAble(T result, PropertyInfo uniformProperty)
|
||||||
|
{
|
||||||
|
var currentValue = uniformProperty.GetValue(result);
|
||||||
|
var isEmptryString = (currentValue as string) == string.Empty;
|
||||||
|
if (currentValue != GetDefaultValue(uniformProperty.PropertyType) && !isEmptryString) return true;
|
||||||
|
|
||||||
|
if (defaultsProvider == null) return false;
|
||||||
|
|
||||||
|
var defaultProperty = defaultsProvider.GetType().GetProperties().SingleOrDefault(p => p.Name == uniformProperty.Name);
|
||||||
|
if (defaultProperty == null) return false;
|
||||||
|
|
||||||
|
var value = defaultProperty.GetValue(defaultsProvider);
|
||||||
|
if (value != null)
|
||||||
|
{
|
||||||
|
return Assign(result, uniformProperty, value);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool AssignFromEnvVarIfAble(T result, UniformAttribute attr, PropertyInfo uniformProperty)
|
||||||
|
{
|
||||||
|
var e = env.GetEnvVarOrDefault(attr.EnvVar, string.Empty);
|
||||||
|
if (!string.IsNullOrEmpty(e))
|
||||||
|
{
|
||||||
|
return Assign(result, uniformProperty, e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool AssignFromArgsIfAble(T result, UniformAttribute attr, PropertyInfo uniformProperty)
|
||||||
|
{
|
||||||
|
var fromArg = GetFromArgs(attr.Arg);
|
||||||
|
if (fromArg != null)
|
||||||
|
{
|
||||||
|
return Assign(result, uniformProperty, fromArg);
|
||||||
|
}
|
||||||
|
var fromShort = GetFromArgs(attr.ArgShort);
|
||||||
|
if (fromShort != null)
|
||||||
|
{
|
||||||
|
return Assign(result, uniformProperty, fromShort);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool Assign(T result, PropertyInfo uniformProperty, object value)
|
||||||
|
{
|
||||||
|
if (uniformProperty.PropertyType == value.GetType())
|
||||||
|
{
|
||||||
|
uniformProperty.SetValue(result, value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (uniformProperty.PropertyType == typeof(string) || uniformProperty.PropertyType == typeof(int))
|
||||||
|
{
|
||||||
|
uniformProperty.SetValue(result, Convert.ChangeType(value, uniformProperty.PropertyType));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (uniformProperty.PropertyType == typeof(int?)) return AssignOptionalInt(result, uniformProperty, value);
|
||||||
|
if (uniformProperty.PropertyType.IsEnum) return AssignEnum(result, uniformProperty, value);
|
||||||
|
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool AssignEnum(T result, PropertyInfo uniformProperty, object value)
|
||||||
|
{
|
||||||
|
var s = value.ToString();
|
||||||
|
if (Enum.TryParse(uniformProperty.PropertyType, s, out var e))
|
||||||
|
{
|
||||||
|
uniformProperty.SetValue(result, e);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool AssignOptionalInt(T result, PropertyInfo uniformProperty, object value)
|
||||||
|
{
|
||||||
|
if (int.TryParse(value.ToString(), out int i))
|
||||||
|
{
|
||||||
|
uniformProperty.SetValue(result, i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string? GetFromArgs(string key)
|
||||||
|
{
|
||||||
|
var argKey = $"--{key}=";
|
||||||
|
var arg = args.FirstOrDefault(a => a.StartsWith(argKey));
|
||||||
|
if (arg != null)
|
||||||
|
{
|
||||||
|
return arg.Substring(argKey.Length);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="I-Env" Version="1.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,29 @@
|
||||||
|
namespace ArgsUniform
|
||||||
|
{
|
||||||
|
public class ExampleUser
|
||||||
|
{
|
||||||
|
public class Args
|
||||||
|
{
|
||||||
|
[Uniform("aaa", "a", "AAA", false, "Sets the AAA!")]
|
||||||
|
public string Aaa { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Uniform("bbb", "b", "BBB", true, "Sets that BBB")]
|
||||||
|
public string Bbb { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DefaultsProvider
|
||||||
|
{
|
||||||
|
public string Aaa { get { return "non-static operation"; } }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Example()
|
||||||
|
{
|
||||||
|
// env var: "AAA=BBB"
|
||||||
|
var args = "--ccc=ddd";
|
||||||
|
|
||||||
|
var uniform = new ArgsUniform<Args>(new DefaultsProvider(), args);
|
||||||
|
|
||||||
|
var aaa = uniform.Parse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
namespace ArgsUniform
|
||||||
|
{
|
||||||
|
public class UniformAttribute : Attribute
|
||||||
|
{
|
||||||
|
public UniformAttribute(string arg, string argShort, string envVar, bool required, string description)
|
||||||
|
{
|
||||||
|
Arg = arg;
|
||||||
|
ArgShort = argShort;
|
||||||
|
EnvVar = envVar;
|
||||||
|
Required = required;
|
||||||
|
Description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Arg { get; }
|
||||||
|
public string ArgShort { get; }
|
||||||
|
public string EnvVar { get; }
|
||||||
|
public bool Required { get; }
|
||||||
|
public string Description { get; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,93 +0,0 @@
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -8,6 +8,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\ArgsUniform\ArgsUniform.csproj" />
|
||||||
<ProjectReference Include="..\DistTestCore\DistTestCore.csproj" />
|
<ProjectReference Include="..\DistTestCore\DistTestCore.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
@ -1,48 +1,47 @@
|
||||||
using DistTestCore;
|
using ArgsUniform;
|
||||||
|
using DistTestCore;
|
||||||
using DistTestCore.Codex;
|
using DistTestCore.Codex;
|
||||||
|
using DistTestCore.Marketplace;
|
||||||
|
|
||||||
namespace CodexNetDeployer
|
namespace CodexNetDeployer
|
||||||
{
|
{
|
||||||
public class Configuration
|
public class Configuration
|
||||||
{
|
{
|
||||||
public Configuration(
|
[Uniform("codex-image", "ci", "CODEXIMAGE", true, "Docker image of Codex.")]
|
||||||
string codexImage,
|
public string CodexImage { get; set; } = string.Empty;
|
||||||
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; }
|
[Uniform("geth-image", "gi", "GETHIMAGE", true, "Docker image of Geth.")]
|
||||||
public string GethImage { get; }
|
public string GethImage { get; set; } = string.Empty;
|
||||||
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()
|
[Uniform("contracts-image", "oi", "CONTRACTSIMAGE", true, "Docker image of Codex Contracts.")]
|
||||||
|
public string ContractsImage { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Uniform("kube-config", "kc", "KUBECONFIG", true, "Path to Kubeconfig file.")]
|
||||||
|
public string KubeConfigFile { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Uniform("kube-namespace", "kn", "KUBENAMESPACE", true, "Kubernetes namespace to be used for deployment.")]
|
||||||
|
public string KubeNamespace { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Uniform("nodes", "n", "NODES", true, "Number of Codex nodes to be created.")]
|
||||||
|
public int? NumberOfCodexNodes { get; set; }
|
||||||
|
|
||||||
|
[Uniform("validators", "v", "VALIDATORS", true, "Number of Codex nodes that will be validating.")]
|
||||||
|
public int? NumberOfValidators { get; set; }
|
||||||
|
|
||||||
|
[Uniform("storage-quota", "s", "STORAGEQUOTA", true, "Storage quota in megabytes used by each Codex node.")]
|
||||||
|
public int? StorageQuota { get; set; }
|
||||||
|
|
||||||
|
[Uniform("log-level", "l", "LOGLEVEL", true, "Log level used by each Codex node. [Trace, Debug*, Info, Warn, Error]")]
|
||||||
|
public CodexLogLevel CodexLogLevel { get; set; }
|
||||||
|
|
||||||
|
public TestRunnerLocation RunnerLocation { get; set; } = TestRunnerLocation.InternalToCluster;
|
||||||
|
|
||||||
|
public class Defaults
|
||||||
{
|
{
|
||||||
ForEachProperty(onString: Print, onInt: Print);
|
public string CodexImage { get; set; } = CodexContainerRecipe.DockerImage;
|
||||||
|
public string GethImage { get; set; } = GethContainerRecipe.DockerImage;
|
||||||
|
public string ContractsImage { get; set; } = CodexContractsContainerRecipe.DockerImage;
|
||||||
|
public CodexLogLevel CodexLogLevel { get; set; } = CodexLogLevel.Debug;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<string> Validate()
|
public List<string> Validate()
|
||||||
|
@ -86,16 +85,5 @@ namespace CodexNetDeployer
|
||||||
errors.Add($"{variable} is must be set.");
|
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>");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using DistTestCore;
|
using DistTestCore;
|
||||||
using DistTestCore.Codex;
|
using DistTestCore.Codex;
|
||||||
using KubernetesWorkflow;
|
using KubernetesWorkflow;
|
||||||
|
using Logging;
|
||||||
|
|
||||||
namespace CodexNetDeployer
|
namespace CodexNetDeployer
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
using CodexNetDeployer;
|
using ArgsUniform;
|
||||||
|
using CodexNetDeployer;
|
||||||
using DistTestCore;
|
using DistTestCore;
|
||||||
using DistTestCore.Codex;
|
|
||||||
using DistTestCore.Marketplace;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Utils;
|
|
||||||
using Configuration = CodexNetDeployer.Configuration;
|
using Configuration = CodexNetDeployer.Configuration;
|
||||||
|
|
||||||
public class Program
|
public class Program
|
||||||
|
@ -11,46 +9,29 @@ public class Program
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
var nl = Environment.NewLine;
|
var nl = Environment.NewLine;
|
||||||
Console.WriteLine("CodexNetDeployer" + nl + nl);
|
Console.WriteLine("CodexNetDeployer" + nl);
|
||||||
|
|
||||||
var argOrVar = new ArgOrVar(args);
|
|
||||||
|
|
||||||
if (args.Any(a => a == "-h" || a == "--help" || a == "-?"))
|
if (args.Any(a => a == "-h" || a == "--help" || a == "-?"))
|
||||||
{
|
{
|
||||||
argOrVar.PrintHelp();
|
PrintHelp();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var location = TestRunnerLocation.InternalToCluster;
|
var uniformArgs = new ArgsUniform<Configuration>(new Configuration.Defaults(), args);
|
||||||
|
var config = uniformArgs.Parse(true);
|
||||||
|
|
||||||
if (args.Any(a => a == "--external"))
|
if (args.Any(a => a == "--external"))
|
||||||
{
|
{
|
||||||
location = TestRunnerLocation.ExternalToCluster;
|
config.RunnerLocation = 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();
|
var errors = config.Validate();
|
||||||
if (errors.Any())
|
if (errors.Any())
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Configuration errors: ({errors.Count})");
|
Console.WriteLine($"Configuration errors: ({errors.Count})");
|
||||||
foreach ( var error in errors ) Console.WriteLine("\t" + error);
|
foreach ( var error in errors ) Console.WriteLine("\t" + error);
|
||||||
Console.WriteLine(nl);
|
Console.WriteLine(nl);
|
||||||
argOrVar.PrintHelp();
|
PrintHelp();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,4 +44,18 @@ public class Program
|
||||||
|
|
||||||
Console.WriteLine("Done!");
|
Console.WriteLine("Done!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static 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);
|
||||||
|
|
||||||
|
var uniformArgs = new ArgsUniform<Configuration>();
|
||||||
|
uniformArgs.PrintHelp();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,91 +1,40 @@
|
||||||
using DistTestCore.Codex;
|
using ArgsUniform;
|
||||||
|
using DistTestCore.Codex;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace ContinuousTests
|
namespace ContinuousTests
|
||||||
{
|
{
|
||||||
public class Configuration
|
public class Configuration
|
||||||
{
|
{
|
||||||
public string LogPath { get; set; } = string.Empty;
|
[Uniform("log-path", "l", "LOGPATH", true, "Path where log files will be written.")]
|
||||||
public string DataPath { get; set; } = string.Empty;
|
public string LogPath { get; set; } = "logs";
|
||||||
|
|
||||||
|
[Uniform("data-path", "d", "DATAPATH", true, "Path where temporary data files will be written.")]
|
||||||
|
public string DataPath { get; set; } = "data";
|
||||||
|
|
||||||
|
[Uniform("codex-deployment", "c", "CODEXDEPLOYMENT", true, "Path to codex-deployment JSON file.")]
|
||||||
|
public string CodexDeploymentJson { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[Uniform("keep", "k", "KEEP", false, "Set to '1' to retain logs of successful tests.")]
|
||||||
|
public bool KeepPassedTestLogs { get; set; } = false;
|
||||||
|
|
||||||
|
[Uniform("kube-config", "kc", "KUBECONFIG", true, "Path to Kubeconfig file.")]
|
||||||
|
public string KubeConfigFile { get; set; } = string.Empty;
|
||||||
|
|
||||||
public CodexDeployment CodexDeployment { get; set; } = null!;
|
public CodexDeployment CodexDeployment { get; set; } = null!;
|
||||||
public bool KeepPassedTestLogs { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ConfigLoader
|
public class ConfigLoader
|
||||||
{
|
{
|
||||||
private const string filename = "config.json";
|
public Configuration Load(string[] args)
|
||||||
|
{
|
||||||
|
var uniformArgs = new ArgsUniform<Configuration>(args);
|
||||||
|
|
||||||
public Configuration Load()
|
var result = uniformArgs.Parse();
|
||||||
{
|
|
||||||
var config = Read();
|
|
||||||
|
|
||||||
Validate(config);
|
result.CodexDeployment = ParseCodexDeploymentJson(result.CodexDeploymentJson);
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Configuration Read()
|
return result;
|
||||||
{
|
|
||||||
if (File.Exists(filename))
|
|
||||||
{
|
|
||||||
var lines = File.ReadAllText(filename);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var result = JsonConvert.DeserializeObject<Configuration>(lines);
|
|
||||||
if (result != null) return result;
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
|
|
||||||
var logPath = Environment.GetEnvironmentVariable("LOGPATH");
|
|
||||||
var dataPath = Environment.GetEnvironmentVariable("DATAPATH");
|
|
||||||
var codexDeploymentJson = Environment.GetEnvironmentVariable("CODEXDEPLOYMENT");
|
|
||||||
var keep = Environment.GetEnvironmentVariable("KEEPPASSEDTESTLOGS");
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(logPath) &&
|
|
||||||
!string.IsNullOrEmpty(dataPath) &&
|
|
||||||
!string.IsNullOrEmpty(codexDeploymentJson))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return new Configuration
|
|
||||||
{
|
|
||||||
LogPath = logPath,
|
|
||||||
DataPath = dataPath,
|
|
||||||
CodexDeployment = ParseCodexDeploymentJson(codexDeploymentJson),
|
|
||||||
KeepPassedTestLogs = keep == "1"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Exception: " + ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var nl = Environment.NewLine;
|
|
||||||
throw new Exception($"Unable to load configuration from '{filename}', and " +
|
|
||||||
"unable to load configuration from environment variables. " + nl +
|
|
||||||
"'LOGPATH' = Path where log files will be saved." + nl +
|
|
||||||
"'DATAPATH' = Path where temporary data files will be saved." + nl +
|
|
||||||
"'CODEXDEPLOYMENT' = Path to codex-deployment JSON file." + nl +
|
|
||||||
nl);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Validate(Configuration configuration)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(configuration.LogPath))
|
|
||||||
{
|
|
||||||
throw new Exception($"Invalid LogPath set: '{configuration.LogPath}'");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(configuration.DataPath))
|
|
||||||
{
|
|
||||||
throw new Exception($"Invalid DataPath set: '{configuration.DataPath}'");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configuration.CodexDeployment == null || !configuration.CodexDeployment.CodexContainers.Any())
|
|
||||||
{
|
|
||||||
throw new Exception("No Codex deployment found.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private CodexDeployment ParseCodexDeploymentJson(string filename)
|
private CodexDeployment ParseCodexDeploymentJson(string filename)
|
||||||
|
|
|
@ -15,21 +15,24 @@ namespace ContinuousTests
|
||||||
protected const int MinuteOne = 60;
|
protected const int MinuteOne = 60;
|
||||||
protected const int MinuteFive = MinuteOne * 5;
|
protected const int MinuteFive = MinuteOne * 5;
|
||||||
protected const int HourOne = MinuteOne * 60;
|
protected const int HourOne = MinuteOne * 60;
|
||||||
|
protected const int HourThree = HourOne * 3;
|
||||||
protected const int DayOne = HourOne * 24;
|
protected const int DayOne = HourOne * 24;
|
||||||
protected const int DayThree = DayOne * 3;
|
protected const int DayThree = DayOne * 3;
|
||||||
|
|
||||||
private const string UploadFailedMessage = "Unable to store block";
|
private const string UploadFailedMessage = "Unable to store block";
|
||||||
|
|
||||||
public void Initialize(CodexNode[] nodes, BaseLog log, FileManager fileManager)
|
public void Initialize(CodexNode[] nodes, BaseLog log, FileManager fileManager, Configuration configuration)
|
||||||
{
|
{
|
||||||
Nodes = nodes;
|
Nodes = nodes;
|
||||||
Log = log;
|
Log = log;
|
||||||
FileManager = fileManager;
|
FileManager = fileManager;
|
||||||
|
Configuration = configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CodexNode[] Nodes { get; private set; } = null!;
|
public CodexNode[] Nodes { get; private set; } = null!;
|
||||||
public BaseLog Log { get; private set; } = null!;
|
public BaseLog Log { get; private set; } = null!;
|
||||||
public IFileManager FileManager { get; private set; } = null!;
|
public IFileManager FileManager { get; private set; } = null!;
|
||||||
|
public Configuration Configuration { get; private set; } = null!;
|
||||||
public virtual ITimeSet TimeSet { get { return new DefaultTimeSet(); } }
|
public virtual ITimeSet TimeSet { get { return new DefaultTimeSet(); } }
|
||||||
|
|
||||||
public abstract int RequiredNumberOfNodes { get; }
|
public abstract int RequiredNumberOfNodes { get; }
|
||||||
|
|
|
@ -9,9 +9,9 @@ namespace ContinuousTests
|
||||||
private readonly Configuration config;
|
private readonly Configuration config;
|
||||||
private readonly StartupChecker startupChecker;
|
private readonly StartupChecker startupChecker;
|
||||||
|
|
||||||
public ContinuousTestRunner()
|
public ContinuousTestRunner(string[] args)
|
||||||
{
|
{
|
||||||
config = configLoader.Load();
|
config = configLoader.Load(args);
|
||||||
startupChecker = new StartupChecker(config);
|
startupChecker = new StartupChecker(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\ArgsUniform\ArgsUniform.csproj" />
|
||||||
<ProjectReference Include="..\DistTestCore\DistTestCore.csproj" />
|
<ProjectReference Include="..\DistTestCore\DistTestCore.csproj" />
|
||||||
<ProjectReference Include="..\Logging\Logging.csproj" />
|
<ProjectReference Include="..\Logging\Logging.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -6,7 +6,7 @@ public class Program
|
||||||
{
|
{
|
||||||
Console.WriteLine("Codex Continous-Test-Runner.");
|
Console.WriteLine("Codex Continous-Test-Runner.");
|
||||||
Console.WriteLine("Running...");
|
Console.WriteLine("Running...");
|
||||||
var runner = new ContinuousTestRunner();
|
var runner = new ContinuousTestRunner(args);
|
||||||
runner.Run();
|
runner.Run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,12 +111,12 @@ namespace ContinuousTests
|
||||||
private void InitializeTest(string name)
|
private void InitializeTest(string name)
|
||||||
{
|
{
|
||||||
Log($" > Running TestMoment '{name}'");
|
Log($" > Running TestMoment '{name}'");
|
||||||
handle.Test.Initialize(nodes, fixtureLog, fileManager);
|
handle.Test.Initialize(nodes, fixtureLog, fileManager, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DecommissionTest()
|
private void DecommissionTest()
|
||||||
{
|
{
|
||||||
handle.Test.Initialize(null!, null!, null!);
|
handle.Test.Initialize(null!, null!, null!, null!);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Log(string msg)
|
private void Log(string msg)
|
||||||
|
|
|
@ -1,25 +1,130 @@
|
||||||
using DistTestCore.Codex;
|
using DistTestCore;
|
||||||
|
using DistTestCore.Codex;
|
||||||
|
using DistTestCore.Marketplace;
|
||||||
|
using KubernetesWorkflow;
|
||||||
|
using Logging;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace ContinuousTests.Tests
|
namespace ContinuousTests.Tests
|
||||||
{
|
{
|
||||||
//public class MarketplaceTest : ContinuousTest
|
public class MarketplaceTest : ContinuousTest
|
||||||
//{
|
{
|
||||||
// public override int RequiredNumberOfNodes => 1;
|
public override int RequiredNumberOfNodes => 1;
|
||||||
// public override TimeSpan RunTestEvery => TimeSpan.FromDays(1);
|
public override TimeSpan RunTestEvery => TimeSpan.FromDays(4);
|
||||||
// public override TestFailMode TestFailMode => TestFailMode.AlwaysRunAllMoments;
|
public override TestFailMode TestFailMode => TestFailMode.AlwaysRunAllMoments;
|
||||||
|
|
||||||
// [TestMoment(t: Zero)]
|
public const int EthereumAccountIndex = 200; // TODO: Check against all other account indices of all other tests.
|
||||||
// public void NodePostsStorageRequest()
|
|
||||||
// {
|
|
||||||
// //var c = new KubernetesWorkflow.WorkflowCreator(Log, new KubernetesWorkflow.Configuration());
|
|
||||||
// //var flow = c.CreateWorkflow();
|
|
||||||
// //var rc = flow.Start(10, KubernetesWorkflow.Location.Unspecified, new CodexContainerRecipe(), new KubernetesWorkflow.StartupConfig());
|
|
||||||
// }
|
|
||||||
|
|
||||||
// [TestMoment(t: DayThree)]
|
private const string MarketplaceTestNamespace = "codex-continuous-marketplace";
|
||||||
// public void NodeDownloadsStorageRequestData()
|
|
||||||
// {
|
|
||||||
|
|
||||||
// }
|
private readonly ByteSize fileSize = 100.MB();
|
||||||
//}
|
private readonly TestToken pricePerBytePerSecond = 1.TestTokens();
|
||||||
|
|
||||||
|
private TestFile file = null!;
|
||||||
|
private ContentId? cid;
|
||||||
|
private TestToken startingBalance = null!;
|
||||||
|
private string purchaseId = string.Empty;
|
||||||
|
|
||||||
|
[TestMoment(t: Zero)]
|
||||||
|
public void NodePostsStorageRequest()
|
||||||
|
{
|
||||||
|
var contractDuration = TimeSpan.FromDays(3) + TimeSpan.FromHours(1);
|
||||||
|
decimal totalDurationSeconds = Convert.ToDecimal(contractDuration.TotalSeconds);
|
||||||
|
var expectedTotalCost = pricePerBytePerSecond.Amount * totalDurationSeconds;
|
||||||
|
|
||||||
|
file = FileManager.GenerateTestFile(fileSize);
|
||||||
|
|
||||||
|
var (workflowCreator, lifecycle) = CreateFacilities();
|
||||||
|
var flow = workflowCreator.CreateWorkflow();
|
||||||
|
var startupConfig = new StartupConfig();
|
||||||
|
var codexStartConfig = new CodexStartupConfig(CodexLogLevel.Debug);
|
||||||
|
codexStartConfig.MarketplaceConfig = new MarketplaceInitialConfig(0.Eth(), 0.TestTokens(), false);
|
||||||
|
codexStartConfig.MarketplaceConfig.AccountIndexOverride = EthereumAccountIndex;
|
||||||
|
startupConfig.Add(codexStartConfig);
|
||||||
|
startupConfig.Add(Configuration.CodexDeployment.GethStartResult);
|
||||||
|
var rc = flow.Start(1, Location.Unspecified, new CodexContainerRecipe(), startupConfig);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var account = Configuration.CodexDeployment.GethStartResult.MarketplaceNetwork.Bootstrap.AllAccounts.Accounts[EthereumAccountIndex];
|
||||||
|
var tokenAddress = Configuration.CodexDeployment.GethStartResult.MarketplaceNetwork.Marketplace.TokenAddress;
|
||||||
|
|
||||||
|
var interaction = Configuration.CodexDeployment.GethStartResult.MarketplaceNetwork.Bootstrap.StartInteraction(lifecycle);
|
||||||
|
interaction.MintTestTokens(new[] { account.Account }, expectedTotalCost, tokenAddress);
|
||||||
|
|
||||||
|
var container = rc.Containers[0];
|
||||||
|
var marketplaceNetwork = Configuration.CodexDeployment.GethStartResult.MarketplaceNetwork;
|
||||||
|
var codexAccess = new CodexAccess(lifecycle, container);
|
||||||
|
var marketAccess = new MarketplaceAccess(lifecycle, marketplaceNetwork, account, codexAccess);
|
||||||
|
|
||||||
|
cid = UploadFile(codexAccess.Node, file);
|
||||||
|
Assert.That(cid, Is.Not.Null);
|
||||||
|
|
||||||
|
startingBalance = marketAccess.GetBalance();
|
||||||
|
|
||||||
|
purchaseId = marketAccess.RequestStorage(
|
||||||
|
contentId: cid!,
|
||||||
|
pricePerBytePerSecond: pricePerBytePerSecond,
|
||||||
|
requiredCollateral: 100.TestTokens(),
|
||||||
|
minRequiredNumberOfNodes: 3,
|
||||||
|
proofProbability: 10,
|
||||||
|
duration: contractDuration);
|
||||||
|
|
||||||
|
Assert.That(!string.IsNullOrEmpty(purchaseId));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
flow.Stop(rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMoment(t: DayThree)]
|
||||||
|
public void StoredDataIsAvailableAfterThreeDays()
|
||||||
|
{
|
||||||
|
var (workflowCreator, lifecycle) = CreateFacilities();
|
||||||
|
var flow = workflowCreator.CreateWorkflow();
|
||||||
|
var startupConfig = new StartupConfig();
|
||||||
|
var codexStartConfig = new CodexStartupConfig(CodexLogLevel.Debug);
|
||||||
|
startupConfig.Add(codexStartConfig);
|
||||||
|
var rc = flow.Start(1, Location.Unspecified, new CodexContainerRecipe(), startupConfig);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var container = rc.Containers[0];
|
||||||
|
var codexAccess = new CodexAccess(lifecycle, container);
|
||||||
|
|
||||||
|
var result = DownloadContent(codexAccess.Node, cid!);
|
||||||
|
|
||||||
|
file.AssertIsEqual(result);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
flow.Stop(rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private (WorkflowCreator, TestLifecycle) CreateFacilities()
|
||||||
|
{
|
||||||
|
var lifecycleConfig = new DistTestCore.Configuration
|
||||||
|
(
|
||||||
|
kubeConfigFile: Configuration.KubeConfigFile,
|
||||||
|
logPath: "null",
|
||||||
|
logDebug: false,
|
||||||
|
dataFilesPath: "notUsed",
|
||||||
|
codexLogLevel: CodexLogLevel.Debug,
|
||||||
|
runnerLocation: TestRunnerLocation.InternalToCluster
|
||||||
|
);
|
||||||
|
|
||||||
|
var kubeConfig = new KubernetesWorkflow.Configuration(
|
||||||
|
k8sNamespacePrefix: MarketplaceTestNamespace,
|
||||||
|
kubeConfigFile: Configuration.KubeConfigFile,
|
||||||
|
operationTimeout: TimeSet.K8sOperationTimeout(),
|
||||||
|
retryDelay: TimeSet.WaitForK8sServiceDelay());
|
||||||
|
|
||||||
|
var workflowCreator = new WorkflowCreator(Log, kubeConfig, testNamespacePostfix: string.Empty);
|
||||||
|
var lifecycle = new TestLifecycle(new NullLog(), lifecycleConfig, TimeSet, workflowCreator);
|
||||||
|
|
||||||
|
return (workflowCreator, lifecycle);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
using Logging;
|
namespace Logging
|
||||||
|
|
||||||
namespace CodexNetDeployer
|
|
||||||
{
|
{
|
||||||
public class NullLog : TestLog
|
public class NullLog : TestLog
|
||||||
{
|
{
|
||||||
|
@ -15,12 +13,10 @@ namespace CodexNetDeployer
|
||||||
|
|
||||||
public override void Log(string message)
|
public override void Log(string message)
|
||||||
{
|
{
|
||||||
//Console.WriteLine(message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Debug(string message = "", int skipFrames = 0)
|
public override void Debug(string message = "", int skipFrames = 0)
|
||||||
{
|
{
|
||||||
//Console.WriteLine(message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Error(string message)
|
public override void Error(string message)
|
|
@ -19,7 +19,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NethereumWorkflow", "Nether
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "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
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodexNetDeployer", "CodexNetDeployer\CodexNetDeployer.csproj", "{871CAF12-14BE-4509-BC6E-20FDF0B1083A}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CodexNetDeployer", "CodexNetDeployer\CodexNetDeployer.csproj", "{871CAF12-14BE-4509-BC6E-20FDF0B1083A}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ArgsUniform", "ArgsUniform\ArgsUniform.csproj", "{634324B1-E359-42B4-A269-BDC429936B3C}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
@ -63,6 +65,10 @@ Global
|
||||||
{871CAF12-14BE-4509-BC6E-20FDF0B1083A}.Debug|Any CPU.Build.0 = 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.ActiveCfg = Release|Any CPU
|
||||||
{871CAF12-14BE-4509-BC6E-20FDF0B1083A}.Release|Any CPU.Build.0 = Release|Any CPU
|
{871CAF12-14BE-4509-BC6E-20FDF0B1083A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{634324B1-E359-42B4-A269-BDC429936B3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{634324B1-E359-42B4-A269-BDC429936B3C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{634324B1-E359-42B4-A269-BDC429936B3C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{634324B1-E359-42B4-A269-BDC429936B3C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
Loading…
Reference in New Issue