From 2c549c5410629cf179544679f76694957c45a4cd Mon Sep 17 00:00:00 2001 From: ThatBen Date: Mon, 27 Jan 2025 10:22:34 +0100 Subject: [PATCH] extracts codex wrapper --- .../CodexPlugin/BinaryCodexStarter.cs | 12 ++ .../CodexContainerProcessControl.cs | 70 +++++++++ ProjectPlugins/CodexPlugin/CodexPlugin.cs | 13 +- ProjectPlugins/CodexPlugin/CodexWrapper.cs | 80 ++++++++++ .../CodexPlugin/ContainerCodexStarter.cs | 139 +----------------- ProjectPlugins/CodexPlugin/ICodexStarter.cs | 5 +- .../CodexPlugin/ProcessControlMap.cs | 29 ++++ 7 files changed, 205 insertions(+), 143 deletions(-) create mode 100644 ProjectPlugins/CodexPlugin/BinaryCodexStarter.cs create mode 100644 ProjectPlugins/CodexPlugin/CodexContainerProcessControl.cs create mode 100644 ProjectPlugins/CodexPlugin/CodexWrapper.cs create mode 100644 ProjectPlugins/CodexPlugin/ProcessControlMap.cs diff --git a/ProjectPlugins/CodexPlugin/BinaryCodexStarter.cs b/ProjectPlugins/CodexPlugin/BinaryCodexStarter.cs new file mode 100644 index 00000000..4353c818 --- /dev/null +++ b/ProjectPlugins/CodexPlugin/BinaryCodexStarter.cs @@ -0,0 +1,12 @@ +using CodexClient; + +namespace CodexPlugin +{ + public class BinaryCodexStarter : ICodexStarter + { + public ICodexInstance[] BringOnline(CodexSetup codexSetup) + { + throw new NotImplementedException(); + } + } +} diff --git a/ProjectPlugins/CodexPlugin/CodexContainerProcessControl.cs b/ProjectPlugins/CodexPlugin/CodexContainerProcessControl.cs new file mode 100644 index 00000000..a6afc2fe --- /dev/null +++ b/ProjectPlugins/CodexPlugin/CodexContainerProcessControl.cs @@ -0,0 +1,70 @@ +using CodexClient; +using Core; +using KubernetesWorkflow; +using KubernetesWorkflow.Types; +using Logging; + +namespace CodexPlugin +{ + public class CodexContainerProcessControl : IProcessControl + { + private readonly IPluginTools tools; + private readonly RunningPod pod; + private readonly Action onStop; + private readonly ContainerCrashWatcher crashWatcher; + + public CodexContainerProcessControl(IPluginTools tools, RunningPod pod, Action onStop) + { + this.tools = tools; + this.pod = pod; + this.onStop = onStop; + + crashWatcher = tools.CreateWorkflow().CreateCrashWatcher(pod.Containers.Single()); + crashWatcher.Start(); + } + + public void Stop(bool waitTillStopped) + { + Log($"Stopping node..."); + var workflow = tools.CreateWorkflow(); + workflow.Stop(pod, waitTillStopped); + crashWatcher.Stop(); + onStop(); + Log("Stopped."); + } + + public IDownloadedLog DownloadLog(LogFile file) + { + var workflow = tools.CreateWorkflow(); + return workflow.DownloadContainerLog(pod.Containers.Single()); + } + + public void DeleteDataDirFolder() + { + var container = pod.Containers.Single(); + + try + { + var dataDirVar = container.Recipe.EnvVars.Single(e => e.Name == "CODEX_DATA_DIR"); + var dataDir = dataDirVar.Value; + var workflow = tools.CreateWorkflow(); + workflow.ExecuteCommand(container, "rm", "-Rfv", $"/codex/{dataDir}/repo"); + Log("Deleted repo folder."); + } + catch (Exception e) + { + Log("Unable to delete repo folder: " + e); + } + } + + public bool HasCrashed() + { + return crashWatcher.HasCrashed(); + } + + private void Log(string message) + { + tools.GetLog().Log(message); + } + } +} diff --git a/ProjectPlugins/CodexPlugin/CodexPlugin.cs b/ProjectPlugins/CodexPlugin/CodexPlugin.cs index 5c33754e..e6c56f7c 100644 --- a/ProjectPlugins/CodexPlugin/CodexPlugin.cs +++ b/ProjectPlugins/CodexPlugin/CodexPlugin.cs @@ -10,10 +10,13 @@ namespace CodexPlugin private readonly IPluginTools tools; private readonly CodexLogLevel defaultLogLevel = CodexLogLevel.Trace; private readonly CodexHooksFactory hooksFactory = new CodexHooksFactory(); + private readonly ProcessControlMap processControlMap = new ProcessControlMap(); + private readonly CodexWrapper codexWrapper; public CodexPlugin(IPluginTools tools) { - codexStarter = new ContainerCodexStarter(tools, hooksFactory); + codexStarter = new ContainerCodexStarter(tools, processControlMap); + codexWrapper = new CodexWrapper(tools, processControlMap, hooksFactory); this.tools = tools; } @@ -21,13 +24,13 @@ namespace CodexPlugin public void Announce() { - Log($"Loaded with Codex ID: '{codexStarter.GetCodexId()}' - Revision: {codexStarter.GetCodexRevision()}"); + Log($"Loaded with Codex ID: '{codexWrapper.GetCodexId()}' - Revision: {codexWrapper.GetCodexRevision()}"); } public void AddMetadata(IAddMetadata metadata) { - metadata.Add("codexid", codexStarter.GetCodexId()); - metadata.Add("codexrevision", codexStarter.GetCodexRevision()); + metadata.Add("codexid", codexWrapper.GetCodexId()); + metadata.Add("codexrevision", codexWrapper.GetCodexRevision()); } public void Decommission() @@ -43,7 +46,7 @@ namespace CodexPlugin public ICodexNodeGroup WrapCodexContainers(ICodexInstance[] instances) { instances = instances.Select(c => SerializeGate.Gate(c as CodexInstance)).ToArray(); - return codexStarter.WrapCodexContainers(instances); + return codexWrapper.WrapCodexInstances(instances); } public void WireUpMarketplace(ICodexNodeGroup result, Action setup) diff --git a/ProjectPlugins/CodexPlugin/CodexWrapper.cs b/ProjectPlugins/CodexPlugin/CodexWrapper.cs new file mode 100644 index 00000000..a4a4eda6 --- /dev/null +++ b/ProjectPlugins/CodexPlugin/CodexWrapper.cs @@ -0,0 +1,80 @@ +using CodexClient; +using CodexClient.Hooks; +using Core; +using Logging; + +namespace CodexPlugin +{ + public class CodexWrapper + { + private readonly IPluginTools pluginTools; + private readonly ProcessControlMap processControlMap; + private readonly CodexHooksFactory hooksFactory; + private DebugInfoVersion? versionResponse; + + public CodexWrapper(IPluginTools pluginTools, ProcessControlMap processControlMap, CodexHooksFactory hooksFactory) + { + this.pluginTools = pluginTools; + this.processControlMap = processControlMap; + this.hooksFactory = hooksFactory; + } + + public string GetCodexId() + { + if (versionResponse != null) return versionResponse.Version; + return "unknown"; + } + + public string GetCodexRevision() + { + if (versionResponse != null) return versionResponse.Revision; + return "unknown"; + } + + public ICodexNodeGroup WrapCodexInstances(ICodexInstance[] instances) + { + var codexNodeFactory = new CodexNodeFactory( + log: pluginTools.GetLog(), + fileManager: pluginTools.GetFileManager(), + hooksFactory: hooksFactory, + httpFactory: pluginTools, + processControlFactory: processControlMap); + + var group = CreateCodexGroup(instances, codexNodeFactory); + + pluginTools.GetLog().Log($"Codex version: {group.Version}"); + versionResponse = group.Version; + + return group; + } + + private CodexNodeGroup CreateCodexGroup(ICodexInstance[] instances, CodexNodeFactory codexNodeFactory) + { + var nodes = instances.Select(codexNodeFactory.CreateCodexNode).ToArray(); + var group = new CodexNodeGroup(pluginTools, nodes); + + try + { + Stopwatch.Measure(pluginTools.GetLog(), "EnsureOnline", group.EnsureOnline); + } + catch + { + CodexNodesNotOnline(instances); + throw; + } + + return group; + } + + private void CodexNodesNotOnline(ICodexInstance[] instances) + { + pluginTools.GetLog().Log("Codex nodes failed to start"); + var log = pluginTools.GetLog(); + foreach (var i in instances) + { + var pc = processControlMap.Get(i); + pc.DownloadLog(log.CreateSubfile(i.Name + "_failed_to_start")); + } + } + } +} diff --git a/ProjectPlugins/CodexPlugin/ContainerCodexStarter.cs b/ProjectPlugins/CodexPlugin/ContainerCodexStarter.cs index f40d8115..658641b6 100644 --- a/ProjectPlugins/CodexPlugin/ContainerCodexStarter.cs +++ b/ProjectPlugins/CodexPlugin/ContainerCodexStarter.cs @@ -1,9 +1,7 @@ using CodexClient; -using CodexClient.Hooks; using Core; using KubernetesWorkflow; using KubernetesWorkflow.Types; -using Logging; using Utils; namespace CodexPlugin @@ -11,24 +9,17 @@ namespace CodexPlugin public class ContainerCodexStarter : ICodexStarter { private readonly IPluginTools pluginTools; - private readonly CodexHooksFactory hooksFactory; + private readonly ProcessControlMap processControlMap; private readonly CodexContainerRecipe recipe = new CodexContainerRecipe(); private readonly ApiChecker apiChecker; - private readonly Dictionary processControlMap = new Dictionary(); - private DebugInfoVersion? versionResponse; - public ContainerCodexStarter(IPluginTools pluginTools, CodexHooksFactory hooksFactory) + public ContainerCodexStarter(IPluginTools pluginTools, ProcessControlMap processControlMap) { this.pluginTools = pluginTools; - this.hooksFactory = hooksFactory; + this.processControlMap = processControlMap; apiChecker = new ApiChecker(pluginTools); } - public IProcessControl CreateProcessControl(ICodexInstance instance) - { - return processControlMap[instance.Name]; - } - public ICodexInstance[] BringOnline(CodexSetup codexSetup) { LogSeparator(); @@ -52,35 +43,6 @@ namespace CodexPlugin return containers.Select(CreateInstance).ToArray(); } - public ICodexNodeGroup WrapCodexContainers(ICodexInstance[] instances) - { - var codexNodeFactory = new CodexNodeFactory( - log: pluginTools.GetLog(), - fileManager: pluginTools.GetFileManager(), - hooksFactory: hooksFactory, - httpFactory: pluginTools, - processControlFactory: this); - - var group = CreateCodexGroup(instances, codexNodeFactory); - - Log($"Codex version: {group.Version}"); - versionResponse = group.Version; - - return group; - } - - public string GetCodexId() - { - if (versionResponse != null) return versionResponse.Version; - return recipe.Image; - } - - public string GetCodexRevision() - { - if (versionResponse != null) return versionResponse.Revision; - return "unknown"; - } - private StartupConfig CreateStartupConfig(CodexSetup codexSetup) { var startupConfig = new StartupConfig(); @@ -109,46 +71,17 @@ namespace CodexPlugin return workflow.GetPodInfo(rc); } - private CodexNodeGroup CreateCodexGroup(ICodexInstance[] instances, CodexNodeFactory codexNodeFactory) - { - var nodes = instances.Select(codexNodeFactory.CreateCodexNode).ToArray(); - var group = new CodexNodeGroup(pluginTools, nodes); - - try - { - Stopwatch.Measure(pluginTools.GetLog(), "EnsureOnline", group.EnsureOnline); - } - catch - { - CodexNodesNotOnline(instances); - throw; - } - - return group; - } - private ICodexInstance CreateInstance(RunningPod pod) { var instance = CodexInstanceContainerExtension.CreateFromPod(pod); var processControl = new CodexContainerProcessControl(pluginTools, pod, onStop: () => { - processControlMap.Remove(instance.Name); + processControlMap.Remove(instance); }); - processControlMap.Add(instance.Name, processControl); + processControlMap.Add(instance, processControl); return instance; } - private void CodexNodesNotOnline(ICodexInstance[] instances) - { - Log("Codex nodes failed to start"); - var log = pluginTools.GetLog(); - foreach (var i in instances) - { - var pc = processControlMap[i.Name]; - pc.DownloadLog(log.CreateSubfile(i.Name + "_failed_to_start")); - } - } - private void LogSeparator() { Log("----------------------------------------------------------------------------"); @@ -166,66 +99,4 @@ namespace CodexPlugin pluginTools.GetLog().Log(message); } } - - public class CodexContainerProcessControl : IProcessControl - { - private readonly IPluginTools tools; - private readonly RunningPod pod; - private readonly Action onStop; - private readonly ContainerCrashWatcher crashWatcher; - - public CodexContainerProcessControl(IPluginTools tools, RunningPod pod, Action onStop) - { - this.tools = tools; - this.pod = pod; - this.onStop = onStop; - - crashWatcher = tools.CreateWorkflow().CreateCrashWatcher(pod.Containers.Single()); - crashWatcher.Start(); - } - - public void Stop(bool waitTillStopped) - { - Log($"Stopping node..."); - var workflow = tools.CreateWorkflow(); - workflow.Stop(pod, waitTillStopped); - crashWatcher.Stop(); - onStop(); - Log("Stopped."); - } - - public IDownloadedLog DownloadLog(LogFile file) - { - var workflow = tools.CreateWorkflow(); - return workflow.DownloadContainerLog(pod.Containers.Single()); - } - - public void DeleteDataDirFolder() - { - var container = pod.Containers.Single(); - - try - { - var dataDirVar = container.Recipe.EnvVars.Single(e => e.Name == "CODEX_DATA_DIR"); - var dataDir = dataDirVar.Value; - var workflow = tools.CreateWorkflow(); - workflow.ExecuteCommand(container, "rm", "-Rfv", $"/codex/{dataDir}/repo"); - Log("Deleted repo folder."); - } - catch (Exception e) - { - Log("Unable to delete repo folder: " + e); - } - } - - public bool HasCrashed() - { - return crashWatcher.HasCrashed(); - } - - private void Log(string message) - { - tools.GetLog().Log(message); - } - } } diff --git a/ProjectPlugins/CodexPlugin/ICodexStarter.cs b/ProjectPlugins/CodexPlugin/ICodexStarter.cs index 5becf6a3..4f264342 100644 --- a/ProjectPlugins/CodexPlugin/ICodexStarter.cs +++ b/ProjectPlugins/CodexPlugin/ICodexStarter.cs @@ -2,11 +2,8 @@ namespace CodexPlugin { - public interface ICodexStarter : IProcessControlFactory + public interface ICodexStarter { - string GetCodexId(); - string GetCodexRevision(); ICodexInstance[] BringOnline(CodexSetup codexSetup); - ICodexNodeGroup WrapCodexContainers(ICodexInstance[] instances); } } diff --git a/ProjectPlugins/CodexPlugin/ProcessControlMap.cs b/ProjectPlugins/CodexPlugin/ProcessControlMap.cs new file mode 100644 index 00000000..a91cce99 --- /dev/null +++ b/ProjectPlugins/CodexPlugin/ProcessControlMap.cs @@ -0,0 +1,29 @@ +using CodexClient; + +namespace CodexPlugin +{ + public class ProcessControlMap : IProcessControlFactory + { + private readonly Dictionary processControlMap = new Dictionary(); + + public void Add(ICodexInstance instance, IProcessControl control) + { + processControlMap.Add(instance.Name, control); + } + + public void Remove(ICodexInstance instance) + { + processControlMap.Remove(instance.Name); + } + + public IProcessControl CreateProcessControl(ICodexInstance instance) + { + return Get(instance); + } + + public IProcessControl Get(ICodexInstance instance) + { + return processControlMap[instance.Name]; + } + } +}