diff --git a/CodexNetDownloader/Configuration.cs b/CodexNetDownloader/Configuration.cs index 008dfbf..feecf24 100644 --- a/CodexNetDownloader/Configuration.cs +++ b/CodexNetDownloader/Configuration.cs @@ -15,6 +15,9 @@ namespace CodexNetDownloader [Uniform("kube-config", "kc", "KUBECONFIG", true, "Path to Kubeconfig file. Use 'null' (default) to use local cluster.")] public string KubeConfigFile { get; set; } = "null"; + [Uniform("continuous", "c", "CONTINUOUS", false, "If true, will continuously download and append log files.")] + public bool Continuous { get; set; } = false; + public CodexDeployment CodexDeployment { get; set; } = null!; public TestRunnerLocation RunnerLocation { get; set; } = TestRunnerLocation.InternalToCluster; diff --git a/CodexNetDownloader/ContinuousLogDownloader.cs b/CodexNetDownloader/ContinuousLogDownloader.cs new file mode 100644 index 0000000..074e197 --- /dev/null +++ b/CodexNetDownloader/ContinuousLogDownloader.cs @@ -0,0 +1,84 @@ +using DistTestCore; +using KubernetesWorkflow; + +namespace CodexNetDownloader +{ + public class ContinuousLogDownloader + { + private readonly TestLifecycle lifecycle; + private readonly Configuration config; + + public ContinuousLogDownloader(TestLifecycle lifecycle, Configuration config) + { + this.lifecycle = lifecycle; + this.config = config; + } + + public void Run() + { + while (true) + { + UpdateLogs(); + + Thread.Sleep(TimeSpan.FromSeconds(30)); + } + } + + private void UpdateLogs() + { + Console.WriteLine("Updating logs..."); + foreach (var container in config.CodexDeployment.CodexContainers) + { + UpdateLog(container); + } + } + + private void UpdateLog(RunningContainer container) + { + var filepath = Path.Combine(config.OutputPath, GetLogName(container)); + if (!File.Exists(filepath)) File.WriteAllLines(filepath, new[] { "" }); + + var appender = new LogAppender(filepath); + + lifecycle.CodexStarter.DownloadLog(container, appender); + } + + private static string GetLogName(RunningContainer container) + { + return container.Name + .Replace("<","") + .Replace(">", "") + + ".log"; + } + } + + public class LogAppender : ILogHandler + { + private readonly string filename; + + public LogAppender(string filename) + { + this.filename = filename; + } + + public void Log(Stream log) + { + using var reader = new StreamReader(log); + var currentLines = File.ReadAllLines(filename); + var line = reader.ReadLine(); + while (line != null) + { + AppendLineIfNew(line, currentLines); + line = reader.ReadLine(); + } + } + + private void AppendLineIfNew(string line, string[] currentLines) + { + if (!currentLines.Contains(line)) + { + File.AppendAllLines(filename, new[] { line }); + } + } + } +} diff --git a/CodexNetDownloader/Program.cs b/CodexNetDownloader/Program.cs index f52a1d2..9a631cc 100644 --- a/CodexNetDownloader/Program.cs +++ b/CodexNetDownloader/Program.cs @@ -1,4 +1,5 @@ using ArgsUniform; +using CodexNetDownloader; using ContinuousTests; using DistTestCore; using DistTestCore.Codex; @@ -27,12 +28,20 @@ public class Program var k8sFactory = new K8sFactory(); var (_, lifecycle) = k8sFactory.CreateFacilities(config.KubeConfigFile, config.OutputPath, "dataPath", config.CodexDeployment.Metadata.KubeNamespace, new DefaultTimeSet(), new NullLog(), config.RunnerLocation); - foreach (var container in config.CodexDeployment.CodexContainers) + if (config.Continuous) { - lifecycle.DownloadLog(container); + var dl = new ContinuousLogDownloader(lifecycle, config); + dl.Run(); } + else + { + foreach (var container in config.CodexDeployment.CodexContainers) + { + lifecycle.DownloadLog(container); + } - Console.WriteLine("Done!"); + Console.WriteLine("Done!"); + } } private static CodexDeployment ParseCodexDeploymentJson(string filename)