diff --git a/CodexNetDownloader/CodexNetDownloader.csproj b/CodexNetDownloader/CodexNetDownloader.csproj new file mode 100644 index 0000000..0df1223 --- /dev/null +++ b/CodexNetDownloader/CodexNetDownloader.csproj @@ -0,0 +1,16 @@ + + + + Exe + net7.0 + enable + enable + + + + + + + + + diff --git a/CodexNetDownloader/Configuration.cs b/CodexNetDownloader/Configuration.cs new file mode 100644 index 0000000..008dfbf --- /dev/null +++ b/CodexNetDownloader/Configuration.cs @@ -0,0 +1,22 @@ +using ArgsUniform; +using DistTestCore; +using DistTestCore.Codex; + +namespace CodexNetDownloader +{ + public class Configuration + { + [Uniform("output-path", "o", "OUTPUT", true, "Path where files will be written.")] + public string OutputPath { get; set; } = "output"; + + [Uniform("codex-deployment", "c", "CODEXDEPLOYMENT", true, "Path to codex-deployment JSON file.")] + public string CodexDeploymentJson { get; set; } = string.Empty; + + [Uniform("kube-config", "kc", "KUBECONFIG", true, "Path to Kubeconfig file. Use 'null' (default) to use local cluster.")] + public string KubeConfigFile { get; set; } = "null"; + + public CodexDeployment CodexDeployment { get; set; } = null!; + + public TestRunnerLocation RunnerLocation { get; set; } = TestRunnerLocation.InternalToCluster; + } +} diff --git a/CodexNetDownloader/Program.cs b/CodexNetDownloader/Program.cs new file mode 100644 index 0000000..d17d76a --- /dev/null +++ b/CodexNetDownloader/Program.cs @@ -0,0 +1,62 @@ +using ArgsUniform; +using ContinuousTests; +using DistTestCore; +using DistTestCore.Codex; +using Logging; +using Newtonsoft.Json; + +public class Program +{ + public static void Main(string[] args) + { + var nl = Environment.NewLine; + Console.WriteLine("CodexNetDownloader" + nl); + + if (args.Any(a => a == "-h" || a == "--help" || a == "-?")) + { + PrintHelp(); + return; + } + + var uniformArgs = new ArgsUniform(args); + var config = uniformArgs.Parse(true); + + if (args.Any(a => a == "--external")) + { + config.RunnerLocation = TestRunnerLocation.ExternalToCluster; + } + + config.CodexDeployment = ParseCodexDeploymentJson(config.CodexDeploymentJson); + + if (!Directory.Exists(config.OutputPath)) Directory.CreateDirectory(config.OutputPath); + + var k8sFactory = new K8sFactory(); + var (_, lifecycle) = k8sFactory.CreateFacilities(config.KubeConfigFile, config.OutputPath, "dataPath", config.CodexDeployment.Metadata.KubeNamespace, new DefaultTimeSet(), new NullLog()); + + foreach (var container in config.CodexDeployment.CodexContainers) + { + lifecycle.DownloadLog(container); + } + + Console.WriteLine("Done!"); + } + + private static CodexDeployment ParseCodexDeploymentJson(string filename) + { + var d = JsonConvert.DeserializeObject(File.ReadAllText(filename))!; + if (d == null) throw new Exception("Unable to parse " + filename); + return d; + } + + private static void PrintHelp() + { + var nl = Environment.NewLine; + Console.WriteLine("CodexNetDownloader lets you download all container logs given a codex-deployment.json file." + nl); + + Console.WriteLine("CodexNetDownloader assumes you are running this tool from *inside* the Kubernetes cluster. " + + "If you are not running this from a container inside the cluster, add the argument '--external'." + nl); + + var uniformArgs = new ArgsUniform(); + uniformArgs.PrintHelp(); + } +} diff --git a/ContinuousTests/ContinuousTestRunner.cs b/ContinuousTests/ContinuousTestRunner.cs index a0f15ab..e465e28 100644 --- a/ContinuousTests/ContinuousTestRunner.cs +++ b/ContinuousTests/ContinuousTestRunner.cs @@ -58,7 +58,7 @@ namespace ContinuousTests if (string.IsNullOrEmpty(test.CustomK8sNamespace)) return; log.Log($"Clearing namespace '{test.CustomK8sNamespace}'..."); - var (workflowCreator, _) = k8SFactory.CreateFacilities(config, test.CustomK8sNamespace, new DefaultTimeSet(), log); + var (workflowCreator, _) = k8SFactory.CreateFacilities(config.KubeConfigFile, config.LogPath, config.DataPath, test.CustomK8sNamespace, new DefaultTimeSet(), log); workflowCreator.CreateWorkflow().DeleteTestResources(); } } diff --git a/ContinuousTests/K8sFactory.cs b/ContinuousTests/K8sFactory.cs index 040a4a3..221e112 100644 --- a/ContinuousTests/K8sFactory.cs +++ b/ContinuousTests/K8sFactory.cs @@ -7,22 +7,22 @@ namespace ContinuousTests { public class K8sFactory { - public (WorkflowCreator, TestLifecycle) CreateFacilities(Configuration config, string customNamespace, ITimeSet timeSet, BaseLog log) + public (WorkflowCreator, TestLifecycle) CreateFacilities(string kubeConfigFile, string logPath, string dataFilePath, string customNamespace, ITimeSet timeSet, BaseLog log) { - var kubeConfig = GetKubeConfig(config.KubeConfigFile); + var kubeConfig = GetKubeConfig(kubeConfigFile); var lifecycleConfig = new DistTestCore.Configuration ( kubeConfigFile: kubeConfig, - logPath: "null", + logPath: logPath, logDebug: false, - dataFilesPath: config.LogPath, + dataFilesPath: dataFilePath, codexLogLevel: CodexLogLevel.Debug, runnerLocation: TestRunnerLocation.ExternalToCluster ); var kubeFlowConfig = new KubernetesWorkflow.Configuration( k8sNamespacePrefix: customNamespace, - kubeConfigFile: kubeConfig, + kubeConfigFile: kubeConfig, operationTimeout: timeSet.K8sOperationTimeout(), retryDelay: timeSet.WaitForK8sServiceDelay()); diff --git a/ContinuousTests/NodeRunner.cs b/ContinuousTests/NodeRunner.cs index 1a36d62..be6d416 100644 --- a/ContinuousTests/NodeRunner.cs +++ b/ContinuousTests/NodeRunner.cs @@ -81,7 +81,7 @@ namespace ContinuousTests private (WorkflowCreator, TestLifecycle) CreateFacilities() { - return k8SFactory.CreateFacilities(config, customNamespace, timeSet, log); + return k8SFactory.CreateFacilities(config.KubeConfigFile, config.LogPath, config.DataPath, customNamespace, timeSet, log); } } } diff --git a/cs-codex-dist-testing.sln b/cs-codex-dist-testing.sln index d72ecae..8e696b3 100644 --- a/cs-codex-dist-testing.sln +++ b/cs-codex-dist-testing.sln @@ -21,7 +21,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ContinuousTests", "Continuo EndProject 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}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ArgsUniform", "ArgsUniform\ArgsUniform.csproj", "{634324B1-E359-42B4-A269-BDC429936B3C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodexNetDownloader", "CodexNetDownloader\CodexNetDownloader.csproj", "{6CDF35D2-906A-4285-8E1F-4794588B948B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -69,6 +71,10 @@ Global {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 + {6CDF35D2-906A-4285-8E1F-4794588B948B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6CDF35D2-906A-4285-8E1F-4794588B948B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6CDF35D2-906A-4285-8E1F-4794588B948B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6CDF35D2-906A-4285-8E1F-4794588B948B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE