From 48dda1735cc19b2446f5d4ce9859731b5aa43351 Mon Sep 17 00:00:00 2001 From: ThatBen Date: Mon, 11 Sep 2023 16:57:57 +0200 Subject: [PATCH] Good progress --- CodexPlugin/CodexAccess.cs | 4 +- CodexPlugin/CodexNodeFactory.cs | 14 +-- CodexPlugin/CodexNodeGroup.cs | 29 +++-- CodexPlugin/CodexStarter.cs | 129 ++++++++++++---------- CodexPlugin/DistTestExtensions.cs | 12 +- CodexPlugin/OnlineCodexNode.cs | 7 +- CodexPlugin/Plugin.cs | 40 +++++++ DistTestCore/Configuration.cs | 66 ----------- DistTestCore/Http.cs | 6 +- DistTestCore/PluginManager.cs | 64 +++++++++++ DistTestCore/TestLifecycle.cs | 8 ++ KubernetesWorkflow/RunnerLocationUtils.cs | 55 +++++++++ KubernetesWorkflow/RunningContainers.cs | 13 +++ KubernetesWorkflow/StartupConfig.cs | 1 + KubernetesWorkflow/StartupWorkflow.cs | 31 ++++-- KubernetesWorkflow/WorkflowCreator.cs | 2 +- Logging/BaseLog.cs | 13 ++- Logging/Stopwatch.cs | 16 +-- Tests/Tests.csproj | 1 - 19 files changed, 332 insertions(+), 179 deletions(-) create mode 100644 CodexPlugin/Plugin.cs create mode 100644 DistTestCore/PluginManager.cs create mode 100644 KubernetesWorkflow/RunnerLocationUtils.cs diff --git a/CodexPlugin/CodexAccess.cs b/CodexPlugin/CodexAccess.cs index 13d971ca..75823c8f 100644 --- a/CodexPlugin/CodexAccess.cs +++ b/CodexPlugin/CodexAccess.cs @@ -7,11 +7,11 @@ namespace CodexPlugin { public class CodexAccess : ILogHandler { - private readonly BaseLog log; + private readonly ILog log; private readonly ITimeSet timeSet; private bool hasContainerCrashed; - public CodexAccess(BaseLog log, RunningContainer container, ITimeSet timeSet, Address address) + public CodexAccess(ILog log, RunningContainer container, ITimeSet timeSet, Address address) { this.log = log; Container = container; diff --git a/CodexPlugin/CodexNodeFactory.cs b/CodexPlugin/CodexNodeFactory.cs index 5e3abbdb..0394fac4 100644 --- a/CodexPlugin/CodexNodeFactory.cs +++ b/CodexPlugin/CodexNodeFactory.cs @@ -3,7 +3,7 @@ namespace CodexPlugin { public interface ICodexNodeFactory { - //OnlineCodexNode CreateOnlineCodexNode(CodexAccess access, CodexNodeGroup group); + OnlineCodexNode CreateOnlineCodexNode(CodexAccess access, CodexNodeGroup group); } public class CodexNodeFactory : ICodexNodeFactory @@ -19,11 +19,11 @@ namespace CodexPlugin // this.marketplaceAccessFactory = marketplaceAccessFactory; //} - //public OnlineCodexNode CreateOnlineCodexNode(CodexAccess access, CodexNodeGroup group) - //{ - // var metricsAccess = metricsAccessFactory.CreateMetricsAccess(access.Container); - // var marketplaceAccess = marketplaceAccessFactory.CreateMarketplaceAccess(access); - // return new OnlineCodexNode(lifecycle, access, group, metricsAccess, marketplaceAccess); - //} + public OnlineCodexNode CreateOnlineCodexNode(CodexAccess access, CodexNodeGroup group) + { + //var metricsAccess = metricsAccessFactory.CreateMetricsAccess(access.Container); + //var marketplaceAccess = marketplaceAccessFactory.CreateMarketplaceAccess(access); + return new OnlineCodexNode(/*lifecycle,*/ access, group/*, metricsAccess, marketplaceAccess*/); + } } } diff --git a/CodexPlugin/CodexNodeGroup.cs b/CodexPlugin/CodexNodeGroup.cs index e783c205..bd9980b1 100644 --- a/CodexPlugin/CodexNodeGroup.cs +++ b/CodexPlugin/CodexNodeGroup.cs @@ -1,11 +1,13 @@ -using KubernetesWorkflow; +using DistTestCore; +using KubernetesWorkflow; +using Logging; using System.Collections; namespace CodexPlugin { public interface ICodexNodeGroup : IEnumerable { - ICodexSetup BringOffline(); + void BringOffline(); IOnlineCodexNode this[int index] { get; } } @@ -13,12 +15,12 @@ namespace CodexPlugin { //private readonly TestLifecycle lifecycle; - public CodexNodeGroup(/*TestLifecycle lifecycle, */CodexSetup setup, RunningContainers[] containers, ICodexNodeFactory codexNodeFactory) + public CodexNodeGroup(/*TestLifecycle lifecycle, CodexSetup setup,*/ILog log, ITimeSet timeSet, RunningContainers[] containers, ICodexNodeFactory codexNodeFactory) { //this.lifecycle = lifecycle; - Setup = setup; + //Setup = setup; Containers = containers; - Nodes = containers.Containers().Select(c => CreateOnlineCodexNode(c, codexNodeFactory)).ToArray(); + Nodes = containers.Containers().Select(c => CreateOnlineCodexNode(c, log, timeSet, codexNodeFactory)).ToArray(); Version = new CodexDebugVersionResponse(); } @@ -30,20 +32,18 @@ namespace CodexPlugin } } - public ICodexSetup BringOffline() + public void BringOffline() { //lifecycle.CodexStarter.BringOffline(this); - var result = Setup; + //var result = Setup; // Clear everything. Prevent accidental use. - Setup = null!; + //Setup = null!; Nodes = Array.Empty(); Containers = null!; - - return result; } - public CodexSetup Setup { get; private set; } + //public CodexSetup Setup { get; private set; } public RunningContainers[] Containers { get; private set; } public OnlineCodexNode[] Nodes { get; private set; } public CodexDebugVersionResponse Version { get; private set; } @@ -78,11 +78,10 @@ namespace CodexPlugin Version = first; } - private OnlineCodexNode CreateOnlineCodexNode(RunningContainer c, ICodexNodeFactory factory) + private OnlineCodexNode CreateOnlineCodexNode(RunningContainer c, ILog log, ITimeSet timeSet, ICodexNodeFactory factory) { - //var access = new CodexAccess(lifecycle.Log, c, lifecycle.TimeSet, lifecycle.Configuration.GetAddress(c)); - //return factory.CreateOnlineCodexNode(access, this); - return null!; + var access = new CodexAccess(log, c, timeSet, c.Address); + return factory.CreateOnlineCodexNode(access, this); } } } diff --git a/CodexPlugin/CodexStarter.cs b/CodexPlugin/CodexStarter.cs index dcd99083..c3ccfb20 100644 --- a/CodexPlugin/CodexStarter.cs +++ b/CodexPlugin/CodexStarter.cs @@ -1,26 +1,32 @@ -using KubernetesWorkflow; +using DistTestCore; +using KubernetesWorkflow; using Logging; namespace CodexPlugin { - public class CodexStarter //: BaseStarter + public class CodexStarter { + private readonly IPluginActions pluginActions; + //public CodexStarter(TestLifecycle lifecycle) // : base(lifecycle) //{ //} - public List RunningGroups { get; } = new List(); + public CodexStarter(IPluginActions pluginActions) + { + this.pluginActions = pluginActions; + } - public ICodexNodeGroup BringOnline(CodexSetup codexSetup) + public RunningContainers[] BringOnline(CodexSetup codexSetup) { //LogSeparator(); //LogStart($"Starting {codexSetup.Describe()}..."); //var gethStartResult = lifecycle.GethStarter.BringOnlineMarketplaceFor(codexSetup); - //var startupConfig = CreateStartupConfig(gethStartResult, codexSetup); + var startupConfig = CreateStartupConfig(/*gethStartResult,*/ codexSetup); - //var containers = StartCodexContainers(startupConfig, codexSetup.NumberOfNodes, codexSetup.Location); + return StartCodexContainers(startupConfig, codexSetup.NumberOfNodes, codexSetup.Location); //var metricAccessFactory = CollectMetrics(codexSetup, containers); @@ -38,7 +44,26 @@ namespace CodexPlugin //LogSeparator(); //return group; - return null!; + } + + public ICodexNodeGroup WrapCodexContainers(RunningContainers[] containers) + { + //var metricAccessFactory = CollectMetrics(codexSetup, containers); + + var codexNodeFactory = new CodexNodeFactory();// (lifecycle, metricAccessFactory, gethStartResult.MarketplaceAccessFactory); + + return CreateCodexGroup(/*codexSetup,*/ containers, codexNodeFactory); + //lifecycle.SetCodexVersion(group.Version); + + //var nl = Environment.NewLine; + //var podInfos = string.Join(nl, containers.Containers().Select(c => $"Container: '{c.Name}' runs at '{c.Pod.PodInfo.K8SNodeName}'={c.Pod.PodInfo.Ip}")); + //LogEnd($"Started {codexSetup.NumberOfNodes} nodes " + + // $"of image '{containers.Containers().First().Recipe.Image}' " + + // $"and version '{group.Version}'{nl}" + + // podInfos); + //LogSeparator(); + + //return group; } public void BringOffline(CodexNodeGroup group) @@ -50,7 +75,6 @@ namespace CodexPlugin // StopCrashWatcher(c); // workflow.Stop(c); //} - //RunningGroups.Remove(group); //LogEnd("Stopped."); } @@ -58,8 +82,6 @@ namespace CodexPlugin { //var workflow = CreateWorkflow(); //workflow.DeleteTestResources(); - - //RunningGroups.Clear(); } public void DownloadLog(RunningContainer container, ILogHandler logHandler, int? tailLines) @@ -82,52 +104,51 @@ namespace CodexPlugin // return new CodexNodeMetricsAccessFactory(lifecycle, runningContainers); //} - //private StartupConfig CreateStartupConfig(GethStartResult gethStartResult, CodexSetup codexSetup) - //{ - // var startupConfig = new StartupConfig(); - // startupConfig.NameOverride = codexSetup.NameOverride; - // startupConfig.Add(codexSetup); - // startupConfig.Add(gethStartResult); - // return startupConfig; - //} + private StartupConfig CreateStartupConfig(/*GethStartResult gethStartResult, */ CodexSetup codexSetup) + { + var startupConfig = new StartupConfig(); + startupConfig.NameOverride = codexSetup.NameOverride; + startupConfig.CreateCrashWatcher = true; + startupConfig.Add(codexSetup); + //startupConfig.Add(gethStartResult); + return startupConfig; + } - //private RunningContainers[] StartCodexContainers(StartupConfig startupConfig, int numberOfNodes, Location location) - //{ - // var result = new List(); - // var recipe = new CodexContainerRecipe(); - // for (var i = 0; i < numberOfNodes; i++) - // { - // var workflow = CreateWorkflow(); - // var rc = workflow.Start(1, location, recipe, startupConfig); - // CreateCrashWatcher(workflow, rc); - // result.Add(rc); - // } - // return result.ToArray(); - //} + private RunningContainers[] StartCodexContainers(StartupConfig startupConfig, int numberOfNodes, Location location) + { + var result = new List(); + var recipe = new CodexContainerRecipe(); + for (var i = 0; i < numberOfNodes; i++) + { + var workflow = pluginActions.CreateWorkflow(); + result.Add(workflow.Start(1, location, recipe, startupConfig)); + } + return result.ToArray(); + } - //private CodexNodeGroup CreateCodexGroup(CodexSetup codexSetup, RunningContainers[] runningContainers, CodexNodeFactory codexNodeFactory) - //{ - // var group = new CodexNodeGroup(lifecycle, codexSetup, runningContainers, codexNodeFactory); - // RunningGroups.Add(group); + private CodexNodeGroup CreateCodexGroup(/*CodexSetup codexSetup, */RunningContainers[] runningContainers, CodexNodeFactory codexNodeFactory) + { + var group = new CodexNodeGroup(pluginActions.GetLog(), pluginActions.GetTimeSet(), /*lifecycle, codexSetup,*/ runningContainers, codexNodeFactory); - // try - // { - // Stopwatch.Measure(lifecycle.Log, "EnsureOnline", group.EnsureOnline, debug: true); - // } - // catch - // { - // CodexNodesNotOnline(runningContainers); - // throw; - // } + try + { + Stopwatch.Measure(pluginActions.GetLog(), "EnsureOnline", group.EnsureOnline, debug: true); + } + catch + { + CodexNodesNotOnline(runningContainers); + throw; + } - // return group; - //} + return group; + } - //private void CodexNodesNotOnline(RunningContainers[] runningContainers) - //{ - // Log("Codex nodes failed to start"); - // foreach (var container in runningContainers.Containers()) lifecycle.DownloadLog(container); - //} + private void CodexNodesNotOnline(RunningContainers[] runningContainers) + { + pluginActions.GetLog().Log("Codex nodes failed to start"); + // todo: + //foreach (var container in runningContainers.Containers()) lifecycle.DownloadLog(container); + } //private StartupWorkflow CreateWorkflow() //{ @@ -139,12 +160,6 @@ namespace CodexPlugin // Log("----------------------------------------------------------------------------"); //} - //private void CreateCrashWatcher(StartupWorkflow workflow, RunningContainers rc) - //{ - // var c = rc.Containers.Single(); - // c.CrashWatcher = workflow.CreateCrashWatcher(c); - //} - //private void StopCrashWatcher(RunningContainers containers) //{ // foreach (var c in containers.Containers) diff --git a/CodexPlugin/DistTestExtensions.cs b/CodexPlugin/DistTestExtensions.cs index e6996278..ebb1d810 100644 --- a/CodexPlugin/DistTestExtensions.cs +++ b/CodexPlugin/DistTestExtensions.cs @@ -5,24 +5,26 @@ namespace CodexPlugin { public static class DistTestExtensions { - public static RunningContainers StartCodexNodes(this DistTest distTest, int number, Action setup) + public static Plugin Plugin { get; internal set; } = null!; + + public static RunningContainers[] StartCodexNodes(this DistTest distTest, int number, Action setup) { - return null!; + return Plugin.StartCodexNodes(number, setup); } public static ICodexNodeGroup WrapCodexContainers(this DistTest distTest, RunningContainers containers) { - return null!; + return Plugin.WrapCodexContainers(containers); } public static IOnlineCodexNode SetupCodexNode(this DistTest distTest, Action setup) { - return null!; + return Plugin.SetupCodexNode(setup); } public static ICodexNodeGroup SetupCodexNodes(this DistTest distTest, int number) { - return null!; + return Plugin.SetupCodexNodes(number); } } } diff --git a/CodexPlugin/OnlineCodexNode.cs b/CodexPlugin/OnlineCodexNode.cs index 0a6a0943..a6bc54b7 100644 --- a/CodexPlugin/OnlineCodexNode.cs +++ b/CodexPlugin/OnlineCodexNode.cs @@ -1,6 +1,5 @@ using DistTestCore.Logs; using FileUtils; -using Logging; using NUnit.Framework; using Utils; @@ -18,7 +17,7 @@ namespace CodexPlugin //IMetricsAccess Metrics { get; } //IMarketplaceAccess Marketplace { get; } CodexDebugVersionResponse Version { get; } - ICodexSetup BringOffline(); + void BringOffline(); } public class OnlineCodexNode : IOnlineCodexNode @@ -108,13 +107,13 @@ namespace CodexPlugin return null!; // lifecycle.DownloadLog(CodexAccess.Container, tailLines); } - public ICodexSetup BringOffline() + public void BringOffline() { if (Group.Count() > 1) throw new InvalidOperationException("Codex-nodes that are part of a group cannot be " + "individually shut down. Use 'BringOffline()' on the group object to stop the group. This method is only " + "available for codex-nodes in groups of 1."); - return Group.BringOffline(); + Group.BringOffline(); } public void EnsureOnlineGetVersionResponse() diff --git a/CodexPlugin/Plugin.cs b/CodexPlugin/Plugin.cs new file mode 100644 index 00000000..a014f8ec --- /dev/null +++ b/CodexPlugin/Plugin.cs @@ -0,0 +1,40 @@ +using DistTestCore; +using KubernetesWorkflow; + +namespace CodexPlugin +{ + public class Plugin : IProjectPlugin + { + private readonly CodexStarter codexStarter; + + public Plugin(IPluginActions actions) + { + codexStarter = new CodexStarter(actions); + + DistTestExtensions.Plugin = this; + } + + public RunningContainers[] StartCodexNodes(int numberOfNodes, Action setup) + { + var codexSetup = new CodexSetup(numberOfNodes, CodexLogLevel.Trace); + setup(codexSetup); + return codexStarter.BringOnline(codexSetup); + } + + public ICodexNodeGroup WrapCodexContainers(RunningContainers[] containers) + { + return codexStarter.WrapCodexContainers(containers); + } + + public IOnlineCodexNode SetupCodexNode(Action setup) + { + return null!; + } + + public ICodexNodeGroup SetupCodexNodes(int number) + { + var rc = StartCodexNodes(1, s => { }); + return WrapCodexContainers(rc); + } + } +} diff --git a/DistTestCore/Configuration.cs b/DistTestCore/Configuration.cs index 86dc2388..e8a38564 100644 --- a/DistTestCore/Configuration.cs +++ b/DistTestCore/Configuration.cs @@ -12,7 +12,6 @@ namespace DistTestCore private readonly string dataFilesPath; //private readonly CodexLogLevel codexLogLevel; private readonly string k8sNamespacePrefix; - private static RunnerLocation? runnerLocation = null; public Configuration() { @@ -59,20 +58,6 @@ namespace DistTestCore // return codexLogLevel; //} - public Address GetAddress(RunningContainer container) - { - if (runnerLocation == null) - { - runnerLocation = RunnerLocationUtils.DetermineRunnerLocation(container); - } - - if (runnerLocation == RunnerLocation.InternalToCluster) - { - return container.ClusterInternalAddress; - } - return container.ClusterExternalAddress; - } - private static string GetEnvVarOrDefault(string varName, string defaultValue) { var v = Environment.GetEnvironmentVariable(varName); @@ -88,56 +73,5 @@ namespace DistTestCore } } - public enum RunnerLocation - { - ExternalToCluster, - InternalToCluster, - } - public static class RunnerLocationUtils - { - private static bool alreadyDidThat = false; - - public static RunnerLocation DetermineRunnerLocation(RunningContainer container) - { - // We want to be sure we don't ping more often than strictly necessary. - // If we have already determined the location during this application - // lifetime, don't do it again. - if (alreadyDidThat) throw new Exception("We already did that."); - alreadyDidThat = true; - - if (PingHost(container.Pod.PodInfo.Ip)) - { - return RunnerLocation.InternalToCluster; - } - if (PingHost(Format(container.ClusterExternalAddress))) - { - return RunnerLocation.ExternalToCluster; - } - - throw new Exception("Unable to determine runner location."); - } - - private static string Format(Address host) - { - return host.Host - .Replace("http://", "") - .Replace("https://", ""); - } - - private static bool PingHost(string host) - { - try - { - using var pinger = new Ping(); - PingReply reply = pinger.Send(host); - return reply.Status == IPStatus.Success; - } - catch (PingException) - { - } - - return false; - } - } } diff --git a/DistTestCore/Http.cs b/DistTestCore/Http.cs index 773f9a56..5df53bbe 100644 --- a/DistTestCore/Http.cs +++ b/DistTestCore/Http.cs @@ -9,19 +9,19 @@ namespace DistTestCore { public class Http { - private readonly BaseLog log; + private readonly ILog log; private readonly ITimeSet timeSet; private readonly Address address; private readonly string baseUrl; private readonly Action onClientCreated; private readonly string? logAlias; - public Http(BaseLog log, ITimeSet timeSet, Address address, string baseUrl, string? logAlias = null) + public Http(ILog log, ITimeSet timeSet, Address address, string baseUrl, string? logAlias = null) : this(log, timeSet, address, baseUrl, DoNothing, logAlias) { } - public Http(BaseLog log, ITimeSet timeSet, Address address, string baseUrl, Action onClientCreated, string? logAlias = null) + public Http(ILog log, ITimeSet timeSet, Address address, string baseUrl, Action onClientCreated, string? logAlias = null) { this.log = log; this.timeSet = timeSet; diff --git a/DistTestCore/PluginManager.cs b/DistTestCore/PluginManager.cs new file mode 100644 index 00000000..ea21e6d6 --- /dev/null +++ b/DistTestCore/PluginManager.cs @@ -0,0 +1,64 @@ +using KubernetesWorkflow; +using Logging; + +namespace DistTestCore +{ + public class PluginManager : IPluginActions + { + private readonly BaseLog log; + private readonly Configuration configuration; + private readonly string testNamespace; + private readonly WorkflowCreator workflowCreator; + private readonly ITimeSet timeSet; + private readonly List projectPlugins = new List(); + + public PluginManager(BaseLog log, Configuration configuration, ITimeSet timeSet, string testNamespace) + { + this.log = log; + this.configuration = configuration; + this.timeSet = timeSet; + this.testNamespace = testNamespace; + workflowCreator = new WorkflowCreator(log, configuration.GetK8sConfiguration(timeSet), testNamespace); + } + + public IStartupWorkflow CreateWorkflow() + { + return workflowCreator.CreateWorkflow(); + } + + public ILog GetLog() + { + return log; + } + + public ITimeSet GetTimeSet() + { + return timeSet; + } + + public void InitializeAllPlugins() + { + var assemblies = AppDomain.CurrentDomain.GetAssemblies(); + var pluginTypes = assemblies.SelectMany(a => a.GetTypes().Where(t => typeof(IProjectPlugin).IsAssignableFrom(t))).ToArray(); + + foreach (var pluginType in pluginTypes) + { + IPluginActions actions = this; + var plugin = (IProjectPlugin)Activator.CreateInstance(pluginType, args: actions)!; + projectPlugins.Add(plugin); + } + } + } + + public interface IProjectPlugin + { + } + + // probably seggregate this out. + public interface IPluginActions + { + IStartupWorkflow CreateWorkflow(); + ILog GetLog(); + ITimeSet GetTimeSet(); + } +} diff --git a/DistTestCore/TestLifecycle.cs b/DistTestCore/TestLifecycle.cs index eeb65c6e..be3da02e 100644 --- a/DistTestCore/TestLifecycle.cs +++ b/DistTestCore/TestLifecycle.cs @@ -26,6 +26,14 @@ namespace DistTestCore testStart = DateTime.UtcNow; //CodexVersion = null; + // the plugin manager is starting to look like the testlifecycle, that's bad because they are not supposed to be doing the same things: + // pluginmanager should be useful for disttest-deployer-continuoustest, everyone! + // but testlifecycle should be a disttest specific user of the plugin manager. + // disttest requires a hook by which it can keep track of containers created?? (does it?) /namespace used? for the purpose of cleaning up. + + //var pluginManager = new PluginManager(Log, configuration, timeSet, testNamespace); + //pluginManager.InitializeAllPlugins(); + Log.WriteLogTag(); } diff --git a/KubernetesWorkflow/RunnerLocationUtils.cs b/KubernetesWorkflow/RunnerLocationUtils.cs new file mode 100644 index 00000000..05d88c49 --- /dev/null +++ b/KubernetesWorkflow/RunnerLocationUtils.cs @@ -0,0 +1,55 @@ +using System.Net.NetworkInformation; +using Utils; + +namespace KubernetesWorkflow +{ + internal enum RunnerLocation + { + ExternalToCluster, + InternalToCluster, + } + + internal static class RunnerLocationUtils + { + private static RunnerLocation? knownLocation = null; + + internal static RunnerLocation DetermineRunnerLocation(RunningContainer container) + { + if (knownLocation != null) return knownLocation.Value; + + if (PingHost(container.Pod.PodInfo.Ip)) + { + knownLocation = RunnerLocation.InternalToCluster; + } + if (PingHost(Format(container.ClusterExternalAddress))) + { + knownLocation = RunnerLocation.ExternalToCluster; + } + + if (knownLocation == null) throw new Exception("Unable to determine location relative to kubernetes cluster."); + return knownLocation.Value; + } + + private static string Format(Address host) + { + return host.Host + .Replace("http://", "") + .Replace("https://", ""); + } + + private static bool PingHost(string host) + { + try + { + using var pinger = new Ping(); + PingReply reply = pinger.Send(host); + return reply.Status == IPStatus.Success; + } + catch (PingException) + { + } + + return false; + } + } +} diff --git a/KubernetesWorkflow/RunningContainers.cs b/KubernetesWorkflow/RunningContainers.cs index 3f43a378..4b36f955 100644 --- a/KubernetesWorkflow/RunningContainers.cs +++ b/KubernetesWorkflow/RunningContainers.cs @@ -43,6 +43,19 @@ namespace KubernetesWorkflow [JsonIgnore] public CrashWatcher? CrashWatcher { get; set; } + + [JsonIgnore] + public Address Address + { + get + { + if (RunnerLocationUtils.DetermineRunnerLocation(this) == RunnerLocation.InternalToCluster) + { + return ClusterInternalAddress; + } + return ClusterExternalAddress; + } + } } public static class RunningContainersExtensions diff --git a/KubernetesWorkflow/StartupConfig.cs b/KubernetesWorkflow/StartupConfig.cs index 76a96b67..6aa7268a 100644 --- a/KubernetesWorkflow/StartupConfig.cs +++ b/KubernetesWorkflow/StartupConfig.cs @@ -5,6 +5,7 @@ private readonly List configs = new List(); public string? NameOverride { get; set; } + public bool CreateCrashWatcher { get; set; } public void Add(object config) { diff --git a/KubernetesWorkflow/StartupWorkflow.cs b/KubernetesWorkflow/StartupWorkflow.cs index 7595be21..5bf5b733 100644 --- a/KubernetesWorkflow/StartupWorkflow.cs +++ b/KubernetesWorkflow/StartupWorkflow.cs @@ -3,7 +3,17 @@ using Utils; namespace KubernetesWorkflow { - public class StartupWorkflow + public interface IStartupWorkflow + { + RunningContainers Start(int numberOfContainers, Location location, ContainerRecipeFactory recipeFactory, StartupConfig startupConfig); + void Stop(RunningContainers runningContainers); + void DownloadContainerLog(RunningContainer container, ILogHandler logHandler, int? tailLines); + string ExecuteCommand(RunningContainer container, string command, params string[] args); + void DeleteAllResources();// !!! delete namespace then!? + void DeleteTestResources(); // !!! do not mention tests. what are we deleting? + } + + public class StartupWorkflow : IStartupWorkflow { private readonly BaseLog log; private readonly WorkflowNumberSource numberSource; @@ -26,18 +36,15 @@ namespace KubernetesWorkflow return K8s(controller => { var recipes = CreateRecipes(numberOfContainers, recipeFactory, startupConfig); - var runningPod = controller.BringOnline(recipes, location); + var containers = CreateContainers(runningPod, recipes, startupConfig); - return new RunningContainers(startupConfig, runningPod, CreateContainers(runningPod, recipes, startupConfig)); + if (startupConfig.CreateCrashWatcher) CreateCrashWatchers(controller, containers); + + return new RunningContainers(startupConfig, runningPod, containers); }); } - public CrashWatcher CreateCrashWatcher(RunningContainer container) - { - return K8s(controller => controller.CreateCrashWatcher(container)); - } - public void Stop(RunningContainers runningContainers) { K8s(controller => @@ -78,6 +85,14 @@ namespace KubernetesWorkflow }); } + private void CreateCrashWatchers(K8sController controller, RunningContainer[] runningContainers) + { + foreach (var container in runningContainers) + { + container.CrashWatcher = controller.CreateCrashWatcher(container); + } + } + private RunningContainer[] CreateContainers(RunningPod runningPod, ContainerRecipe[] recipes, StartupConfig startupConfig) { log.Debug(); diff --git a/KubernetesWorkflow/WorkflowCreator.cs b/KubernetesWorkflow/WorkflowCreator.cs index 51f0177d..ae8c85bc 100644 --- a/KubernetesWorkflow/WorkflowCreator.cs +++ b/KubernetesWorkflow/WorkflowCreator.cs @@ -19,7 +19,7 @@ namespace KubernetesWorkflow this.testNamespace = testNamespace.ToLowerInvariant(); } - public StartupWorkflow CreateWorkflow() + public IStartupWorkflow CreateWorkflow() { var workflowNumberSource = new WorkflowNumberSource(numberSource.GetNextNumber(), containerNumberSource); diff --git a/Logging/BaseLog.cs b/Logging/BaseLog.cs index d11ecc17..b106b84d 100644 --- a/Logging/BaseLog.cs +++ b/Logging/BaseLog.cs @@ -1,8 +1,17 @@ -using Utils; +using System.Diagnostics; +using Utils; namespace Logging { - public abstract class BaseLog + public interface ILog + { + void Log(string message); + void Debug(string message = "", int skipFrames = 0); + void Error(string message); + LogFile CreateSubfile(string ext = "log"); + } + + public abstract class BaseLog : ILog { private readonly NumberSource subfileNumberSource = new NumberSource(0); private readonly bool debug; diff --git a/Logging/Stopwatch.cs b/Logging/Stopwatch.cs index f62f7f63..830b49a9 100644 --- a/Logging/Stopwatch.cs +++ b/Logging/Stopwatch.cs @@ -5,25 +5,25 @@ namespace Logging public class Stopwatch { private readonly DateTime start = DateTime.UtcNow; - private readonly BaseLog log; + private readonly ILog log; private readonly string name; private readonly bool debug; - private Stopwatch(BaseLog log, string name, bool debug) + private Stopwatch(ILog log, string name, bool debug) { this.log = log; this.name = name; this.debug = debug; } - public static void Measure(BaseLog log, string name, Action action, bool debug = false) + public static void Measure(ILog log, string name, Action action, bool debug = false) { var sw = Begin(log, name, debug); action(); sw.End(); } - public static T Measure(BaseLog log, string name, Func action, bool debug = false) + public static T Measure(ILog log, string name, Func action, bool debug = false) { var sw = Begin(log, name, debug); var result = action(); @@ -31,22 +31,22 @@ namespace Logging return result; } - public static Stopwatch Begin(BaseLog log) + public static Stopwatch Begin(ILog log) { return Begin(log, ""); } - public static Stopwatch Begin(BaseLog log, string name) + public static Stopwatch Begin(ILog log, string name) { return Begin(log, name, false); } - public static Stopwatch Begin(BaseLog log, bool debug) + public static Stopwatch Begin(ILog log, bool debug) { return Begin(log, "", debug); } - public static Stopwatch Begin(BaseLog log, string name, bool debug) + public static Stopwatch Begin(ILog log, string name, bool debug) { return new Stopwatch(log, name, debug); } diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 16dbb662..ecc4f581 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -14,7 +14,6 @@ -