diff --git a/CodexNetDeployer/ArgOrVar.cs b/CodexNetDeployer/ArgOrVar.cs
new file mode 100644
index 0000000..df70171
--- /dev/null
+++ b/CodexNetDeployer/ArgOrVar.cs
@@ -0,0 +1,89 @@
+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 StorageQuota = new ArgVar("storage-quota", "STORAGEQUOTA", "Storage quota in megabytes used by each Codex node.");
+
+ 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.Write("\t[ CLI argument ] or [ Environment variable ]");
+ Console.CursorLeft = 70;
+ Console.Write("(Description)" + nl);
+ var fields = GetType().GetFields();// System.Reflection.BindingFlags.Public & System.Reflection.BindingFlags.Static);
+ 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);
+ }
+ }
+}
diff --git a/CodexNetDeployer/CodexNetDeployer.csproj b/CodexNetDeployer/CodexNetDeployer.csproj
index f02677b..80f6f4c 100644
--- a/CodexNetDeployer/CodexNetDeployer.csproj
+++ b/CodexNetDeployer/CodexNetDeployer.csproj
@@ -7,4 +7,8 @@
enable
+
+
+
+
diff --git a/CodexNetDeployer/Configuration.cs b/CodexNetDeployer/Configuration.cs
new file mode 100644
index 0000000..3abb7a4
--- /dev/null
+++ b/CodexNetDeployer/Configuration.cs
@@ -0,0 +1,84 @@
+namespace CodexNetDeployer
+{
+ public class Configuration
+ {
+ public Configuration(
+ string codexImage,
+ string gethImage,
+ string contractsImage,
+ string kubeConfigFile,
+ string kubeNamespace,
+ int? numberOfCodexNodes,
+ int? storageQuota)
+ {
+ CodexImage = codexImage;
+ GethImage = gethImage;
+ ContractsImage = contractsImage;
+ KubeConfigFile = kubeConfigFile;
+ KubeNamespace = kubeNamespace;
+ NumberOfCodexNodes = numberOfCodexNodes;
+ StorageQuota = storageQuota;
+ }
+
+ 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? StorageQuota { get; }
+
+ public void PrintConfig()
+ {
+ ForEachProperty(onString: Print, onInt: Print);
+ }
+
+ public List Validate()
+ {
+ var errors = new List();
+
+ ForEachProperty(
+ onString: (n, v) => StringIsSet(n, v, errors),
+ onInt: (n, v) => IntIsOverZero(n, v, errors));
+
+ return errors;
+ }
+
+ private void ForEachProperty(Action onString, Action 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 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 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, "");
+ }
+ }
+}
diff --git a/CodexNetDeployer/Program.cs b/CodexNetDeployer/Program.cs
index a08476f..64a445f 100644
--- a/CodexNetDeployer/Program.cs
+++ b/CodexNetDeployer/Program.cs
@@ -1,7 +1,46 @@
-public class Program
+using CodexNetDeployer;
+using DistTestCore.Codex;
+using DistTestCore.Marketplace;
+
+public class Program
{
public static void Main(string[] args)
{
- Console.WriteLine("Hello, World!");
+ 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 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),
+ storageQuota: argOrVar.GetInt(ArgOrVar.StorageQuota)
+ );
+
+ 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;
+ }
+
+
}
}