From 83d184177acc78932b73c677ee7967dd9188fdaf Mon Sep 17 00:00:00 2001 From: benbierens Date: Mon, 11 Sep 2023 11:59:33 +0200 Subject: [PATCH] Moving all codex details to CodexPlugin --- .../Codex => CodexPlugin}/CodexAccess.cs | 5 +- .../Codex => CodexPlugin}/CodexApiTypes.cs | 2 +- .../CodexContainerRecipe.cs | 67 ++-- .../Codex => CodexPlugin}/CodexDeployment.cs | 15 +- .../Codex => CodexPlugin}/CodexLogLevel.cs | 2 +- CodexPlugin/CodexNodeFactory.cs | 29 ++ .../CodexNodeGroup.cs | 18 +- CodexPlugin/CodexPlugin.csproj | 28 ++ {DistTestCore => CodexPlugin}/CodexSetup.cs | 50 ++- CodexPlugin/CodexStarter.cs | 156 ++++++++ .../CodexStartupConfig.cs | 10 +- CodexPlugin/DistTestExtensions.cs | 28 ++ CodexPlugin/GethStarter.cs | 88 +++++ .../CodexContractsContainerConfig.cs | 16 + .../CodexContractsContainerRecipe.cs | 25 ++ .../Marketplace/CodexContractsStarter.cs | 103 ++++++ .../Marketplace/ContainerInfoExtractor.cs | 149 ++++++++ .../Marketplace/GethBootstrapNodeInfo.cs | 42 +++ .../Marketplace/GethBootstrapNodeStarter.cs | 40 +++ .../Marketplace/GethCompanionNodeInfo.cs | 38 ++ .../Marketplace/GethCompanionNodeStarter.cs | 77 ++++ .../Marketplace/GethContainerRecipe.cs | 73 ++++ CodexPlugin/Marketplace/GethStartResult.cs | 19 + CodexPlugin/Marketplace/GethStartupConfig.cs | 18 + CodexPlugin/Marketplace/MarketplaceAccess.cs | 243 +++++++++++++ .../Marketplace/MarketplaceAccessFactory.cs | 41 +++ .../Marketplace/MarketplaceInitialConfig.cs | 17 + CodexPlugin/Marketplace/MarketplaceNetwork.cs | 21 ++ CodexPlugin/Metrics/GrafanaContainerRecipe.cs | 25 ++ CodexPlugin/Metrics/MetricsAccess.cs | 81 +++++ CodexPlugin/Metrics/MetricsAccessFactory.cs | 35 ++ CodexPlugin/Metrics/MetricsDownloader.cs | 80 +++++ CodexPlugin/Metrics/MetricsMode.cs | 9 + CodexPlugin/Metrics/MetricsQuery.cs | 198 +++++++++++ .../Metrics/PrometheusContainerRecipe.cs | 18 + .../Metrics/PrometheusStartupConfig.cs | 12 + .../Metrics/dashboard.json | 0 .../OnlineCodexNode.cs | 69 ++-- DistTestCore/AutoBootstrapDistTest.cs | 38 +- DistTestCore/CodexNodeFactory.cs | 32 -- DistTestCore/CodexStarter.cs | 158 -------- DistTestCore/Configuration.cs | 19 +- DistTestCore/DistTest.cs | 172 +++++---- DistTestCore/DistTestCore.csproj | 8 - DistTestCore/GethStarter.cs | 88 ----- DistTestCore/GrafanaStarter.cs | 210 ++++++----- .../Helpers/FullConnectivityHelper.cs | 336 +++++++++--------- .../Helpers/PeerConnectionTestHelpers.cs | 122 +++---- .../Helpers/PeerDownloadTestHelpers.cs | 154 ++++---- .../CodexContractsContainerConfig.cs | 16 - .../CodexContractsContainerRecipe.cs | 25 -- .../Marketplace/CodexContractsStarter.cs | 103 ------ .../Marketplace/ContainerInfoExtractor.cs | 149 -------- .../Marketplace/GethBootstrapNodeInfo.cs | 42 --- .../Marketplace/GethBootstrapNodeStarter.cs | 40 --- .../Marketplace/GethCompanionNodeInfo.cs | 38 -- .../Marketplace/GethCompanionNodeStarter.cs | 77 ---- .../Marketplace/GethContainerRecipe.cs | 73 ---- DistTestCore/Marketplace/GethStartResult.cs | 19 - DistTestCore/Marketplace/GethStartupConfig.cs | 18 - DistTestCore/Marketplace/MarketplaceAccess.cs | 243 ------------- .../Marketplace/MarketplaceAccessFactory.cs | 41 --- .../Marketplace/MarketplaceInitialConfig.cs | 17 - .../Marketplace/MarketplaceNetwork.cs | 21 -- .../Metrics/GrafanaContainerRecipe.cs | 25 -- DistTestCore/Metrics/MetricsAccess.cs | 81 ----- DistTestCore/Metrics/MetricsAccessFactory.cs | 35 -- DistTestCore/Metrics/MetricsDownloader.cs | 80 ----- DistTestCore/Metrics/MetricsMode.cs | 9 - DistTestCore/Metrics/MetricsQuery.cs | 198 ----------- .../Metrics/PrometheusContainerRecipe.cs | 18 - .../Metrics/PrometheusStartupConfig.cs | 12 - DistTestCore/PrometheusStarter.cs | 61 ++-- DistTestCore/TestLifecycle.cs | 53 ++- Tests/BasicTests/ContinuousSubstitute.cs | 252 ------------- Tests/BasicTests/ExampleTests.cs | 86 ----- Tests/BasicTests/NetworkIsolationTest.cs | 46 --- Tests/BasicTests/OneClientTests.cs | 41 --- Tests/BasicTests/ThreeClientTest.cs | 25 -- Tests/BasicTests/TwoClientTests.cs | 7 +- .../FullyConnectedDownloadTests.cs | 42 --- .../LayeredDiscoveryTests.cs | 52 --- .../PeerDiscoveryTests/PeerDiscoveryTests.cs | 51 --- Tests/Tests.csproj | 1 + cs-codex-dist-testing.sln | 12 +- 85 files changed, 2414 insertions(+), 2979 deletions(-) rename {DistTestCore/Codex => CodexPlugin}/CodexAccess.cs (98%) rename {DistTestCore/Codex => CodexPlugin}/CodexApiTypes.cs (99%) rename {DistTestCore/Codex => CodexPlugin}/CodexContainerRecipe.cs (62%) rename {DistTestCore/Codex => CodexPlugin}/CodexDeployment.cs (78%) rename {DistTestCore/Codex => CodexPlugin}/CodexLogLevel.cs (78%) create mode 100644 CodexPlugin/CodexNodeFactory.cs rename {DistTestCore => CodexPlugin}/CodexNodeGroup.cs (80%) create mode 100644 CodexPlugin/CodexPlugin.csproj rename {DistTestCore => CodexPlugin}/CodexSetup.cs (66%) create mode 100644 CodexPlugin/CodexStarter.cs rename {DistTestCore/Codex => CodexPlugin}/CodexStartupConfig.cs (70%) create mode 100644 CodexPlugin/DistTestExtensions.cs create mode 100644 CodexPlugin/GethStarter.cs create mode 100644 CodexPlugin/Marketplace/CodexContractsContainerConfig.cs create mode 100644 CodexPlugin/Marketplace/CodexContractsContainerRecipe.cs create mode 100644 CodexPlugin/Marketplace/CodexContractsStarter.cs create mode 100644 CodexPlugin/Marketplace/ContainerInfoExtractor.cs create mode 100644 CodexPlugin/Marketplace/GethBootstrapNodeInfo.cs create mode 100644 CodexPlugin/Marketplace/GethBootstrapNodeStarter.cs create mode 100644 CodexPlugin/Marketplace/GethCompanionNodeInfo.cs create mode 100644 CodexPlugin/Marketplace/GethCompanionNodeStarter.cs create mode 100644 CodexPlugin/Marketplace/GethContainerRecipe.cs create mode 100644 CodexPlugin/Marketplace/GethStartResult.cs create mode 100644 CodexPlugin/Marketplace/GethStartupConfig.cs create mode 100644 CodexPlugin/Marketplace/MarketplaceAccess.cs create mode 100644 CodexPlugin/Marketplace/MarketplaceAccessFactory.cs create mode 100644 CodexPlugin/Marketplace/MarketplaceInitialConfig.cs create mode 100644 CodexPlugin/Marketplace/MarketplaceNetwork.cs create mode 100644 CodexPlugin/Metrics/GrafanaContainerRecipe.cs create mode 100644 CodexPlugin/Metrics/MetricsAccess.cs create mode 100644 CodexPlugin/Metrics/MetricsAccessFactory.cs create mode 100644 CodexPlugin/Metrics/MetricsDownloader.cs create mode 100644 CodexPlugin/Metrics/MetricsMode.cs create mode 100644 CodexPlugin/Metrics/MetricsQuery.cs create mode 100644 CodexPlugin/Metrics/PrometheusContainerRecipe.cs create mode 100644 CodexPlugin/Metrics/PrometheusStartupConfig.cs rename {DistTestCore => CodexPlugin}/Metrics/dashboard.json (100%) rename {DistTestCore => CodexPlugin}/OnlineCodexNode.cs (69%) delete mode 100644 DistTestCore/CodexNodeFactory.cs delete mode 100644 DistTestCore/CodexStarter.cs delete mode 100644 DistTestCore/GethStarter.cs delete mode 100644 DistTestCore/Marketplace/CodexContractsContainerConfig.cs delete mode 100644 DistTestCore/Marketplace/CodexContractsContainerRecipe.cs delete mode 100644 DistTestCore/Marketplace/CodexContractsStarter.cs delete mode 100644 DistTestCore/Marketplace/ContainerInfoExtractor.cs delete mode 100644 DistTestCore/Marketplace/GethBootstrapNodeInfo.cs delete mode 100644 DistTestCore/Marketplace/GethBootstrapNodeStarter.cs delete mode 100644 DistTestCore/Marketplace/GethCompanionNodeInfo.cs delete mode 100644 DistTestCore/Marketplace/GethCompanionNodeStarter.cs delete mode 100644 DistTestCore/Marketplace/GethContainerRecipe.cs delete mode 100644 DistTestCore/Marketplace/GethStartResult.cs delete mode 100644 DistTestCore/Marketplace/GethStartupConfig.cs delete mode 100644 DistTestCore/Marketplace/MarketplaceAccess.cs delete mode 100644 DistTestCore/Marketplace/MarketplaceAccessFactory.cs delete mode 100644 DistTestCore/Marketplace/MarketplaceInitialConfig.cs delete mode 100644 DistTestCore/Marketplace/MarketplaceNetwork.cs delete mode 100644 DistTestCore/Metrics/GrafanaContainerRecipe.cs delete mode 100644 DistTestCore/Metrics/MetricsAccess.cs delete mode 100644 DistTestCore/Metrics/MetricsAccessFactory.cs delete mode 100644 DistTestCore/Metrics/MetricsDownloader.cs delete mode 100644 DistTestCore/Metrics/MetricsMode.cs delete mode 100644 DistTestCore/Metrics/MetricsQuery.cs delete mode 100644 DistTestCore/Metrics/PrometheusContainerRecipe.cs delete mode 100644 DistTestCore/Metrics/PrometheusStartupConfig.cs delete mode 100644 Tests/BasicTests/ContinuousSubstitute.cs delete mode 100644 Tests/BasicTests/ExampleTests.cs delete mode 100644 Tests/BasicTests/NetworkIsolationTest.cs delete mode 100644 Tests/BasicTests/OneClientTests.cs delete mode 100644 Tests/BasicTests/ThreeClientTest.cs delete mode 100644 Tests/DownloadConnectivityTests/FullyConnectedDownloadTests.cs delete mode 100644 Tests/PeerDiscoveryTests/LayeredDiscoveryTests.cs delete mode 100644 Tests/PeerDiscoveryTests/PeerDiscoveryTests.cs diff --git a/DistTestCore/Codex/CodexAccess.cs b/CodexPlugin/CodexAccess.cs similarity index 98% rename from DistTestCore/Codex/CodexAccess.cs rename to CodexPlugin/CodexAccess.cs index 67f42635..13d971ca 100644 --- a/DistTestCore/Codex/CodexAccess.cs +++ b/CodexPlugin/CodexAccess.cs @@ -1,8 +1,9 @@ -using KubernetesWorkflow; +using DistTestCore; +using KubernetesWorkflow; using Logging; using Utils; -namespace DistTestCore.Codex +namespace CodexPlugin { public class CodexAccess : ILogHandler { diff --git a/DistTestCore/Codex/CodexApiTypes.cs b/CodexPlugin/CodexApiTypes.cs similarity index 99% rename from DistTestCore/Codex/CodexApiTypes.cs rename to CodexPlugin/CodexApiTypes.cs index 5944b842..127f4374 100644 --- a/DistTestCore/Codex/CodexApiTypes.cs +++ b/CodexPlugin/CodexApiTypes.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace DistTestCore.Codex +namespace CodexPlugin { public class CodexDebugResponse { diff --git a/DistTestCore/Codex/CodexContainerRecipe.cs b/CodexPlugin/CodexContainerRecipe.cs similarity index 62% rename from DistTestCore/Codex/CodexContainerRecipe.cs rename to CodexPlugin/CodexContainerRecipe.cs index c928b3ea..1f7f6890 100644 --- a/DistTestCore/Codex/CodexContainerRecipe.cs +++ b/CodexPlugin/CodexContainerRecipe.cs @@ -1,8 +1,9 @@ -using DistTestCore.Marketplace; +//using DistTestCore.Marketplace; +using DistTestCore; using KubernetesWorkflow; using Utils; -namespace DistTestCore.Codex +namespace CodexPlugin { public class CodexContainerRecipe : DefaultContainerRecipe { @@ -66,36 +67,36 @@ namespace DistTestCore.Codex { AddEnvVar("CODEX_BLOCK_MN", config.BlockMaintenanceNumber.ToString()!); } - if (config.MetricsMode != Metrics.MetricsMode.None) - { - var metricsPort = AddInternalPort(MetricsPortTag); - AddEnvVar("CODEX_METRICS", "true"); - AddEnvVar("CODEX_METRICS_ADDRESS", "0.0.0.0"); - AddEnvVar("CODEX_METRICS_PORT", metricsPort); - AddPodAnnotation("prometheus.io/scrape", "true"); - AddPodAnnotation("prometheus.io/port", metricsPort.Number.ToString()); - } + //if (config.MetricsMode != Metrics.MetricsMode.None) + //{ + // var metricsPort = AddInternalPort(MetricsPortTag); + // AddEnvVar("CODEX_METRICS", "true"); + // AddEnvVar("CODEX_METRICS_ADDRESS", "0.0.0.0"); + // AddEnvVar("CODEX_METRICS_PORT", metricsPort); + // AddPodAnnotation("prometheus.io/scrape", "true"); + // AddPodAnnotation("prometheus.io/port", metricsPort.Number.ToString()); + //} - if (config.MarketplaceConfig != null) - { - var gethConfig = startupConfig.Get(); - var companionNode = gethConfig.CompanionNode; - var companionNodeAccount = companionNode.Accounts[GetAccountIndex(config.MarketplaceConfig)]; - Additional(companionNodeAccount); + //if (config.MarketplaceConfig != null) + //{ + // var gethConfig = startupConfig.Get(); + // var companionNode = gethConfig.CompanionNode; + // var companionNodeAccount = companionNode.Accounts[GetAccountIndex(config.MarketplaceConfig)]; + // Additional(companionNodeAccount); - var ip = companionNode.RunningContainer.Pod.PodInfo.Ip; - var port = companionNode.RunningContainer.Recipe.GetPortByTag(GethContainerRecipe.HttpPortTag).Number; + // var ip = companionNode.RunningContainer.Pod.PodInfo.Ip; + // var port = companionNode.RunningContainer.Recipe.GetPortByTag(GethContainerRecipe.HttpPortTag).Number; - AddEnvVar("CODEX_ETH_PROVIDER", $"ws://{ip}:{port}"); - AddEnvVar("CODEX_ETH_ACCOUNT", companionNodeAccount.Account); - AddEnvVar("CODEX_MARKETPLACE_ADDRESS", gethConfig.MarketplaceNetwork.Marketplace.Address); - AddEnvVar("CODEX_PERSISTENCE", "true"); + // AddEnvVar("CODEX_ETH_PROVIDER", $"ws://{ip}:{port}"); + // AddEnvVar("CODEX_ETH_ACCOUNT", companionNodeAccount.Account); + // AddEnvVar("CODEX_MARKETPLACE_ADDRESS", gethConfig.MarketplaceNetwork.Marketplace.Address); + // AddEnvVar("CODEX_PERSISTENCE", "true"); - if (config.MarketplaceConfig.IsValidator) - { - AddEnvVar("CODEX_VALIDATOR", "true"); - } - } + // if (config.MarketplaceConfig.IsValidator) + // { + // AddEnvVar("CODEX_VALIDATOR", "true"); + // } + //} } private ByteSize GetVolumeCapacity(CodexStartupConfig config) @@ -105,11 +106,11 @@ namespace DistTestCore.Codex return 8.GB().Multiply(1.2); } - private int GetAccountIndex(MarketplaceInitialConfig marketplaceConfig) - { - if (marketplaceConfig.AccountIndexOverride != null) return marketplaceConfig.AccountIndexOverride.Value; - return Index; - } + //private int GetAccountIndex(MarketplaceInitialConfig marketplaceConfig) + //{ + // if (marketplaceConfig.AccountIndexOverride != null) return marketplaceConfig.AccountIndexOverride.Value; + // return Index; + //} private string GetDockerImage() { diff --git a/DistTestCore/Codex/CodexDeployment.cs b/CodexPlugin/CodexDeployment.cs similarity index 78% rename from DistTestCore/Codex/CodexDeployment.cs rename to CodexPlugin/CodexDeployment.cs index 0595a9a1..3bca60b1 100644 --- a/DistTestCore/Codex/CodexDeployment.cs +++ b/CodexPlugin/CodexDeployment.cs @@ -1,23 +1,22 @@ -using DistTestCore.Marketplace; -using KubernetesWorkflow; +using KubernetesWorkflow; -namespace DistTestCore.Codex +namespace CodexPlugin { public class CodexDeployment { - public CodexDeployment(GethStartResult gethStartResult, RunningContainer[] codexContainers, RunningContainer? prometheusContainer, GrafanaStartInfo? grafanaStartInfo, DeploymentMetadata metadata) + public CodexDeployment(/*GethStartResult gethStartResult,*/ RunningContainer[] codexContainers, RunningContainer? prometheusContainer, /*GrafanaStartInfo? grafanaStartInfo,*/ DeploymentMetadata metadata) { - GethStartResult = gethStartResult; + //GethStartResult = gethStartResult; CodexContainers = codexContainers; PrometheusContainer = prometheusContainer; - GrafanaStartInfo = grafanaStartInfo; + //GrafanaStartInfo = grafanaStartInfo; Metadata = metadata; } - public GethStartResult GethStartResult { get; } + //public GethStartResult GethStartResult { get; } public RunningContainer[] CodexContainers { get; } public RunningContainer? PrometheusContainer { get; } - public GrafanaStartInfo? GrafanaStartInfo { get; } + //public GrafanaStartInfo? GrafanaStartInfo { get; } public DeploymentMetadata Metadata { get; } } diff --git a/DistTestCore/Codex/CodexLogLevel.cs b/CodexPlugin/CodexLogLevel.cs similarity index 78% rename from DistTestCore/Codex/CodexLogLevel.cs rename to CodexPlugin/CodexLogLevel.cs index cde0eb7a..a859a0c4 100644 --- a/DistTestCore/Codex/CodexLogLevel.cs +++ b/CodexPlugin/CodexLogLevel.cs @@ -1,4 +1,4 @@ -namespace DistTestCore.Codex +namespace CodexPlugin { public enum CodexLogLevel { diff --git a/CodexPlugin/CodexNodeFactory.cs b/CodexPlugin/CodexNodeFactory.cs new file mode 100644 index 00000000..5e3abbdb --- /dev/null +++ b/CodexPlugin/CodexNodeFactory.cs @@ -0,0 +1,29 @@ + +namespace CodexPlugin +{ + public interface ICodexNodeFactory + { + //OnlineCodexNode CreateOnlineCodexNode(CodexAccess access, CodexNodeGroup group); + } + + public class CodexNodeFactory : ICodexNodeFactory + { + //private readonly TestLifecycle lifecycle; + //private readonly IMetricsAccessFactory metricsAccessFactory; + //private readonly IMarketplaceAccessFactory marketplaceAccessFactory; + + //public CodexNodeFactory(TestLifecycle lifecycle, IMetricsAccessFactory metricsAccessFactory, IMarketplaceAccessFactory marketplaceAccessFactory) + //{ + // this.lifecycle = lifecycle; + // this.metricsAccessFactory = metricsAccessFactory; + // 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); + //} + } +} diff --git a/DistTestCore/CodexNodeGroup.cs b/CodexPlugin/CodexNodeGroup.cs similarity index 80% rename from DistTestCore/CodexNodeGroup.cs rename to CodexPlugin/CodexNodeGroup.cs index 7759ea7e..e783c205 100644 --- a/DistTestCore/CodexNodeGroup.cs +++ b/CodexPlugin/CodexNodeGroup.cs @@ -1,8 +1,7 @@ -using DistTestCore.Codex; -using KubernetesWorkflow; +using KubernetesWorkflow; using System.Collections; -namespace DistTestCore +namespace CodexPlugin { public interface ICodexNodeGroup : IEnumerable { @@ -12,11 +11,11 @@ namespace DistTestCore public class CodexNodeGroup : ICodexNodeGroup { - private readonly TestLifecycle lifecycle; + //private readonly TestLifecycle lifecycle; - public CodexNodeGroup(TestLifecycle lifecycle, CodexSetup setup, RunningContainers[] containers, ICodexNodeFactory codexNodeFactory) + public CodexNodeGroup(/*TestLifecycle lifecycle, */CodexSetup setup, RunningContainers[] containers, ICodexNodeFactory codexNodeFactory) { - this.lifecycle = lifecycle; + //this.lifecycle = lifecycle; Setup = setup; Containers = containers; Nodes = containers.Containers().Select(c => CreateOnlineCodexNode(c, codexNodeFactory)).ToArray(); @@ -33,7 +32,7 @@ namespace DistTestCore public ICodexSetup BringOffline() { - lifecycle.CodexStarter.BringOffline(this); + //lifecycle.CodexStarter.BringOffline(this); var result = Setup; // Clear everything. Prevent accidental use. @@ -81,8 +80,9 @@ namespace DistTestCore private OnlineCodexNode CreateOnlineCodexNode(RunningContainer c, ICodexNodeFactory factory) { - var access = new CodexAccess(lifecycle.Log, c, lifecycle.TimeSet, lifecycle.Configuration.GetAddress(c)); - return factory.CreateOnlineCodexNode(access, this); + //var access = new CodexAccess(lifecycle.Log, c, lifecycle.TimeSet, lifecycle.Configuration.GetAddress(c)); + //return factory.CreateOnlineCodexNode(access, this); + return null!; } } } diff --git a/CodexPlugin/CodexPlugin.csproj b/CodexPlugin/CodexPlugin.csproj new file mode 100644 index 00000000..dc720d57 --- /dev/null +++ b/CodexPlugin/CodexPlugin.csproj @@ -0,0 +1,28 @@ + + + + net7.0 + enable + enable + + + + + + + + + Never + + + + + + + + + + + + + diff --git a/DistTestCore/CodexSetup.cs b/CodexPlugin/CodexSetup.cs similarity index 66% rename from DistTestCore/CodexSetup.cs rename to CodexPlugin/CodexSetup.cs index f2ec51e3..7602acab 100644 --- a/DistTestCore/CodexSetup.cs +++ b/CodexPlugin/CodexSetup.cs @@ -1,9 +1,7 @@ -using DistTestCore.Codex; -using DistTestCore.Marketplace; -using KubernetesWorkflow; +using KubernetesWorkflow; using Utils; -namespace DistTestCore +namespace CodexPlugin { public interface ICodexSetup { @@ -14,10 +12,10 @@ namespace DistTestCore ICodexSetup WithBlockTTL(TimeSpan duration); ICodexSetup WithBlockMaintenanceInterval(TimeSpan duration); ICodexSetup WithBlockMaintenanceNumber(int numberOfBlocks); - ICodexSetup EnableMetrics(); - ICodexSetup EnableMarketplace(TestToken initialBalance); - ICodexSetup EnableMarketplace(TestToken initialBalance, Ether initialEther); - ICodexSetup EnableMarketplace(TestToken initialBalance, Ether initialEther, bool isValidator); + //ICodexSetup EnableMetrics(); + //ICodexSetup EnableMarketplace(TestToken initialBalance); + //ICodexSetup EnableMarketplace(TestToken initialBalance, Ether initialEther); + //ICodexSetup EnableMarketplace(TestToken initialBalance, Ether initialEther, bool isValidator); } public class CodexSetup : CodexStartupConfig, ICodexSetup @@ -72,27 +70,27 @@ namespace DistTestCore return this; } - public ICodexSetup EnableMetrics() - { - MetricsMode = Metrics.MetricsMode.Record; - return this; - } + //public ICodexSetup EnableMetrics() + //{ + // MetricsMode = Metrics.MetricsMode.Record; + // return this; + //} - public ICodexSetup EnableMarketplace(TestToken initialBalance) - { - return EnableMarketplace(initialBalance, 1000.Eth()); - } + //public ICodexSetup EnableMarketplace(TestToken initialBalance) + //{ + // return EnableMarketplace(initialBalance, 1000.Eth()); + //} - public ICodexSetup EnableMarketplace(TestToken initialBalance, Ether initialEther) - { - return EnableMarketplace(initialBalance, initialEther, false); - } + //public ICodexSetup EnableMarketplace(TestToken initialBalance, Ether initialEther) + //{ + // return EnableMarketplace(initialBalance, initialEther, false); + //} - public ICodexSetup EnableMarketplace(TestToken initialBalance, Ether initialEther, bool isValidator) - { - MarketplaceConfig = new MarketplaceInitialConfig(initialEther, initialBalance, isValidator); - return this; - } + //public ICodexSetup EnableMarketplace(TestToken initialBalance, Ether initialEther, bool isValidator) + //{ + // MarketplaceConfig = new MarketplaceInitialConfig(initialEther, initialBalance, isValidator); + // return this; + //} public string Describe() { diff --git a/CodexPlugin/CodexStarter.cs b/CodexPlugin/CodexStarter.cs new file mode 100644 index 00000000..dcd99083 --- /dev/null +++ b/CodexPlugin/CodexStarter.cs @@ -0,0 +1,156 @@ +using KubernetesWorkflow; +using Logging; + +namespace CodexPlugin +{ + public class CodexStarter //: BaseStarter + { + //public CodexStarter(TestLifecycle lifecycle) + // : base(lifecycle) + //{ + //} + + public List RunningGroups { get; } = new List(); + + public ICodexNodeGroup BringOnline(CodexSetup codexSetup) + { + //LogSeparator(); + //LogStart($"Starting {codexSetup.Describe()}..."); + //var gethStartResult = lifecycle.GethStarter.BringOnlineMarketplaceFor(codexSetup); + + //var startupConfig = CreateStartupConfig(gethStartResult, codexSetup); + + //var containers = StartCodexContainers(startupConfig, codexSetup.NumberOfNodes, codexSetup.Location); + + //var metricAccessFactory = CollectMetrics(codexSetup, containers); + + //var codexNodeFactory = new CodexNodeFactory(lifecycle, metricAccessFactory, gethStartResult.MarketplaceAccessFactory); + + //var group = 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; + return null!; + } + + public void BringOffline(CodexNodeGroup group) + { + //LogStart($"Stopping {group.Describe()}..."); + //var workflow = CreateWorkflow(); + //foreach (var c in group.Containers) + //{ + // StopCrashWatcher(c); + // workflow.Stop(c); + //} + //RunningGroups.Remove(group); + //LogEnd("Stopped."); + } + + public void DeleteAllResources() + { + //var workflow = CreateWorkflow(); + //workflow.DeleteTestResources(); + + //RunningGroups.Clear(); + } + + public void DownloadLog(RunningContainer container, ILogHandler logHandler, int? tailLines) + { + //var workflow = CreateWorkflow(); + //workflow.DownloadContainerLog(container, logHandler, tailLines); + } + + //private IMetricsAccessFactory CollectMetrics(CodexSetup codexSetup, RunningContainers[] containers) + //{ + // if (codexSetup.MetricsMode == MetricsMode.None) return new MetricsUnavailableAccessFactory(); + + // var runningContainers = lifecycle.PrometheusStarter.CollectMetricsFor(containers); + + // if (codexSetup.MetricsMode == MetricsMode.Dashboard) + // { + // lifecycle.GrafanaStarter.StartDashboard(runningContainers.Containers.First(), codexSetup); + // } + + // 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 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 CodexNodeGroup CreateCodexGroup(CodexSetup codexSetup, RunningContainers[] runningContainers, CodexNodeFactory codexNodeFactory) + //{ + // var group = new CodexNodeGroup(lifecycle, codexSetup, runningContainers, codexNodeFactory); + // RunningGroups.Add(group); + + // try + // { + // Stopwatch.Measure(lifecycle.Log, "EnsureOnline", group.EnsureOnline, debug: true); + // } + // catch + // { + // CodexNodesNotOnline(runningContainers); + // throw; + // } + + // return group; + //} + + //private void CodexNodesNotOnline(RunningContainers[] runningContainers) + //{ + // Log("Codex nodes failed to start"); + // foreach (var container in runningContainers.Containers()) lifecycle.DownloadLog(container); + //} + + //private StartupWorkflow CreateWorkflow() + //{ + // return lifecycle.WorkflowCreator.CreateWorkflow(); + //} + + //private void LogSeparator() + //{ + // 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) + // { + // c.CrashWatcher?.Stop(); + // } + //} + } +} diff --git a/DistTestCore/Codex/CodexStartupConfig.cs b/CodexPlugin/CodexStartupConfig.cs similarity index 70% rename from DistTestCore/Codex/CodexStartupConfig.cs rename to CodexPlugin/CodexStartupConfig.cs index 36e47570..85639590 100644 --- a/DistTestCore/Codex/CodexStartupConfig.cs +++ b/CodexPlugin/CodexStartupConfig.cs @@ -1,9 +1,7 @@ -using DistTestCore.Marketplace; -using DistTestCore.Metrics; -using KubernetesWorkflow; +using KubernetesWorkflow; using Utils; -namespace DistTestCore.Codex +namespace CodexPlugin { public class CodexStartupConfig { @@ -16,8 +14,8 @@ namespace DistTestCore.Codex public Location Location { get; set; } public CodexLogLevel LogLevel { get; } public ByteSize? StorageQuota { get; set; } - public MetricsMode MetricsMode { get; set; } - public MarketplaceInitialConfig? MarketplaceConfig { get; set; } + //public MetricsMode MetricsMode { get; set; } + //public MarketplaceInitialConfig? MarketplaceConfig { get; set; } public string? BootstrapSpr { get; set; } public int? BlockTTL { get; set; } public TimeSpan? BlockMaintenanceInterval { get; set; } diff --git a/CodexPlugin/DistTestExtensions.cs b/CodexPlugin/DistTestExtensions.cs new file mode 100644 index 00000000..e6996278 --- /dev/null +++ b/CodexPlugin/DistTestExtensions.cs @@ -0,0 +1,28 @@ +using DistTestCore; +using KubernetesWorkflow; + +namespace CodexPlugin +{ + public static class DistTestExtensions + { + public static RunningContainers StartCodexNodes(this DistTest distTest, int number, Action setup) + { + return null!; + } + + public static ICodexNodeGroup WrapCodexContainers(this DistTest distTest, RunningContainers containers) + { + return null!; + } + + public static IOnlineCodexNode SetupCodexNode(this DistTest distTest, Action setup) + { + return null!; + } + + public static ICodexNodeGroup SetupCodexNodes(this DistTest distTest, int number) + { + return null!; + } + } +} diff --git a/CodexPlugin/GethStarter.cs b/CodexPlugin/GethStarter.cs new file mode 100644 index 00000000..f6381b39 --- /dev/null +++ b/CodexPlugin/GethStarter.cs @@ -0,0 +1,88 @@ +//using DistTestCore.Marketplace; + +//namespace CodexPlugin +//{ +// public class GethStarter : BaseStarter +// { +// private readonly MarketplaceNetworkCache marketplaceNetworkCache; +// private readonly GethCompanionNodeStarter companionNodeStarter; + +// public GethStarter(TestLifecycle lifecycle) +// : base(lifecycle) +// { +// marketplaceNetworkCache = new MarketplaceNetworkCache( +// new GethBootstrapNodeStarter(lifecycle), +// new CodexContractsStarter(lifecycle)); +// companionNodeStarter = new GethCompanionNodeStarter(lifecycle); +// } + +// public GethStartResult BringOnlineMarketplaceFor(CodexSetup codexSetup) +// { +// if (codexSetup.MarketplaceConfig == null) return CreateMarketplaceUnavailableResult(); + +// var marketplaceNetwork = marketplaceNetworkCache.Get(); +// var companionNode = StartCompanionNode(codexSetup, marketplaceNetwork); + +// LogStart("Setting up initial balance..."); +// TransferInitialBalance(marketplaceNetwork, codexSetup.MarketplaceConfig, companionNode); +// LogEnd($"Initial balance of {codexSetup.MarketplaceConfig.InitialTestTokens} set for {codexSetup.NumberOfNodes} nodes."); + +// return CreateGethStartResult(marketplaceNetwork, companionNode); +// } + +// private void TransferInitialBalance(MarketplaceNetwork marketplaceNetwork, MarketplaceInitialConfig marketplaceConfig, GethCompanionNodeInfo companionNode) +// { +// if (marketplaceConfig.InitialTestTokens.Amount == 0) return; + +// var interaction = marketplaceNetwork.StartInteraction(lifecycle); +// var tokenAddress = marketplaceNetwork.Marketplace.TokenAddress; + +// var accounts = companionNode.Accounts.Select(a => a.Account).ToArray(); +// interaction.MintTestTokens(accounts, marketplaceConfig.InitialTestTokens.Amount, tokenAddress); +// } + +// private GethStartResult CreateGethStartResult(MarketplaceNetwork marketplaceNetwork, GethCompanionNodeInfo companionNode) +// { +// return new GethStartResult(CreateMarketplaceAccessFactory(marketplaceNetwork), marketplaceNetwork, companionNode); +// } + +// private GethStartResult CreateMarketplaceUnavailableResult() +// { +// return new GethStartResult(new MarketplaceUnavailableAccessFactory(), null!, null!); +// } + +// private IMarketplaceAccessFactory CreateMarketplaceAccessFactory(MarketplaceNetwork marketplaceNetwork) +// { +// return new GethMarketplaceAccessFactory(lifecycle, marketplaceNetwork); +// } + +// private GethCompanionNodeInfo StartCompanionNode(CodexSetup codexSetup, MarketplaceNetwork marketplaceNetwork) +// { +// return companionNodeStarter.StartCompanionNodeFor(codexSetup, marketplaceNetwork); +// } +// } + +// public class MarketplaceNetworkCache +// { +// private readonly GethBootstrapNodeStarter bootstrapNodeStarter; +// private readonly CodexContractsStarter codexContractsStarter; +// private MarketplaceNetwork? network; + +// public MarketplaceNetworkCache(GethBootstrapNodeStarter bootstrapNodeStarter, CodexContractsStarter codexContractsStarter) +// { +// this.bootstrapNodeStarter = bootstrapNodeStarter; +// this.codexContractsStarter = codexContractsStarter; +// } + +// public MarketplaceNetwork Get() +// { +// if (network == null) +// { +// var bootstrapInfo = bootstrapNodeStarter.StartGethBootstrapNode(); +// var marketplaceInfo = codexContractsStarter.Start(bootstrapInfo); +// network = new MarketplaceNetwork(bootstrapInfo, marketplaceInfo ); +// } +// return network; +// } +// } +//} diff --git a/CodexPlugin/Marketplace/CodexContractsContainerConfig.cs b/CodexPlugin/Marketplace/CodexContractsContainerConfig.cs new file mode 100644 index 00000000..f6e9896d --- /dev/null +++ b/CodexPlugin/Marketplace/CodexContractsContainerConfig.cs @@ -0,0 +1,16 @@ +//using KubernetesWorkflow; + +//namespace DistTestCore.Marketplace +//{ +// public class CodexContractsContainerConfig +// { +// public CodexContractsContainerConfig(string bootstrapNodeIp, Port jsonRpcPort) +// { +// BootstrapNodeIp = bootstrapNodeIp; +// JsonRpcPort = jsonRpcPort; +// } + +// public string BootstrapNodeIp { get; } +// public Port JsonRpcPort { get; } +// } +//} diff --git a/CodexPlugin/Marketplace/CodexContractsContainerRecipe.cs b/CodexPlugin/Marketplace/CodexContractsContainerRecipe.cs new file mode 100644 index 00000000..db8e88f4 --- /dev/null +++ b/CodexPlugin/Marketplace/CodexContractsContainerRecipe.cs @@ -0,0 +1,25 @@ +//using KubernetesWorkflow; + +//namespace DistTestCore.Marketplace +//{ +// public class CodexContractsContainerRecipe : DefaultContainerRecipe +// { +// public const string MarketplaceAddressFilename = "/hardhat/deployments/codexdisttestnetwork/Marketplace.json"; +// public const string MarketplaceArtifactFilename = "/hardhat/artifacts/contracts/Marketplace.sol/Marketplace.json"; + +// public override string AppName => "codex-contracts"; +// public override string Image => "codexstorage/codex-contracts-eth:latest-dist-tests"; + +// protected override void InitializeRecipe(StartupConfig startupConfig) +// { +// var config = startupConfig.Get(); + +// var ip = config.BootstrapNodeIp; +// var port = config.JsonRpcPort.Number; + +// AddEnvVar("DISTTEST_NETWORK_URL", $"http://{ip}:{port}"); +// AddEnvVar("HARDHAT_NETWORK", "codexdisttestnetwork"); +// AddEnvVar("KEEP_ALIVE", "1"); +// } +// } +//} diff --git a/CodexPlugin/Marketplace/CodexContractsStarter.cs b/CodexPlugin/Marketplace/CodexContractsStarter.cs new file mode 100644 index 00000000..e09b1f1a --- /dev/null +++ b/CodexPlugin/Marketplace/CodexContractsStarter.cs @@ -0,0 +1,103 @@ +//using KubernetesWorkflow; +//using Utils; + +//namespace DistTestCore.Marketplace +//{ +// public class CodexContractsStarter : BaseStarter +// { + +// public CodexContractsStarter(TestLifecycle lifecycle) +// : base(lifecycle) +// { +// } + +// public MarketplaceInfo Start(GethBootstrapNodeInfo bootstrapNode) +// { +// LogStart("Deploying Codex Marketplace..."); + +// var workflow = lifecycle.WorkflowCreator.CreateWorkflow(); +// var startupConfig = CreateStartupConfig(bootstrapNode.RunningContainers.Containers[0]); + +// var containers = workflow.Start(1, Location.Unspecified, new CodexContractsContainerRecipe(), startupConfig); +// if (containers.Containers.Length != 1) throw new InvalidOperationException("Expected 1 Codex contracts container to be created. Test infra failure."); +// var container = containers.Containers[0]; + +// WaitUntil(() => +// { +// var logHandler = new ContractsReadyLogHandler(Debug); +// workflow.DownloadContainerLog(container, logHandler, null); +// return logHandler.Found; +// }); +// Log("Contracts deployed. Extracting addresses..."); + +// var extractor = new ContainerInfoExtractor(lifecycle.Log, workflow, container); +// var marketplaceAddress = extractor.ExtractMarketplaceAddress(); +// var abi = extractor.ExtractMarketplaceAbi(); + +// var interaction = bootstrapNode.StartInteraction(lifecycle); +// var tokenAddress = interaction.GetTokenAddress(marketplaceAddress); + +// LogEnd("Extract completed. Marketplace deployed."); + +// return new MarketplaceInfo(marketplaceAddress, abi, tokenAddress); +// } + +// private void WaitUntil(Func predicate) +// { +// Time.WaitUntil(predicate, TimeSpan.FromMinutes(3), TimeSpan.FromSeconds(2)); +// } + +// private StartupConfig CreateStartupConfig(RunningContainer bootstrapContainer) +// { +// var startupConfig = new StartupConfig(); +// var contractsConfig = new CodexContractsContainerConfig(bootstrapContainer.Pod.PodInfo.Ip, bootstrapContainer.Recipe.GetPortByTag(GethContainerRecipe.HttpPortTag)); +// startupConfig.Add(contractsConfig); +// return startupConfig; +// } +// } + +// public class MarketplaceInfo +// { +// public MarketplaceInfo(string address, string abi, string tokenAddress) +// { +// Address = address; +// Abi = abi; +// TokenAddress = tokenAddress; +// } + +// public string Address { get; } +// public string Abi { get; } +// public string TokenAddress { get; } +// } + +// public class ContractsReadyLogHandler : LogHandler +// { +// // Log should contain 'Compiled 15 Solidity files successfully' at some point. +// private const string RequiredCompiledString = "Solidity files successfully"; +// // When script is done, it prints the ready-string. +// private const string ReadyString = "Done! Sleeping indefinitely..."; +// private readonly Action debug; + +// public ContractsReadyLogHandler(Action debug) +// { +// this.debug = debug; +// debug($"Looking for '{RequiredCompiledString}' and '{ReadyString}' in container logs..."); +// } + +// public bool SeenCompileString { get; private set; } +// public bool Found { get; private set; } + +// protected override void ProcessLine(string line) +// { +// debug(line); +// if (line.Contains(RequiredCompiledString)) SeenCompileString = true; +// if (line.Contains(ReadyString)) +// { +// if (!SeenCompileString) throw new Exception("CodexContracts deployment failed. " + +// "Solidity files not compiled before process exited."); + +// Found = true; +// } +// } +// } +//} diff --git a/CodexPlugin/Marketplace/ContainerInfoExtractor.cs b/CodexPlugin/Marketplace/ContainerInfoExtractor.cs new file mode 100644 index 00000000..ced47e12 --- /dev/null +++ b/CodexPlugin/Marketplace/ContainerInfoExtractor.cs @@ -0,0 +1,149 @@ +//using KubernetesWorkflow; +//using Logging; +//using Newtonsoft.Json; +//using Newtonsoft.Json.Linq; +//using Utils; + +//namespace DistTestCore.Marketplace +//{ +// public class ContainerInfoExtractor +// { +// private readonly BaseLog log; +// private readonly StartupWorkflow workflow; +// private readonly RunningContainer container; + +// public ContainerInfoExtractor(BaseLog log, StartupWorkflow workflow, RunningContainer container) +// { +// this.log = log; +// this.workflow = workflow; +// this.container = container; +// } + +// public AllGethAccounts ExtractAccounts() +// { +// log.Debug(); +// var accountsCsv = Retry(() => FetchAccountsCsv()); +// if (string.IsNullOrEmpty(accountsCsv)) throw new InvalidOperationException("Unable to fetch accounts.csv for geth node. Test infra failure."); + +// var lines = accountsCsv.Split('\n'); +// return new AllGethAccounts(lines.Select(ParseLineToAccount).ToArray()); +// } + +// public string ExtractPubKey() +// { +// log.Debug(); +// var pubKey = Retry(FetchPubKey); +// if (string.IsNullOrEmpty(pubKey)) throw new InvalidOperationException("Unable to fetch enode from geth node. Test infra failure."); + +// return pubKey; +// } + +// public string ExtractMarketplaceAddress() +// { +// log.Debug(); +// var marketplaceAddress = Retry(FetchMarketplaceAddress); +// if (string.IsNullOrEmpty(marketplaceAddress)) throw new InvalidOperationException("Unable to fetch marketplace account from codex-contracts node. Test infra failure."); + +// return marketplaceAddress; +// } + +// public string ExtractMarketplaceAbi() +// { +// log.Debug(); +// var marketplaceAbi = Retry(FetchMarketplaceAbi); +// if (string.IsNullOrEmpty(marketplaceAbi)) throw new InvalidOperationException("Unable to fetch marketplace artifacts from codex-contracts node. Test infra failure."); + +// return marketplaceAbi; +// } + +// private string FetchAccountsCsv() +// { +// return workflow.ExecuteCommand(container, "cat", GethContainerRecipe.AccountsFilename); +// } + +// private string FetchMarketplaceAddress() +// { +// var json = workflow.ExecuteCommand(container, "cat", CodexContractsContainerRecipe.MarketplaceAddressFilename); +// var marketplace = JsonConvert.DeserializeObject(json); +// return marketplace!.address; +// } + +// private string FetchMarketplaceAbi() +// { +// var json = workflow.ExecuteCommand(container, "cat", CodexContractsContainerRecipe.MarketplaceArtifactFilename); + +// var artifact = JObject.Parse(json); +// var abi = artifact["abi"]; +// return abi!.ToString(Formatting.None); +// } + +// private string FetchPubKey() +// { +// var enodeFinder = new PubKeyFinder(s => log.Debug(s)); +// workflow.DownloadContainerLog(container, enodeFinder, null); +// return enodeFinder.GetPubKey(); +// } + +// private GethAccount ParseLineToAccount(string l) +// { +// var tokens = l.Replace("\r", "").Split(','); +// if (tokens.Length != 2) throw new InvalidOperationException(); +// var account = tokens[0]; +// var privateKey = tokens[1]; +// return new GethAccount(account, privateKey); +// } + +// private static string Retry(Func fetch) +// { +// return Time.Retry(fetch, nameof(ContainerInfoExtractor)); +// } +// } + +// public class PubKeyFinder : LogHandler, ILogHandler +// { +// private const string openTag = "self=enode://"; +// private const string openTagQuote = "self=\"enode://"; +// private readonly Action debug; +// private string pubKey = string.Empty; + +// public PubKeyFinder(Action debug) +// { +// this.debug = debug; +// debug($"Looking for '{openTag}' in container logs..."); +// } + +// public string GetPubKey() +// { +// if (string.IsNullOrEmpty(pubKey)) throw new Exception("Not found yet exception."); +// return pubKey; +// } + +// protected override void ProcessLine(string line) +// { +// debug(line); +// if (line.Contains(openTag)) +// { +// ExtractPubKey(openTag, line); +// } +// else if (line.Contains(openTagQuote)) +// { +// ExtractPubKey(openTagQuote, line); +// } +// } + +// private void ExtractPubKey(string tag, string line) +// { +// var openIndex = line.IndexOf(tag) + tag.Length; +// var closeIndex = line.IndexOf("@"); + +// pubKey = line.Substring( +// startIndex: openIndex, +// length: closeIndex - openIndex); +// } +// } + +// public class MarketplaceJson +// { +// public string address { get; set; } = string.Empty; +// } +//} diff --git a/CodexPlugin/Marketplace/GethBootstrapNodeInfo.cs b/CodexPlugin/Marketplace/GethBootstrapNodeInfo.cs new file mode 100644 index 00000000..3e84decc --- /dev/null +++ b/CodexPlugin/Marketplace/GethBootstrapNodeInfo.cs @@ -0,0 +1,42 @@ +//using KubernetesWorkflow; +//using NethereumWorkflow; + +//namespace DistTestCore.Marketplace +//{ +// public class GethBootstrapNodeInfo +// { +// public GethBootstrapNodeInfo(RunningContainers runningContainers, AllGethAccounts allAccounts, string pubKey, Port discoveryPort) +// { +// RunningContainers = runningContainers; +// AllAccounts = allAccounts; +// Account = allAccounts.Accounts[0]; +// PubKey = pubKey; +// DiscoveryPort = discoveryPort; +// } + +// public RunningContainers RunningContainers { get; } +// public AllGethAccounts AllAccounts { get; } +// public GethAccount Account { get; } +// public string PubKey { get; } +// public Port DiscoveryPort { get; } + +// public NethereumInteraction StartInteraction(TestLifecycle lifecycle) +// { +// var address = lifecycle.Configuration.GetAddress(RunningContainers.Containers[0]); +// var account = Account; + +// var creator = new NethereumInteractionCreator(lifecycle.Log, address.Host, address.Port, account.PrivateKey); +// return creator.CreateWorkflow(); +// } +// } + +// public class AllGethAccounts +// { +// public GethAccount[] Accounts { get; } + +// public AllGethAccounts(GethAccount[] accounts) +// { +// Accounts = accounts; +// } +// } +//} diff --git a/CodexPlugin/Marketplace/GethBootstrapNodeStarter.cs b/CodexPlugin/Marketplace/GethBootstrapNodeStarter.cs new file mode 100644 index 00000000..b94d041d --- /dev/null +++ b/CodexPlugin/Marketplace/GethBootstrapNodeStarter.cs @@ -0,0 +1,40 @@ +//using KubernetesWorkflow; + +//namespace DistTestCore.Marketplace +//{ +// public class GethBootstrapNodeStarter : BaseStarter +// { +// public GethBootstrapNodeStarter(TestLifecycle lifecycle) +// : base(lifecycle) +// { +// } + +// public GethBootstrapNodeInfo StartGethBootstrapNode() +// { +// LogStart("Starting Geth bootstrap node..."); +// var startupConfig = CreateBootstrapStartupConfig(); + +// var workflow = lifecycle.WorkflowCreator.CreateWorkflow(); +// var containers = workflow.Start(1, Location.Unspecified, new GethContainerRecipe(), startupConfig); +// if (containers.Containers.Length != 1) throw new InvalidOperationException("Expected 1 Geth bootstrap node to be created. Test infra failure."); +// var bootstrapContainer = containers.Containers[0]; + +// var extractor = new ContainerInfoExtractor(lifecycle.Log, workflow, bootstrapContainer); +// var accounts = extractor.ExtractAccounts(); +// var pubKey = extractor.ExtractPubKey(); +// var discoveryPort = bootstrapContainer.Recipe.GetPortByTag(GethContainerRecipe.DiscoveryPortTag); +// var result = new GethBootstrapNodeInfo(containers, accounts, pubKey, discoveryPort); + +// LogEnd($"Geth bootstrap node started with account '{result.Account.Account}'"); + +// return result; +// } + +// private StartupConfig CreateBootstrapStartupConfig() +// { +// var config = new StartupConfig(); +// config.Add(new GethStartupConfig(true, null!, 0, 0)); +// return config; +// } +// } +//} diff --git a/CodexPlugin/Marketplace/GethCompanionNodeInfo.cs b/CodexPlugin/Marketplace/GethCompanionNodeInfo.cs new file mode 100644 index 00000000..30f2e78d --- /dev/null +++ b/CodexPlugin/Marketplace/GethCompanionNodeInfo.cs @@ -0,0 +1,38 @@ +//using KubernetesWorkflow; +//using NethereumWorkflow; + +//namespace DistTestCore.Marketplace +//{ +// public class GethCompanionNodeInfo +// { +// public GethCompanionNodeInfo(RunningContainer runningContainer, GethAccount[] accounts) +// { +// RunningContainer = runningContainer; +// Accounts = accounts; +// } + +// public RunningContainer RunningContainer { get; } +// public GethAccount[] Accounts { get; } + +// public NethereumInteraction StartInteraction(TestLifecycle lifecycle, GethAccount account) +// { +// var address = lifecycle.Configuration.GetAddress(RunningContainer); +// var privateKey = account.PrivateKey; + +// var creator = new NethereumInteractionCreator(lifecycle.Log, address.Host, address.Port, privateKey); +// return creator.CreateWorkflow(); +// } +// } + +// public class GethAccount +// { +// public GethAccount(string account, string privateKey) +// { +// Account = account; +// PrivateKey = privateKey; +// } + +// public string Account { get; } +// public string PrivateKey { get; } +// } +//} diff --git a/CodexPlugin/Marketplace/GethCompanionNodeStarter.cs b/CodexPlugin/Marketplace/GethCompanionNodeStarter.cs new file mode 100644 index 00000000..9c8a303f --- /dev/null +++ b/CodexPlugin/Marketplace/GethCompanionNodeStarter.cs @@ -0,0 +1,77 @@ +//using KubernetesWorkflow; +//using Utils; + +//namespace DistTestCore.Marketplace +//{ +// public class GethCompanionNodeStarter : BaseStarter +// { +// private int companionAccountIndex = 0; + +// public GethCompanionNodeStarter(TestLifecycle lifecycle) +// : base(lifecycle) +// { +// } + +// public GethCompanionNodeInfo StartCompanionNodeFor(CodexSetup codexSetup, MarketplaceNetwork marketplace) +// { +// LogStart($"Initializing companion for {codexSetup.NumberOfNodes} Codex nodes."); + +// var config = CreateCompanionNodeStartupConfig(marketplace.Bootstrap, codexSetup.NumberOfNodes); + +// var workflow = lifecycle.WorkflowCreator.CreateWorkflow(); +// var containers = workflow.Start(1, Location.Unspecified, new GethContainerRecipe(), CreateStartupConfig(config)); +// if (containers.Containers.Length != 1) throw new InvalidOperationException("Expected one Geth companion node to be created. Test infra failure."); +// var container = containers.Containers[0]; + +// var node = CreateCompanionInfo(container, marketplace, config); +// EnsureCompanionNodeIsSynced(node, marketplace); + +// LogEnd($"Initialized one companion node for {codexSetup.NumberOfNodes} Codex nodes. Their accounts: [{string.Join(",", node.Accounts.Select(a => a.Account))}]"); +// return node; +// } + +// private GethCompanionNodeInfo CreateCompanionInfo(RunningContainer container, MarketplaceNetwork marketplace, GethStartupConfig config) +// { +// var accounts = ExtractAccounts(marketplace, config); +// return new GethCompanionNodeInfo(container, accounts); +// } + +// private static GethAccount[] ExtractAccounts(MarketplaceNetwork marketplace, GethStartupConfig config) +// { +// return marketplace.Bootstrap.AllAccounts.Accounts +// .Skip(1 + config.CompanionAccountStartIndex) +// .Take(config.NumberOfCompanionAccounts) +// .ToArray(); +// } + +// private void EnsureCompanionNodeIsSynced(GethCompanionNodeInfo node, MarketplaceNetwork marketplace) +// { +// try +// { +// Time.WaitUntil(() => +// { +// var interaction = node.StartInteraction(lifecycle, node.Accounts.First()); +// return interaction.IsSynced(marketplace.Marketplace.Address, marketplace.Marketplace.Abi); +// }, TimeSpan.FromMinutes(1), TimeSpan.FromSeconds(3)); +// } +// catch (Exception e) +// { +// throw new Exception("Geth companion node did not sync within timeout. Test infra failure.", e); +// } +// } + +// private GethStartupConfig CreateCompanionNodeStartupConfig(GethBootstrapNodeInfo bootstrapNode, int numberOfAccounts) +// { +// var config = new GethStartupConfig(false, bootstrapNode, companionAccountIndex, numberOfAccounts); +// companionAccountIndex += numberOfAccounts; +// return config; +// } + +// private StartupConfig CreateStartupConfig(GethStartupConfig gethConfig) +// { +// var config = new StartupConfig(); +// config.Add(gethConfig); +// return config; +// } +// } +//} diff --git a/CodexPlugin/Marketplace/GethContainerRecipe.cs b/CodexPlugin/Marketplace/GethContainerRecipe.cs new file mode 100644 index 00000000..e5b2f9b4 --- /dev/null +++ b/CodexPlugin/Marketplace/GethContainerRecipe.cs @@ -0,0 +1,73 @@ +//using KubernetesWorkflow; + +//namespace DistTestCore.Marketplace +//{ +// public class GethContainerRecipe : DefaultContainerRecipe +// { +// private const string defaultArgs = "--ipcdisable --syncmode full"; + +// public const string HttpPortTag = "http_port"; +// public const string DiscoveryPortTag = "disc_port"; +// public const string AccountsFilename = "accounts.csv"; + +// public override string AppName => "geth"; +// public override string Image => "codexstorage/dist-tests-geth:latest"; + +// protected override void InitializeRecipe(StartupConfig startupConfig) +// { +// var config = startupConfig.Get(); + +// var args = CreateArgs(config); + +// AddEnvVar("GETH_ARGS", args); +// } + +// private string CreateArgs(GethStartupConfig config) +// { +// var discovery = AddInternalPort(tag: DiscoveryPortTag); + +// if (config.IsBootstrapNode) +// { +// return CreateBootstapArgs(discovery); +// } + +// return CreateCompanionArgs(discovery, config); +// } + +// private string CreateBootstapArgs(Port discovery) +// { +// AddEnvVar("ENABLE_MINER", "1"); +// UnlockAccounts(0, 1); +// var exposedPort = AddExposedPort(tag: HttpPortTag); +// return $"--http.port {exposedPort.Number} --port {discovery.Number} --discovery.port {discovery.Number} {defaultArgs}"; +// } + +// private string CreateCompanionArgs(Port discovery, GethStartupConfig config) +// { +// UnlockAccounts( +// config.CompanionAccountStartIndex + 1, +// config.NumberOfCompanionAccounts); + +// var port = AddInternalPort(); +// var authRpc = AddInternalPort(); +// var httpPort = AddExposedPort(tag: HttpPortTag); + +// var bootPubKey = config.BootstrapNode.PubKey; +// var bootIp = config.BootstrapNode.RunningContainers.Containers[0].Pod.PodInfo.Ip; +// var bootPort = config.BootstrapNode.DiscoveryPort.Number; +// var bootstrapArg = $"--bootnodes enode://{bootPubKey}@{bootIp}:{bootPort} --nat=extip:{bootIp}"; + +// return $"--port {port.Number} --discovery.port {discovery.Number} --authrpc.port {authRpc.Number} --http.addr 0.0.0.0 --http.port {httpPort.Number} --ws --ws.addr 0.0.0.0 --ws.port {httpPort.Number} {bootstrapArg} {defaultArgs}"; +// } + +// private void UnlockAccounts(int startIndex, int numberOfAccounts) +// { +// if (startIndex < 0) throw new ArgumentException(); +// if (numberOfAccounts < 1) throw new ArgumentException(); +// if (startIndex + numberOfAccounts > 1000) throw new ArgumentException("Out of accounts!"); + +// AddEnvVar("UNLOCK_START_INDEX", startIndex.ToString()); +// AddEnvVar("UNLOCK_NUMBER", numberOfAccounts.ToString()); +// } +// } +//} diff --git a/CodexPlugin/Marketplace/GethStartResult.cs b/CodexPlugin/Marketplace/GethStartResult.cs new file mode 100644 index 00000000..f9e10489 --- /dev/null +++ b/CodexPlugin/Marketplace/GethStartResult.cs @@ -0,0 +1,19 @@ +//using Newtonsoft.Json; + +//namespace DistTestCore.Marketplace +//{ +// public class GethStartResult +// { +// public GethStartResult(IMarketplaceAccessFactory marketplaceAccessFactory, MarketplaceNetwork marketplaceNetwork, GethCompanionNodeInfo companionNode) +// { +// MarketplaceAccessFactory = marketplaceAccessFactory; +// MarketplaceNetwork = marketplaceNetwork; +// CompanionNode = companionNode; +// } + +// [JsonIgnore] +// public IMarketplaceAccessFactory MarketplaceAccessFactory { get; } +// public MarketplaceNetwork MarketplaceNetwork { get; } +// public GethCompanionNodeInfo CompanionNode { get; } +// } +//} diff --git a/CodexPlugin/Marketplace/GethStartupConfig.cs b/CodexPlugin/Marketplace/GethStartupConfig.cs new file mode 100644 index 00000000..67ad0d51 --- /dev/null +++ b/CodexPlugin/Marketplace/GethStartupConfig.cs @@ -0,0 +1,18 @@ +//namespace DistTestCore.Marketplace +//{ +// public class GethStartupConfig +// { +// public GethStartupConfig(bool isBootstrapNode, GethBootstrapNodeInfo bootstrapNode, int companionAccountStartIndex, int numberOfCompanionAccounts) +// { +// IsBootstrapNode = isBootstrapNode; +// BootstrapNode = bootstrapNode; +// CompanionAccountStartIndex = companionAccountStartIndex; +// NumberOfCompanionAccounts = numberOfCompanionAccounts; +// } + +// public bool IsBootstrapNode { get; } +// public GethBootstrapNodeInfo BootstrapNode { get; } +// public int CompanionAccountStartIndex { get; } +// public int NumberOfCompanionAccounts { get; } +// } +//} diff --git a/CodexPlugin/Marketplace/MarketplaceAccess.cs b/CodexPlugin/Marketplace/MarketplaceAccess.cs new file mode 100644 index 00000000..bee6cb7d --- /dev/null +++ b/CodexPlugin/Marketplace/MarketplaceAccess.cs @@ -0,0 +1,243 @@ +//using DistTestCore.Codex; +//using DistTestCore.Helpers; +//using Logging; +//using Newtonsoft.Json; +//using NUnit.Framework; +//using NUnit.Framework.Constraints; +//using System.Numerics; +//using Utils; + +//namespace DistTestCore.Marketplace +//{ +// public interface IMarketplaceAccess +// { +// string MakeStorageAvailable(ByteSize size, TestToken minPricePerBytePerSecond, TestToken maxCollateral, TimeSpan maxDuration); +// StoragePurchaseContract RequestStorage(ContentId contentId, TestToken pricePerSlotPerSecond, TestToken requiredCollateral, uint minRequiredNumberOfNodes, int proofProbability, TimeSpan duration); +// void AssertThatBalance(IResolveConstraint constraint, string message = ""); +// TestToken GetBalance(); +// } + +// public class MarketplaceAccess : IMarketplaceAccess +// { +// private readonly TestLifecycle lifecycle; +// private readonly MarketplaceNetwork marketplaceNetwork; +// private readonly GethAccount account; +// private readonly CodexAccess codexAccess; + +// public MarketplaceAccess(TestLifecycle lifecycle, MarketplaceNetwork marketplaceNetwork, GethAccount account, CodexAccess codexAccess) +// { +// this.lifecycle = lifecycle; +// this.marketplaceNetwork = marketplaceNetwork; +// this.account = account; +// this.codexAccess = codexAccess; +// } + +// public StoragePurchaseContract RequestStorage(ContentId contentId, TestToken pricePerSlotPerSecond, TestToken requiredCollateral, uint minRequiredNumberOfNodes, int proofProbability, TimeSpan duration) +// { +// var request = new CodexSalesRequestStorageRequest +// { +// duration = ToDecInt(duration.TotalSeconds), +// proofProbability = ToDecInt(proofProbability), +// reward = ToDecInt(pricePerSlotPerSecond), +// collateral = ToDecInt(requiredCollateral), +// expiry = null, +// nodes = minRequiredNumberOfNodes, +// tolerance = null, +// }; + +// Log($"Requesting storage for: {contentId.Id}... (" + +// $"pricePerSlotPerSecond: {pricePerSlotPerSecond}, " + +// $"requiredCollateral: {requiredCollateral}, " + +// $"minRequiredNumberOfNodes: {minRequiredNumberOfNodes}, " + +// $"proofProbability: {proofProbability}, " + +// $"duration: {Time.FormatDuration(duration)})"); + +// var response = codexAccess.RequestStorage(request, contentId.Id); + +// if (response == "Purchasing not available") +// { +// throw new InvalidOperationException(response); +// } + +// Log($"Storage requested successfully. PurchaseId: '{response}'."); + +// return new StoragePurchaseContract(lifecycle.Log, codexAccess, response, duration); +// } + +// public string MakeStorageAvailable(ByteSize totalSpace, TestToken minPriceForTotalSpace, TestToken maxCollateral, TimeSpan maxDuration) +// { +// var request = new CodexSalesAvailabilityRequest +// { +// size = ToDecInt(totalSpace.SizeInBytes), +// duration = ToDecInt(maxDuration.TotalSeconds), +// maxCollateral = ToDecInt(maxCollateral), +// minPrice = ToDecInt(minPriceForTotalSpace) +// }; + +// Log($"Making storage available... (" + +// $"size: {totalSpace}, " + +// $"minPriceForTotalSpace: {minPriceForTotalSpace}, " + +// $"maxCollateral: {maxCollateral}, " + +// $"maxDuration: {Time.FormatDuration(maxDuration)})"); + +// var response = codexAccess.SalesAvailability(request); + +// Log($"Storage successfully made available. Id: {response.id}"); + +// return response.id; +// } + +// private string ToDecInt(double d) +// { +// var i = new BigInteger(d); +// return i.ToString("D"); +// } + +// public string ToDecInt(TestToken t) +// { +// var i = new BigInteger(t.Amount); +// return i.ToString("D"); +// } + +// public void AssertThatBalance(IResolveConstraint constraint, string message = "") +// { +// AssertHelpers.RetryAssert(constraint, GetBalance, message); +// } + +// public TestToken GetBalance() +// { +// var interaction = marketplaceNetwork.StartInteraction(lifecycle); +// var amount = interaction.GetBalance(marketplaceNetwork.Marketplace.TokenAddress, account.Account); +// var balance = new TestToken(amount); + +// Log($"Balance of {account.Account} is {balance}."); + +// return balance; +// } + +// private void Log(string msg) +// { +// lifecycle.Log.Log($"{codexAccess.Container.Name} {msg}"); +// } +// } + +// public class MarketplaceUnavailable : IMarketplaceAccess +// { +// public StoragePurchaseContract RequestStorage(ContentId contentId, TestToken pricePerBytePerSecond, TestToken requiredCollateral, uint minRequiredNumberOfNodes, int proofProbability, TimeSpan duration) +// { +// Unavailable(); +// return null!; +// } + +// public string MakeStorageAvailable(ByteSize size, TestToken minPricePerBytePerSecond, TestToken maxCollateral, TimeSpan duration) +// { +// Unavailable(); +// return string.Empty; +// } + +// public void AssertThatBalance(IResolveConstraint constraint, string message = "") +// { +// Unavailable(); +// } + +// public TestToken GetBalance() +// { +// Unavailable(); +// return new TestToken(0); +// } + +// private void Unavailable() +// { +// Assert.Fail("Incorrect test setup: Marketplace was not enabled for this group of Codex nodes. Add 'EnableMarketplace(...)' after 'SetupCodexNodes()' to enable it."); +// throw new InvalidOperationException(); +// } +// } + +// public class StoragePurchaseContract +// { +// private readonly BaseLog log; +// private readonly CodexAccess codexAccess; +// private DateTime? contractStartUtc; + +// public StoragePurchaseContract(BaseLog log, CodexAccess codexAccess, string purchaseId, TimeSpan contractDuration) +// { +// this.log = log; +// this.codexAccess = codexAccess; +// PurchaseId = purchaseId; +// ContractDuration = contractDuration; +// } + +// public string PurchaseId { get; } +// public TimeSpan ContractDuration { get; } + +// public void WaitForStorageContractStarted() +// { +// WaitForStorageContractStarted(TimeSpan.FromSeconds(30)); +// } + +// public void WaitForStorageContractFinished() +// { +// if (!contractStartUtc.HasValue) +// { +// WaitForStorageContractStarted(); +// } +// var gracePeriod = TimeSpan.FromSeconds(10); +// var currentContractTime = DateTime.UtcNow - contractStartUtc!.Value; +// var timeout = (ContractDuration - currentContractTime) + gracePeriod; +// WaitForStorageContractState(timeout, "finished"); +// } + +// /// +// /// Wait for contract to start. Max timeout depends on contract filesize. Allows more time for larger files. +// /// +// public void WaitForStorageContractStarted(ByteSize contractFileSize) +// { +// var filesizeInMb = contractFileSize.SizeInBytes / (1024 * 1024); +// var maxWaitTime = TimeSpan.FromSeconds(filesizeInMb * 10.0); + +// WaitForStorageContractStarted(maxWaitTime); +// } + +// public void WaitForStorageContractStarted(TimeSpan timeout) +// { +// WaitForStorageContractState(timeout, "started"); +// contractStartUtc = DateTime.UtcNow; +// } + +// private void WaitForStorageContractState(TimeSpan timeout, string desiredState) +// { +// var lastState = ""; +// var waitStart = DateTime.UtcNow; + +// log.Log($"Waiting for {Time.FormatDuration(timeout)} for contract '{PurchaseId}' to reach state '{desiredState}'."); +// while (lastState != desiredState) +// { +// var purchaseStatus = codexAccess.GetPurchaseStatus(PurchaseId); +// var statusJson = JsonConvert.SerializeObject(purchaseStatus); +// if (purchaseStatus != null && purchaseStatus.state != lastState) +// { +// lastState = purchaseStatus.state; +// log.Debug("Purchase status: " + statusJson); +// } + +// Thread.Sleep(1000); + +// if (lastState == "errored") +// { +// Assert.Fail("Contract errored: " + statusJson); +// } + +// if (DateTime.UtcNow - waitStart > timeout) +// { +// Assert.Fail($"Contract did not reach '{desiredState}' within timeout. {statusJson}"); +// } +// } +// log.Log($"Contract '{desiredState}'."); +// } + +// public CodexStoragePurchase GetPurchaseStatus(string purchaseId) +// { +// return codexAccess.GetPurchaseStatus(purchaseId); +// } +// } +//} diff --git a/CodexPlugin/Marketplace/MarketplaceAccessFactory.cs b/CodexPlugin/Marketplace/MarketplaceAccessFactory.cs new file mode 100644 index 00000000..efc68413 --- /dev/null +++ b/CodexPlugin/Marketplace/MarketplaceAccessFactory.cs @@ -0,0 +1,41 @@ +//using DistTestCore.Codex; + +//namespace DistTestCore.Marketplace +//{ +// public interface IMarketplaceAccessFactory +// { +// IMarketplaceAccess CreateMarketplaceAccess(CodexAccess access); +// } + +// public class MarketplaceUnavailableAccessFactory : IMarketplaceAccessFactory +// { +// public IMarketplaceAccess CreateMarketplaceAccess(CodexAccess access) +// { +// return new MarketplaceUnavailable(); +// } +// } + +// public class GethMarketplaceAccessFactory : IMarketplaceAccessFactory +// { +// private readonly TestLifecycle lifecycle; +// private readonly MarketplaceNetwork marketplaceNetwork; + +// public GethMarketplaceAccessFactory(TestLifecycle lifecycle, MarketplaceNetwork marketplaceNetwork) +// { +// this.lifecycle = lifecycle; +// this.marketplaceNetwork = marketplaceNetwork; +// } + +// public IMarketplaceAccess CreateMarketplaceAccess(CodexAccess access) +// { +// var companionNode = GetGethCompanionNode(access); +// return new MarketplaceAccess(lifecycle, marketplaceNetwork, companionNode, access); +// } + +// private GethAccount GetGethCompanionNode(CodexAccess access) +// { +// var account = access.Container.Recipe.Additionals.Single(a => a is GethAccount); +// return (GethAccount)account; +// } +// } +//} diff --git a/CodexPlugin/Marketplace/MarketplaceInitialConfig.cs b/CodexPlugin/Marketplace/MarketplaceInitialConfig.cs new file mode 100644 index 00000000..da16bca1 --- /dev/null +++ b/CodexPlugin/Marketplace/MarketplaceInitialConfig.cs @@ -0,0 +1,17 @@ +//namespace DistTestCore.Marketplace +//{ +// public class MarketplaceInitialConfig +// { +// public MarketplaceInitialConfig(Ether initialEth, TestToken initialTestTokens, bool isValidator) +// { +// InitialEth = initialEth; +// InitialTestTokens = initialTestTokens; +// IsValidator = isValidator; +// } + +// public Ether InitialEth { get; } +// public TestToken InitialTestTokens { get; } +// public bool IsValidator { get; } +// public int? AccountIndexOverride { get; set; } +// } +//} diff --git a/CodexPlugin/Marketplace/MarketplaceNetwork.cs b/CodexPlugin/Marketplace/MarketplaceNetwork.cs new file mode 100644 index 00000000..d828f37c --- /dev/null +++ b/CodexPlugin/Marketplace/MarketplaceNetwork.cs @@ -0,0 +1,21 @@ +//using NethereumWorkflow; + +//namespace DistTestCore.Marketplace +//{ +// public class MarketplaceNetwork +// { +// public MarketplaceNetwork(GethBootstrapNodeInfo bootstrap, MarketplaceInfo marketplace) +// { +// Bootstrap = bootstrap; +// Marketplace = marketplace; +// } + +// public GethBootstrapNodeInfo Bootstrap { get; } +// public MarketplaceInfo Marketplace { get; } + +// public NethereumInteraction StartInteraction(TestLifecycle lifecycle) +// { +// return Bootstrap.StartInteraction(lifecycle); +// } +// } +//} diff --git a/CodexPlugin/Metrics/GrafanaContainerRecipe.cs b/CodexPlugin/Metrics/GrafanaContainerRecipe.cs new file mode 100644 index 00000000..db384613 --- /dev/null +++ b/CodexPlugin/Metrics/GrafanaContainerRecipe.cs @@ -0,0 +1,25 @@ +//using KubernetesWorkflow; + +//namespace DistTestCore.Metrics +//{ +// public class GrafanaContainerRecipe : DefaultContainerRecipe +// { +// public override string AppName => "grafana"; +// public override string Image => "grafana/grafana-oss:10.0.3"; + +// public const string DefaultAdminUser = "adminium"; +// public const string DefaultAdminPassword = "passwordium"; + +// protected override void InitializeRecipe(StartupConfig startupConfig) +// { +// AddExposedPort(3000); + +// AddEnvVar("GF_AUTH_ANONYMOUS_ENABLED", "true"); +// AddEnvVar("GF_AUTH_ANONYMOUS_ORG_NAME", "Main Org."); +// AddEnvVar("GF_AUTH_ANONYMOUS_ORG_ROLE", "Editor"); + +// AddEnvVar("GF_SECURITY_ADMIN_USER", DefaultAdminUser); +// AddEnvVar("GF_SECURITY_ADMIN_PASSWORD", DefaultAdminPassword); +// } +// } +//} diff --git a/CodexPlugin/Metrics/MetricsAccess.cs b/CodexPlugin/Metrics/MetricsAccess.cs new file mode 100644 index 00000000..3641d4fb --- /dev/null +++ b/CodexPlugin/Metrics/MetricsAccess.cs @@ -0,0 +1,81 @@ +//using DistTestCore.Helpers; +//using KubernetesWorkflow; +//using Logging; +//using NUnit.Framework; +//using NUnit.Framework.Constraints; +//using Utils; + +//namespace DistTestCore.Metrics +//{ +// public interface IMetricsAccess +// { +// void AssertThat(string metricName, IResolveConstraint constraint, string message = ""); +// } + +// public class MetricsAccess : IMetricsAccess +// { +// private readonly BaseLog log; +// private readonly ITimeSet timeSet; +// private readonly MetricsQuery query; +// private readonly RunningContainer node; + +// public MetricsAccess(BaseLog log, ITimeSet timeSet, MetricsQuery query, RunningContainer node) +// { +// this.log = log; +// this.timeSet = timeSet; +// this.query = query; +// this.node = node; +// } + +// public void AssertThat(string metricName, IResolveConstraint constraint, string message = "") +// { +// AssertHelpers.RetryAssert(constraint, () => +// { +// var metricSet = GetMetricWithTimeout(metricName); +// var metricValue = metricSet.Values[0].Value; + +// log.Log($"{node.Name} metric '{metricName}' = {metricValue}"); +// return metricValue; +// }, message); +// } + +// public Metrics? GetAllMetrics() +// { +// return query.GetAllMetricsForNode(node); +// } + +// private MetricsSet GetMetricWithTimeout(string metricName) +// { +// var start = DateTime.UtcNow; + +// while (true) +// { +// var mostRecent = GetMostRecent(metricName); +// if (mostRecent != null) return mostRecent; +// if (DateTime.UtcNow - start > timeSet.WaitForMetricTimeout()) +// { +// Assert.Fail($"Timeout: Unable to get metric '{metricName}'."); +// throw new TimeoutException(); +// } + +// Time.Sleep(TimeSpan.FromSeconds(2)); +// } +// } + +// private MetricsSet? GetMostRecent(string metricName) +// { +// var result = query.GetMostRecent(metricName, node); +// if (result == null) return null; +// return result.Sets.LastOrDefault(); +// } +// } + +// public class MetricsUnavailable : IMetricsAccess +// { +// public void AssertThat(string metricName, IResolveConstraint constraint, string message = "") +// { +// Assert.Fail("Incorrect test setup: Metrics were not enabled for this group of Codex nodes. Add 'EnableMetrics()' after 'SetupCodexNodes()' to enable it."); +// throw new InvalidOperationException(); +// } +// } +//} diff --git a/CodexPlugin/Metrics/MetricsAccessFactory.cs b/CodexPlugin/Metrics/MetricsAccessFactory.cs new file mode 100644 index 00000000..c185fef7 --- /dev/null +++ b/CodexPlugin/Metrics/MetricsAccessFactory.cs @@ -0,0 +1,35 @@ +//using KubernetesWorkflow; + +//namespace DistTestCore.Metrics +//{ +// public interface IMetricsAccessFactory +// { +// IMetricsAccess CreateMetricsAccess(RunningContainer codexContainer); +// } + +// public class MetricsUnavailableAccessFactory : IMetricsAccessFactory +// { +// public IMetricsAccess CreateMetricsAccess(RunningContainer codexContainer) +// { +// return new MetricsUnavailable(); +// } +// } + +// public class CodexNodeMetricsAccessFactory : IMetricsAccessFactory +// { +// private readonly TestLifecycle lifecycle; +// private readonly RunningContainers prometheusContainer; + +// public CodexNodeMetricsAccessFactory(TestLifecycle lifecycle, RunningContainers prometheusContainer) +// { +// this.lifecycle = lifecycle; +// this.prometheusContainer = prometheusContainer; +// } + +// public IMetricsAccess CreateMetricsAccess(RunningContainer codexContainer) +// { +// var query = new MetricsQuery(lifecycle, prometheusContainer); +// return new MetricsAccess(lifecycle.Log, lifecycle.TimeSet, query, codexContainer); +// } +// } +//} diff --git a/CodexPlugin/Metrics/MetricsDownloader.cs b/CodexPlugin/Metrics/MetricsDownloader.cs new file mode 100644 index 00000000..5efa0851 --- /dev/null +++ b/CodexPlugin/Metrics/MetricsDownloader.cs @@ -0,0 +1,80 @@ +//using Logging; +//using System.Globalization; + +//namespace DistTestCore.Metrics +//{ +// public class MetricsDownloader +// { +// private readonly BaseLog log; + +// public MetricsDownloader(BaseLog log) +// { +// this.log = log; +// } + +// public void DownloadAllMetricsForNode(string nodeName, MetricsAccess access) +// { +// var metrics = access.GetAllMetrics(); +// if (metrics == null || metrics.Sets.Length == 0 || metrics.Sets.All(s => s.Values.Length == 0)) return; + +// var headers = new[] { "timestamp" }.Concat(metrics.Sets.Select(s => s.Name)).ToArray(); +// var map = CreateValueMap(metrics); + +// WriteToFile(nodeName, headers, map); +// } + +// private void WriteToFile(string nodeName, string[] headers, Dictionary> map) +// { +// var file = log.CreateSubfile("csv"); +// log.Log($"Downloading metrics for {nodeName} to file {file.FullFilename}"); + +// file.WriteRaw(string.Join(",", headers)); + +// foreach (var pair in map) +// { +// file.WriteRaw(string.Join(",", new[] { FormatTimestamp(pair.Key) }.Concat(pair.Value))); +// } +// } + +// private Dictionary> CreateValueMap(Metrics metrics) +// { +// var map = CreateForAllTimestamps(metrics); +// foreach (var metric in metrics.Sets) +// { +// AddToMap(map, metric); +// } +// return map; + +// } + +// private Dictionary> CreateForAllTimestamps(Metrics metrics) +// { +// var result = new Dictionary>(); +// var timestamps = metrics.Sets.SelectMany(s => s.Values).Select(v => v.Timestamp).Distinct().ToArray(); +// foreach (var timestamp in timestamps) result.Add(timestamp, new List()); +// return result; +// } + +// private void AddToMap(Dictionary> map, MetricsSet metric) +// { +// foreach (var key in map.Keys) +// { +// map[key].Add(GetValueAtTimestamp(key, metric)); +// } +// } + +// private string GetValueAtTimestamp(DateTime key, MetricsSet metric) +// { +// var value = metric.Values.SingleOrDefault(v => v.Timestamp == key); +// if (value == null) return ""; +// return value.Value.ToString(CultureInfo.InvariantCulture); +// } + +// private string FormatTimestamp(DateTime key) +// { +// var origin = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); +// var diff = key - origin; +// return Math.Floor(diff.TotalSeconds).ToString(CultureInfo.InvariantCulture); +// } +// } +//} diff --git a/CodexPlugin/Metrics/MetricsMode.cs b/CodexPlugin/Metrics/MetricsMode.cs new file mode 100644 index 00000000..44a99e93 --- /dev/null +++ b/CodexPlugin/Metrics/MetricsMode.cs @@ -0,0 +1,9 @@ +//namespace DistTestCore.Metrics +//{ +// public enum MetricsMode +// { +// None, +// Record, +// Dashboard +// } +//} diff --git a/CodexPlugin/Metrics/MetricsQuery.cs b/CodexPlugin/Metrics/MetricsQuery.cs new file mode 100644 index 00000000..668ee9f6 --- /dev/null +++ b/CodexPlugin/Metrics/MetricsQuery.cs @@ -0,0 +1,198 @@ +//using DistTestCore.Codex; +//using KubernetesWorkflow; +//using System.Globalization; + +//namespace DistTestCore.Metrics +//{ +// public class MetricsQuery +// { +// private readonly Http http; + +// public MetricsQuery(TestLifecycle lifecycle, RunningContainers runningContainers) +// { +// RunningContainers = runningContainers; + +// var address = lifecycle.Configuration.GetAddress(runningContainers.Containers[0]); + +// http = new Http( +// lifecycle.Log, +// lifecycle.TimeSet, +// address, +// "api/v1"); +// } + +// public RunningContainers RunningContainers { get; } + +// public Metrics? GetMostRecent(string metricName, RunningContainer node) +// { +// var response = GetLastOverTime(metricName, GetInstanceStringForNode(node)); +// if (response == null) return null; + +// return new Metrics +// { +// Sets = response.data.result.Select(r => +// { +// return new MetricsSet +// { +// Instance = r.metric.instance, +// Values = MapSingleValue(r.value) +// }; +// }).ToArray() +// }; +// } + +// public Metrics? GetMetrics(string metricName) +// { +// var response = GetAll(metricName); +// if (response == null) return null; +// return MapResponseToMetrics(response); +// } + +// public Metrics? GetAllMetricsForNode(RunningContainer node) +// { +// var response = http.HttpGetJson($"query?query={GetInstanceStringForNode(node)}{GetQueryTimeRange()}"); +// if (response.status != "success") return null; +// return MapResponseToMetrics(response); +// } + +// private PrometheusQueryResponse? GetLastOverTime(string metricName, string instanceString) +// { +// var response = http.HttpGetJson($"query?query=last_over_time({metricName}{instanceString}{GetQueryTimeRange()})"); +// if (response.status != "success") return null; +// return response; +// } + +// private PrometheusQueryResponse? GetAll(string metricName) +// { +// var response = http.HttpGetJson($"query?query={metricName}{GetQueryTimeRange()}"); +// if (response.status != "success") return null; +// return response; +// } + +// private Metrics MapResponseToMetrics(PrometheusQueryResponse response) +// { +// return new Metrics +// { +// Sets = response.data.result.Select(r => +// { +// return new MetricsSet +// { +// Name = r.metric.__name__, +// Instance = r.metric.instance, +// Values = MapMultipleValues(r.values) +// }; +// }).ToArray() +// }; +// } + +// private MetricsSetValue[] MapSingleValue(object[] value) +// { +// if (value != null && value.Length > 0) +// { +// return new[] +// { +// MapValue(value) +// }; +// } +// return Array.Empty(); +// } + +// private MetricsSetValue[] MapMultipleValues(object[][] values) +// { +// if (values != null && values.Length > 0) +// { +// return values.Select(v => MapValue(v)).ToArray(); +// } +// return Array.Empty(); +// } + +// private MetricsSetValue MapValue(object[] value) +// { +// if (value.Length != 2) throw new InvalidOperationException("Expected value to be [double, string]."); + +// return new MetricsSetValue +// { +// Timestamp = ToTimestamp(value[0]), +// Value = ToValue(value[1]) +// }; +// } + +// private string GetInstanceNameForNode(RunningContainer node) +// { +// var ip = node.Pod.PodInfo.Ip; +// var port = node.Recipe.GetPortByTag(CodexContainerRecipe.MetricsPortTag).Number; +// return $"{ip}:{port}"; +// } + +// private string GetInstanceStringForNode(RunningContainer node) +// { +// return "{instance=\"" + GetInstanceNameForNode(node) + "\"}"; +// } + +// private string GetQueryTimeRange() +// { +// return "[12h]"; +// } + +// private double ToValue(object v) +// { +// return Convert.ToDouble(v, CultureInfo.InvariantCulture); +// } + +// private DateTime ToTimestamp(object v) +// { +// var unixSeconds = ToValue(v); +// return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(unixSeconds); +// } +// } + +// public class Metrics +// { +// public MetricsSet[] Sets { get; set; } = Array.Empty(); +// } + +// public class MetricsSet +// { +// public string Name { get; set; } = string.Empty; +// public string Instance { get; set; } = string.Empty; +// public MetricsSetValue[] Values { get; set; } = Array.Empty(); +// } + +// public class MetricsSetValue +// { +// public DateTime Timestamp { get; set; } +// public double Value { get; set; } +// } + +// public class PrometheusQueryResponse +// { +// public string status { get; set; } = string.Empty; +// public PrometheusQueryResponseData data { get; set; } = new(); +// } + +// public class PrometheusQueryResponseData +// { +// public string resultType { get; set; } = string.Empty; +// public PrometheusQueryResponseDataResultEntry[] result { get; set; } = Array.Empty(); +// } + +// public class PrometheusQueryResponseDataResultEntry +// { +// public ResultEntryMetric metric { get; set; } = new(); +// public object[] value { get; set; } = Array.Empty(); +// public object[][] values { get; set; } = Array.Empty(); +// } + +// public class ResultEntryMetric +// { +// public string __name__ { get; set; } = string.Empty; +// public string instance { get; set; } = string.Empty; +// public string job { get; set; } = string.Empty; +// } + +// public class PrometheusAllNamesResponse +// { +// public string status { get; set; } = string.Empty; +// public string[] data { get; set; } = Array.Empty(); +// } +//} diff --git a/CodexPlugin/Metrics/PrometheusContainerRecipe.cs b/CodexPlugin/Metrics/PrometheusContainerRecipe.cs new file mode 100644 index 00000000..c3b57068 --- /dev/null +++ b/CodexPlugin/Metrics/PrometheusContainerRecipe.cs @@ -0,0 +1,18 @@ +//using KubernetesWorkflow; + +//namespace DistTestCore.Metrics +//{ +// public class PrometheusContainerRecipe : DefaultContainerRecipe +// { +// public override string AppName => "prometheus"; +// public override string Image => "codexstorage/dist-tests-prometheus:latest"; + +// protected override void InitializeRecipe(StartupConfig startupConfig) +// { +// var config = startupConfig.Get(); + +// AddExposedPortAndVar("PROM_PORT"); +// AddEnvVar("PROM_CONFIG", config.PrometheusConfigBase64); +// } +// } +//} diff --git a/CodexPlugin/Metrics/PrometheusStartupConfig.cs b/CodexPlugin/Metrics/PrometheusStartupConfig.cs new file mode 100644 index 00000000..57434eba --- /dev/null +++ b/CodexPlugin/Metrics/PrometheusStartupConfig.cs @@ -0,0 +1,12 @@ +//namespace DistTestCore.Metrics +//{ +// public class PrometheusStartupConfig +// { +// public PrometheusStartupConfig(string prometheusConfigBase64) +// { +// PrometheusConfigBase64 = prometheusConfigBase64; +// } + +// public string PrometheusConfigBase64 { get; } +// } +//} diff --git a/DistTestCore/Metrics/dashboard.json b/CodexPlugin/Metrics/dashboard.json similarity index 100% rename from DistTestCore/Metrics/dashboard.json rename to CodexPlugin/Metrics/dashboard.json diff --git a/DistTestCore/OnlineCodexNode.cs b/CodexPlugin/OnlineCodexNode.cs similarity index 69% rename from DistTestCore/OnlineCodexNode.cs rename to CodexPlugin/OnlineCodexNode.cs index 2d1ee9d4..0a6a0943 100644 --- a/DistTestCore/OnlineCodexNode.cs +++ b/CodexPlugin/OnlineCodexNode.cs @@ -1,13 +1,10 @@ -using DistTestCore.Codex; -using DistTestCore.Logs; -using DistTestCore.Marketplace; -using DistTestCore.Metrics; +using DistTestCore.Logs; using FileUtils; using Logging; using NUnit.Framework; using Utils; -namespace DistTestCore +namespace CodexPlugin { public interface IOnlineCodexNode { @@ -18,8 +15,8 @@ namespace DistTestCore TestFile? DownloadContent(ContentId contentId, string fileLabel = ""); void ConnectToPeer(IOnlineCodexNode node); IDownloadedLog DownloadLog(int? tailLines = null); - IMetricsAccess Metrics { get; } - IMarketplaceAccess Marketplace { get; } + //IMetricsAccess Metrics { get; } + //IMarketplaceAccess Marketplace { get; } CodexDebugVersionResponse Version { get; } ICodexSetup BringOffline(); } @@ -28,22 +25,22 @@ namespace DistTestCore { private const string SuccessfullyConnectedMessage = "Successfully connected to peer"; private const string UploadFailedMessage = "Unable to store block"; - private readonly TestLifecycle lifecycle; + //private readonly TestLifecycle lifecycle; - public OnlineCodexNode(TestLifecycle lifecycle, CodexAccess codexAccess, CodexNodeGroup group, IMetricsAccess metricsAccess, IMarketplaceAccess marketplaceAccess) + public OnlineCodexNode(/*TestLifecycle lifecycle, */CodexAccess codexAccess, CodexNodeGroup group/*, IMetricsAccess metricsAccess, IMarketplaceAccess marketplaceAccess*/) { - this.lifecycle = lifecycle; + //this.lifecycle = lifecycle; CodexAccess = codexAccess; Group = group; - Metrics = metricsAccess; - Marketplace = marketplaceAccess; + //Metrics = metricsAccess; + //Marketplace = marketplaceAccess; Version = new CodexDebugVersionResponse(); } public CodexAccess CodexAccess { get; } public CodexNodeGroup Group { get; } - public IMetricsAccess Metrics { get; } - public IMarketplaceAccess Marketplace { get; } + //public IMetricsAccess Metrics { get; } + //public IMarketplaceAccess Marketplace { get; } public CodexDebugVersionResponse Version { get; private set; } public string GetName() @@ -66,30 +63,32 @@ namespace DistTestCore public ContentId UploadFile(TestFile file) { - using var fileStream = File.OpenRead(file.Filename); + //using var fileStream = File.OpenRead(file.Filename); - var logMessage = $"Uploading file {file.Describe()}..."; - Log(logMessage); - var response = Stopwatch.Measure(lifecycle.Log, logMessage, () => - { - return CodexAccess.UploadFile(fileStream); - }); + //var logMessage = $"Uploading file {file.Describe()}..."; + //Log(logMessage); + //var response = Stopwatch.Measure(lifecycle.Log, logMessage, () => + //{ + // return CodexAccess.UploadFile(fileStream); + //}); - if (string.IsNullOrEmpty(response)) Assert.Fail("Received empty response."); - if (response.StartsWith(UploadFailedMessage)) Assert.Fail("Node failed to store block."); + //if (string.IsNullOrEmpty(response)) Assert.Fail("Received empty response."); + //if (response.StartsWith(UploadFailedMessage)) Assert.Fail("Node failed to store block."); - Log($"Uploaded file. Received contentId: '{response}'."); - return new ContentId(response); + //Log($"Uploaded file. Received contentId: '{response}'."); + //return new ContentId(response); + return null!; } public TestFile? DownloadContent(ContentId contentId, string fileLabel = "") { - var logMessage = $"Downloading for contentId: '{contentId.Id}'..."; - Log(logMessage); - var file = lifecycle.FileManager.CreateEmptyTestFile(fileLabel); - Stopwatch.Measure(lifecycle.Log, logMessage, () => DownloadToFile(contentId.Id, file)); - Log($"Downloaded file {file.Describe()} to '{file.Filename}'."); - return file; + //var logMessage = $"Downloading for contentId: '{contentId.Id}'..."; + //Log(logMessage); + //var file = lifecycle.FileManager.CreateEmptyTestFile(fileLabel); + //Stopwatch.Measure(lifecycle.Log, logMessage, () => DownloadToFile(contentId.Id, file)); + //Log($"Downloaded file {file.Describe()} to '{file.Filename}'."); + //return file; + return null!; } public void ConnectToPeer(IOnlineCodexNode node) @@ -106,7 +105,7 @@ namespace DistTestCore public IDownloadedLog DownloadLog(int? tailLines = null) { - return lifecycle.DownloadLog(CodexAccess.Container, tailLines); + return null!; // lifecycle.DownloadLog(CodexAccess.Container, tailLines); } public ICodexSetup BringOffline() @@ -129,8 +128,8 @@ namespace DistTestCore throw new Exception($"Invalid version information received from Codex node {GetName()}: {debugInfo.codex}"); } - lifecycle.Log.AddStringReplace(nodePeerId, nodeName); - lifecycle.Log.AddStringReplace(debugInfo.table.localNode.nodeId, nodeName); + //lifecycle.Log.AddStringReplace(nodePeerId, nodeName); + //lifecycle.Log.AddStringReplace(debugInfo.table.localNode.nodeId, nodeName); Version = debugInfo.codex; } @@ -161,7 +160,7 @@ namespace DistTestCore private void Log(string msg) { - lifecycle.Log.Log($"{GetName()}: {msg}"); + //lifecycle.Log.Log($"{GetName()}: {msg}"); } } diff --git a/DistTestCore/AutoBootstrapDistTest.cs b/DistTestCore/AutoBootstrapDistTest.cs index 25bb1554..6fadf9bf 100644 --- a/DistTestCore/AutoBootstrapDistTest.cs +++ b/DistTestCore/AutoBootstrapDistTest.cs @@ -4,27 +4,27 @@ namespace DistTestCore { public class AutoBootstrapDistTest : DistTest { - public override IOnlineCodexNode SetupCodexBootstrapNode(Action setup) - { - throw new Exception("AutoBootstrapDistTest creates and attaches a single bootstrap node for you. " + - "If you want to control the bootstrap node from your test, please use DistTest instead."); - } + //public override IOnlineCodexNode SetupCodexBootstrapNode(Action setup) + //{ + // throw new Exception("AutoBootstrapDistTest creates and attaches a single bootstrap node for you. " + + // "If you want to control the bootstrap node from your test, please use DistTest instead."); + //} - public override ICodexNodeGroup SetupCodexNodes(int numberOfNodes, Action setup) - { - var codexSetup = CreateCodexSetup(numberOfNodes); - setup(codexSetup); - codexSetup.WithBootstrapNode(BootstrapNode); - return BringOnline(codexSetup); - } + //public override ICodexNodeGroup SetupCodexNodes(int numberOfNodes, Action setup) + //{ + // var codexSetup = CreateCodexSetup(numberOfNodes); + // setup(codexSetup); + // codexSetup.WithBootstrapNode(BootstrapNode); + // return BringOnline(codexSetup); + //} - [SetUp] - public void SetUpBootstrapNode() - { - var setup = CreateCodexSetup(1).WithName("BOOTSTRAP"); - BootstrapNode = BringOnline(setup)[0]; - } + //[SetUp] + //public void SetUpBootstrapNode() + //{ + // var setup = CreateCodexSetup(1).WithName("BOOTSTRAP"); + // BootstrapNode = BringOnline(setup)[0]; + //} - protected IOnlineCodexNode BootstrapNode { get; private set; } = null!; + //protected IOnlineCodexNode BootstrapNode { get; private set; } = null!; } } diff --git a/DistTestCore/CodexNodeFactory.cs b/DistTestCore/CodexNodeFactory.cs deleted file mode 100644 index 9b67158b..00000000 --- a/DistTestCore/CodexNodeFactory.cs +++ /dev/null @@ -1,32 +0,0 @@ -using DistTestCore.Codex; -using DistTestCore.Marketplace; -using DistTestCore.Metrics; - -namespace DistTestCore -{ - public interface ICodexNodeFactory - { - OnlineCodexNode CreateOnlineCodexNode(CodexAccess access, CodexNodeGroup group); - } - - public class CodexNodeFactory : ICodexNodeFactory - { - private readonly TestLifecycle lifecycle; - private readonly IMetricsAccessFactory metricsAccessFactory; - private readonly IMarketplaceAccessFactory marketplaceAccessFactory; - - public CodexNodeFactory(TestLifecycle lifecycle, IMetricsAccessFactory metricsAccessFactory, IMarketplaceAccessFactory marketplaceAccessFactory) - { - this.lifecycle = lifecycle; - this.metricsAccessFactory = metricsAccessFactory; - 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); - } - } -} diff --git a/DistTestCore/CodexStarter.cs b/DistTestCore/CodexStarter.cs deleted file mode 100644 index 86a839ef..00000000 --- a/DistTestCore/CodexStarter.cs +++ /dev/null @@ -1,158 +0,0 @@ -using DistTestCore.Codex; -using DistTestCore.Marketplace; -using DistTestCore.Metrics; -using KubernetesWorkflow; -using Logging; - -namespace DistTestCore -{ - public class CodexStarter : BaseStarter - { - public CodexStarter(TestLifecycle lifecycle) - : base(lifecycle) - { - } - - public List RunningGroups { get; } = new List(); - - public ICodexNodeGroup BringOnline(CodexSetup codexSetup) - { - LogSeparator(); - LogStart($"Starting {codexSetup.Describe()}..."); - var gethStartResult = lifecycle.GethStarter.BringOnlineMarketplaceFor(codexSetup); - - var startupConfig = CreateStartupConfig(gethStartResult, codexSetup); - - var containers = StartCodexContainers(startupConfig, codexSetup.NumberOfNodes, codexSetup.Location); - - var metricAccessFactory = CollectMetrics(codexSetup, containers); - - var codexNodeFactory = new CodexNodeFactory(lifecycle, metricAccessFactory, gethStartResult.MarketplaceAccessFactory); - - var group = 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) - { - LogStart($"Stopping {group.Describe()}..."); - var workflow = CreateWorkflow(); - foreach (var c in group.Containers) - { - StopCrashWatcher(c); - workflow.Stop(c); - } - RunningGroups.Remove(group); - LogEnd("Stopped."); - } - - public void DeleteAllResources() - { - var workflow = CreateWorkflow(); - workflow.DeleteTestResources(); - - RunningGroups.Clear(); - } - - public void DownloadLog(RunningContainer container, ILogHandler logHandler, int? tailLines) - { - var workflow = CreateWorkflow(); - workflow.DownloadContainerLog(container, logHandler, tailLines); - } - - private IMetricsAccessFactory CollectMetrics(CodexSetup codexSetup, RunningContainers[] containers) - { - if (codexSetup.MetricsMode == MetricsMode.None) return new MetricsUnavailableAccessFactory(); - - var runningContainers = lifecycle.PrometheusStarter.CollectMetricsFor(containers); - - if (codexSetup.MetricsMode == MetricsMode.Dashboard) - { - lifecycle.GrafanaStarter.StartDashboard(runningContainers.Containers.First(), codexSetup); - } - - 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 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 CodexNodeGroup CreateCodexGroup(CodexSetup codexSetup, RunningContainers[] runningContainers, CodexNodeFactory codexNodeFactory) - { - var group = new CodexNodeGroup(lifecycle, codexSetup, runningContainers, codexNodeFactory); - RunningGroups.Add(group); - - try - { - Stopwatch.Measure(lifecycle.Log, "EnsureOnline", group.EnsureOnline, debug: true); - } - catch - { - CodexNodesNotOnline(runningContainers); - throw; - } - - return group; - } - - private void CodexNodesNotOnline(RunningContainers[] runningContainers) - { - Log("Codex nodes failed to start"); - foreach (var container in runningContainers.Containers()) lifecycle.DownloadLog(container); - } - - private StartupWorkflow CreateWorkflow() - { - return lifecycle.WorkflowCreator.CreateWorkflow(); - } - - private void LogSeparator() - { - 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) - { - c.CrashWatcher?.Stop(); - } - } - } -} diff --git a/DistTestCore/Configuration.cs b/DistTestCore/Configuration.cs index a8170221..86dc2388 100644 --- a/DistTestCore/Configuration.cs +++ b/DistTestCore/Configuration.cs @@ -1,5 +1,4 @@ -using DistTestCore.Codex; -using KubernetesWorkflow; +using KubernetesWorkflow; using System.Net.NetworkInformation; using Utils; @@ -11,7 +10,7 @@ namespace DistTestCore private readonly string logPath; private readonly bool logDebug; private readonly string dataFilesPath; - private readonly CodexLogLevel codexLogLevel; + //private readonly CodexLogLevel codexLogLevel; private readonly string k8sNamespacePrefix; private static RunnerLocation? runnerLocation = null; @@ -21,17 +20,17 @@ namespace DistTestCore logPath = GetEnvVarOrDefault("LOGPATH", "CodexTestLogs"); logDebug = GetEnvVarOrDefault("LOGDEBUG", "false").ToLowerInvariant() == "true"; dataFilesPath = GetEnvVarOrDefault("DATAFILEPATH", "TestDataFiles"); - codexLogLevel = ParseEnum.Parse(GetEnvVarOrDefault("LOGLEVEL", nameof(CodexLogLevel.Trace))); + //codexLogLevel = ParseEnum.Parse(GetEnvVarOrDefault("LOGLEVEL", nameof(CodexLogLevel.Trace))); k8sNamespacePrefix = "ct-"; } - public Configuration(string? kubeConfigFile, string logPath, bool logDebug, string dataFilesPath, CodexLogLevel codexLogLevel, string k8sNamespacePrefix) + public Configuration(string? kubeConfigFile, string logPath, bool logDebug, string dataFilesPath, /*CodexLogLevel codexLogLevel,*/ string k8sNamespacePrefix) { this.kubeConfigFile = kubeConfigFile; this.logPath = logPath; this.logDebug = logDebug; this.dataFilesPath = dataFilesPath; - this.codexLogLevel = codexLogLevel; + //this.codexLogLevel = codexLogLevel; this.k8sNamespacePrefix = k8sNamespacePrefix; } @@ -55,10 +54,10 @@ namespace DistTestCore return dataFilesPath; } - public CodexLogLevel GetCodexLogLevel() - { - return codexLogLevel; - } + //public CodexLogLevel GetCodexLogLevel() + //{ + // return codexLogLevel; + //} public Address GetAddress(RunningContainer container) { diff --git a/DistTestCore/DistTest.cs b/DistTestCore/DistTest.cs index 5439b5af..e9655148 100644 --- a/DistTestCore/DistTest.cs +++ b/DistTestCore/DistTest.cs @@ -1,8 +1,4 @@ -using DistTestCore.Codex; -using DistTestCore.Helpers; -using DistTestCore.Logs; -using DistTestCore.Marketplace; -using DistTestCore.Metrics; +using DistTestCore.Logs; using FileUtils; using KubernetesWorkflow; using Logging; @@ -38,10 +34,10 @@ namespace DistTestCore public void GlobalSetup() { fixtureLog.Log($"Codex Distributed Tests are starting..."); - fixtureLog.Log($"Codex image: '{new CodexContainerRecipe().Image}'"); - fixtureLog.Log($"CodexContracts image: '{new CodexContractsContainerRecipe().Image}'"); - fixtureLog.Log($"Prometheus image: '{new PrometheusContainerRecipe().Image}'"); - fixtureLog.Log($"Geth image: '{new GethContainerRecipe().Image}'"); + //fixtureLog.Log($"Codex image: '{new CodexContainerRecipe().Image}'"); + //fixtureLog.Log($"CodexContracts image: '{new CodexContractsContainerRecipe().Image}'"); + //fixtureLog.Log($"Prometheus image: '{new PrometheusContainerRecipe().Image}'"); + //fixtureLog.Log($"Geth image: '{new GethContainerRecipe().Image}'"); // Previous test run may have been interrupted. // Begin by cleaning everything up. @@ -104,53 +100,53 @@ namespace DistTestCore Get().FileManager.ScopedFiles(action); } - public IOnlineCodexNode SetupCodexBootstrapNode() - { - return SetupCodexBootstrapNode(s => { }); - } + //public IOnlineCodexNode SetupCodexBootstrapNode() + //{ + // return SetupCodexBootstrapNode(s => { }); + //} - public virtual IOnlineCodexNode SetupCodexBootstrapNode(Action setup) - { - return SetupCodexNode(s => - { - setup(s); - s.WithName("Bootstrap"); - }); - } + //public virtual IOnlineCodexNode SetupCodexBootstrapNode(Action setup) + //{ + // return SetupCodexNode(s => + // { + // setup(s); + // s.WithName("Bootstrap"); + // }); + //} - public IOnlineCodexNode SetupCodexNode() - { - return SetupCodexNode(s => { }); - } + //public IOnlineCodexNode SetupCodexNode() + //{ + // return SetupCodexNode(s => { }); + //} - public IOnlineCodexNode SetupCodexNode(Action setup) - { - return SetupCodexNodes(1, setup)[0]; - } + //public IOnlineCodexNode SetupCodexNode(Action setup) + //{ + // return SetupCodexNodes(1, setup)[0]; + //} - public ICodexNodeGroup SetupCodexNodes(int numberOfNodes) - { - return SetupCodexNodes(numberOfNodes, s => { }); - } + //public ICodexNodeGroup SetupCodexNodes(int numberOfNodes) + //{ + // return SetupCodexNodes(numberOfNodes, s => { }); + //} - public virtual ICodexNodeGroup SetupCodexNodes(int numberOfNodes, Action setup) - { - var codexSetup = CreateCodexSetup(numberOfNodes); + //public virtual ICodexNodeGroup SetupCodexNodes(int numberOfNodes, Action setup) + //{ + // var codexSetup = CreateCodexSetup(numberOfNodes); - setup(codexSetup); + // setup(codexSetup); - return BringOnline(codexSetup); - } + // return BringOnline(codexSetup); + //} - public ICodexNodeGroup BringOnline(ICodexSetup codexSetup) - { - return Get().CodexStarter.BringOnline((CodexSetup)codexSetup); - } + //public ICodexNodeGroup BringOnline(ICodexSetup codexSetup) + //{ + // return Get().CodexStarter.BringOnline((CodexSetup)codexSetup); + //} - public IEnumerable GetAllOnlineCodexNodes() - { - return Get().CodexStarter.RunningGroups.SelectMany(g => g.Nodes); - } + //public IEnumerable GetAllOnlineCodexNodes() + //{ + // return Get().CodexStarter.RunningGroups.SelectMany(g => g.Nodes); + //} public BaseLog GetTestLog() { @@ -169,25 +165,25 @@ namespace DistTestCore GetTestLog().Debug(msg); } - public PeerConnectionTestHelpers CreatePeerConnectionTestHelpers() - { - return new PeerConnectionTestHelpers(GetTestLog()); - } + //public PeerConnectionTestHelpers CreatePeerConnectionTestHelpers() + //{ + // return new PeerConnectionTestHelpers(GetTestLog()); + //} - public PeerDownloadTestHelpers CreatePeerDownloadTestHelpers() - { - return new PeerDownloadTestHelpers(GetTestLog(), Get().FileManager); - } + //public PeerDownloadTestHelpers CreatePeerDownloadTestHelpers() + //{ + // return new PeerDownloadTestHelpers(GetTestLog(), Get().FileManager); + //} public void Measure(string name, Action action) { Stopwatch.Measure(Get().Log, name, action); } - protected CodexSetup CreateCodexSetup(int numberOfNodes) - { - return new CodexSetup(numberOfNodes, configuration.GetCodexLogLevel()); - } + //protected CodexSetup CreateCodexSetup(int numberOfNodes) + //{ + // return new CodexSetup(numberOfNodes, configuration.GetCodexLogLevel()); + //} private TestLifecycle Get() { @@ -261,8 +257,8 @@ namespace DistTestCore if (IsDownloadingLogsAndMetricsEnabled()) { lifecycle.Log.Log("Downloading all CodexNode logs and metrics because of test failure..."); - DownloadAllLogs(lifecycle); - DownloadAllMetrics(lifecycle); + //DownloadAllLogs(lifecycle); + //DownloadAllMetrics(lifecycle); } else { @@ -271,36 +267,36 @@ namespace DistTestCore } } - private void DownloadAllLogs(TestLifecycle lifecycle) - { - OnEachCodexNode(lifecycle, node => - { - lifecycle.DownloadLog(node.CodexAccess.Container); - }); - } + //private void DownloadAllLogs(TestLifecycle lifecycle) + //{ + // OnEachCodexNode(lifecycle, node => + // { + // lifecycle.DownloadLog(node.CodexAccess.Container); + // }); + //} - private void DownloadAllMetrics(TestLifecycle lifecycle) - { - var metricsDownloader = new MetricsDownloader(lifecycle.Log); + //private void DownloadAllMetrics(TestLifecycle lifecycle) + //{ + // var metricsDownloader = new MetricsDownloader(lifecycle.Log); - OnEachCodexNode(lifecycle, node => - { - var m = node.Metrics as MetricsAccess; - if (m != null) - { - metricsDownloader.DownloadAllMetricsForNode(node.GetName(), m); - } - }); - } + // OnEachCodexNode(lifecycle, node => + // { + // var m = node.Metrics as MetricsAccess; + // if (m != null) + // { + // metricsDownloader.DownloadAllMetricsForNode(node.GetName(), m); + // } + // }); + //} - private void OnEachCodexNode(TestLifecycle lifecycle, Action action) - { - var allNodes = lifecycle.CodexStarter.RunningGroups.SelectMany(g => g.Nodes); - foreach (var node in allNodes) - { - action(node); - } - } + //private void OnEachCodexNode(TestLifecycle lifecycle, Action action) + //{ + // var allNodes = lifecycle.CodexStarter.RunningGroups.SelectMany(g => g.Nodes); + // foreach (var node in allNodes) + // { + // action(node); + // } + //} private string GetCurrentTestName() { diff --git a/DistTestCore/DistTestCore.csproj b/DistTestCore/DistTestCore.csproj index 565e175a..6005043a 100644 --- a/DistTestCore/DistTestCore.csproj +++ b/DistTestCore/DistTestCore.csproj @@ -10,14 +10,6 @@ Arm64 - - - - - - Never - - diff --git a/DistTestCore/GethStarter.cs b/DistTestCore/GethStarter.cs deleted file mode 100644 index 578cc307..00000000 --- a/DistTestCore/GethStarter.cs +++ /dev/null @@ -1,88 +0,0 @@ -using DistTestCore.Marketplace; - -namespace DistTestCore -{ - public class GethStarter : BaseStarter - { - private readonly MarketplaceNetworkCache marketplaceNetworkCache; - private readonly GethCompanionNodeStarter companionNodeStarter; - - public GethStarter(TestLifecycle lifecycle) - : base(lifecycle) - { - marketplaceNetworkCache = new MarketplaceNetworkCache( - new GethBootstrapNodeStarter(lifecycle), - new CodexContractsStarter(lifecycle)); - companionNodeStarter = new GethCompanionNodeStarter(lifecycle); - } - - public GethStartResult BringOnlineMarketplaceFor(CodexSetup codexSetup) - { - if (codexSetup.MarketplaceConfig == null) return CreateMarketplaceUnavailableResult(); - - var marketplaceNetwork = marketplaceNetworkCache.Get(); - var companionNode = StartCompanionNode(codexSetup, marketplaceNetwork); - - LogStart("Setting up initial balance..."); - TransferInitialBalance(marketplaceNetwork, codexSetup.MarketplaceConfig, companionNode); - LogEnd($"Initial balance of {codexSetup.MarketplaceConfig.InitialTestTokens} set for {codexSetup.NumberOfNodes} nodes."); - - return CreateGethStartResult(marketplaceNetwork, companionNode); - } - - private void TransferInitialBalance(MarketplaceNetwork marketplaceNetwork, MarketplaceInitialConfig marketplaceConfig, GethCompanionNodeInfo companionNode) - { - if (marketplaceConfig.InitialTestTokens.Amount == 0) return; - - var interaction = marketplaceNetwork.StartInteraction(lifecycle); - var tokenAddress = marketplaceNetwork.Marketplace.TokenAddress; - - var accounts = companionNode.Accounts.Select(a => a.Account).ToArray(); - interaction.MintTestTokens(accounts, marketplaceConfig.InitialTestTokens.Amount, tokenAddress); - } - - private GethStartResult CreateGethStartResult(MarketplaceNetwork marketplaceNetwork, GethCompanionNodeInfo companionNode) - { - return new GethStartResult(CreateMarketplaceAccessFactory(marketplaceNetwork), marketplaceNetwork, companionNode); - } - - private GethStartResult CreateMarketplaceUnavailableResult() - { - return new GethStartResult(new MarketplaceUnavailableAccessFactory(), null!, null!); - } - - private IMarketplaceAccessFactory CreateMarketplaceAccessFactory(MarketplaceNetwork marketplaceNetwork) - { - return new GethMarketplaceAccessFactory(lifecycle, marketplaceNetwork); - } - - private GethCompanionNodeInfo StartCompanionNode(CodexSetup codexSetup, MarketplaceNetwork marketplaceNetwork) - { - return companionNodeStarter.StartCompanionNodeFor(codexSetup, marketplaceNetwork); - } - } - - public class MarketplaceNetworkCache - { - private readonly GethBootstrapNodeStarter bootstrapNodeStarter; - private readonly CodexContractsStarter codexContractsStarter; - private MarketplaceNetwork? network; - - public MarketplaceNetworkCache(GethBootstrapNodeStarter bootstrapNodeStarter, CodexContractsStarter codexContractsStarter) - { - this.bootstrapNodeStarter = bootstrapNodeStarter; - this.codexContractsStarter = codexContractsStarter; - } - - public MarketplaceNetwork Get() - { - if (network == null) - { - var bootstrapInfo = bootstrapNodeStarter.StartGethBootstrapNode(); - var marketplaceInfo = codexContractsStarter.Start(bootstrapInfo); - network = new MarketplaceNetwork(bootstrapInfo, marketplaceInfo ); - } - return network; - } - } -} diff --git a/DistTestCore/GrafanaStarter.cs b/DistTestCore/GrafanaStarter.cs index d4a3cd8f..f6dd43f3 100644 --- a/DistTestCore/GrafanaStarter.cs +++ b/DistTestCore/GrafanaStarter.cs @@ -1,9 +1,4 @@ -using DistTestCore.Metrics; -using IdentityModel.Client; -using KubernetesWorkflow; -using Newtonsoft.Json; -using System.Reflection; -using Utils; +using KubernetesWorkflow; namespace DistTestCore { @@ -17,133 +12,134 @@ namespace DistTestCore { } - public GrafanaStartInfo StartDashboard(RunningContainer prometheusContainer, CodexSetup codexSetup) + public GrafanaStartInfo StartDashboard(RunningContainer prometheusContainer)//, CodexSetup codexSetup) { - LogStart($"Starting dashboard server"); + return null!; + //LogStart($"Starting dashboard server"); - var grafanaContainer = StartGrafanaContainer(); - var grafanaAddress = lifecycle.Configuration.GetAddress(grafanaContainer); + //var grafanaContainer = StartGrafanaContainer(); + //var grafanaAddress = lifecycle.Configuration.GetAddress(grafanaContainer); - var http = new Http(lifecycle.Log, new DefaultTimeSet(), grafanaAddress, "api/", AddBasicAuth); + //var http = new Http(lifecycle.Log, new DefaultTimeSet(), grafanaAddress, "api/", AddBasicAuth); - Log("Connecting datasource..."); - AddDataSource(http, prometheusContainer); + //Log("Connecting datasource..."); + //AddDataSource(http, prometheusContainer); - Log("Uploading dashboard configurations..."); - var jsons = ReadEachDashboardJsonFile(codexSetup); - var dashboardUrls = jsons.Select(j => UploadDashboard(http, grafanaContainer, j)).ToArray(); + //Log("Uploading dashboard configurations..."); + //var jsons = ReadEachDashboardJsonFile(codexSetup); + //var dashboardUrls = jsons.Select(j => UploadDashboard(http, grafanaContainer, j)).ToArray(); - LogEnd("Dashboard server started."); + //LogEnd("Dashboard server started."); - return new GrafanaStartInfo(dashboardUrls, grafanaContainer); + //return new GrafanaStartInfo(dashboardUrls, grafanaContainer); } - private RunningContainer StartGrafanaContainer() - { - var startupConfig = new StartupConfig(); + //private RunningContainer StartGrafanaContainer() + //{ + // var startupConfig = new StartupConfig(); - var workflow = lifecycle.WorkflowCreator.CreateWorkflow(); - var grafanaContainers = workflow.Start(1, Location.Unspecified, new GrafanaContainerRecipe(), startupConfig); - if (grafanaContainers.Containers.Length != 1) throw new InvalidOperationException("Expected 1 dashboard container to be created."); + // var workflow = lifecycle.WorkflowCreator.CreateWorkflow(); + // var grafanaContainers = workflow.Start(1, Location.Unspecified, new GrafanaContainerRecipe(), startupConfig); + // if (grafanaContainers.Containers.Length != 1) throw new InvalidOperationException("Expected 1 dashboard container to be created."); - return grafanaContainers.Containers.First(); - } + // return grafanaContainers.Containers.First(); + //} - private void AddBasicAuth(HttpClient client) - { - client.SetBasicAuthentication( - GrafanaContainerRecipe.DefaultAdminUser, - GrafanaContainerRecipe.DefaultAdminPassword); - } + //private void AddBasicAuth(HttpClient client) + //{ + // client.SetBasicAuthentication( + // GrafanaContainerRecipe.DefaultAdminUser, + // GrafanaContainerRecipe.DefaultAdminPassword); + //} - private static void AddDataSource(Http http, RunningContainer prometheusContainer) - { - var prometheusAddress = prometheusContainer.ClusterExternalAddress; - var prometheusUrl = prometheusAddress.Host + ":" + prometheusAddress.Port; - var response = http.HttpPostJson("datasources", new GrafanaDataSourceRequest - { - uid = "c89eaad3-9184-429f-ac94-8ba0b1824dbb", - name = "CodexPrometheus", - type = "prometheus", - url = prometheusUrl, - access = "proxy", - basicAuth = false, - jsonData = new GrafanaDataSourceJsonData - { - httpMethod = "POST" - } - }); + //private static void AddDataSource(Http http, RunningContainer prometheusContainer) + //{ + // var prometheusAddress = prometheusContainer.ClusterExternalAddress; + // var prometheusUrl = prometheusAddress.Host + ":" + prometheusAddress.Port; + // var response = http.HttpPostJson("datasources", new GrafanaDataSourceRequest + // { + // uid = "c89eaad3-9184-429f-ac94-8ba0b1824dbb", + // name = "CodexPrometheus", + // type = "prometheus", + // url = prometheusUrl, + // access = "proxy", + // basicAuth = false, + // jsonData = new GrafanaDataSourceJsonData + // { + // httpMethod = "POST" + // } + // }); - if (response.message != "Datasource added") - { - throw new Exception("Test infra failure: Failed to add datasource to dashboard: " + response.message); - } - } + // if (response.message != "Datasource added") + // { + // throw new Exception("Test infra failure: Failed to add datasource to dashboard: " + response.message); + // } + //} - public static string UploadDashboard(Http http, RunningContainer grafanaContainer, string dashboardJson) - { - var request = GetDashboardCreateRequest(dashboardJson); - var response = http.HttpPostString("dashboards/db", request); - var jsonResponse = JsonConvert.DeserializeObject(response); - if (jsonResponse == null || string.IsNullOrEmpty(jsonResponse.url)) throw new Exception("Failed to upload dashboard."); + //public static string UploadDashboard(Http http, RunningContainer grafanaContainer, string dashboardJson) + //{ + // var request = GetDashboardCreateRequest(dashboardJson); + // var response = http.HttpPostString("dashboards/db", request); + // var jsonResponse = JsonConvert.DeserializeObject(response); + // if (jsonResponse == null || string.IsNullOrEmpty(jsonResponse.url)) throw new Exception("Failed to upload dashboard."); - var grafanaAddress = grafanaContainer.ClusterExternalAddress; - return grafanaAddress.Host + ":" + grafanaAddress.Port + jsonResponse.url; - } + // var grafanaAddress = grafanaContainer.ClusterExternalAddress; + // return grafanaAddress.Host + ":" + grafanaAddress.Port + jsonResponse.url; + //} - private static string[] ReadEachDashboardJsonFile(CodexSetup codexSetup) - { - var assembly = Assembly.GetExecutingAssembly(); - var resourceNames = new[] - { - "DistTestCore.Metrics.dashboard.json" - }; + //private static string[] ReadEachDashboardJsonFile(CodexSetup codexSetup) + //{ + // var assembly = Assembly.GetExecutingAssembly(); + // var resourceNames = new[] + // { + // "DistTestCore.Metrics.dashboard.json" + // }; - return resourceNames.Select(r => GetManifestResource(assembly, r, codexSetup)).ToArray(); - } + // return resourceNames.Select(r => GetManifestResource(assembly, r, codexSetup)).ToArray(); + //} - private static string GetManifestResource(Assembly assembly, string resourceName, CodexSetup codexSetup) - { - using var stream = assembly.GetManifestResourceStream(resourceName); - if (stream == null) throw new Exception("Unable to find resource " + resourceName); - using var reader = new StreamReader(stream); - return ApplyReplacements(reader.ReadToEnd(), codexSetup); - } + //private static string GetManifestResource(Assembly assembly, string resourceName, CodexSetup codexSetup) + //{ + // using var stream = assembly.GetManifestResourceStream(resourceName); + // if (stream == null) throw new Exception("Unable to find resource " + resourceName); + // using var reader = new StreamReader(stream); + // return ApplyReplacements(reader.ReadToEnd(), codexSetup); + //} - private static string ApplyReplacements(string input, CodexSetup codexSetup) - { - var quotaString = GetQuotaString(codexSetup); - var softMaxString = GetSoftMaxString(codexSetup); + //private static string ApplyReplacements(string input, CodexSetup codexSetup) + //{ + // var quotaString = GetQuotaString(codexSetup); + // var softMaxString = GetSoftMaxString(codexSetup); - return input - .Replace(StorageQuotaThresholdReplaceToken, quotaString) - .Replace(BytesUsedGraphAxisSoftMaxReplaceToken, softMaxString); - } + // return input + // .Replace(StorageQuotaThresholdReplaceToken, quotaString) + // .Replace(BytesUsedGraphAxisSoftMaxReplaceToken, softMaxString); + //} - private static string GetQuotaString(CodexSetup codexSetup) - { - return GetCodexStorageQuotaInBytes(codexSetup).ToString(); - } + //private static string GetQuotaString(CodexSetup codexSetup) + //{ + // return GetCodexStorageQuotaInBytes(codexSetup).ToString(); + //} - private static string GetSoftMaxString(CodexSetup codexSetup) - { - var quota = GetCodexStorageQuotaInBytes(codexSetup); - var softMax = Convert.ToInt64(quota * 1.1); // + 10%, for nice viewing. - return softMax.ToString(); - } + //private static string GetSoftMaxString(CodexSetup codexSetup) + //{ + // var quota = GetCodexStorageQuotaInBytes(codexSetup); + // var softMax = Convert.ToInt64(quota * 1.1); // + 10%, for nice viewing. + // return softMax.ToString(); + //} - private static long GetCodexStorageQuotaInBytes(CodexSetup codexSetup) - { - if (codexSetup.StorageQuota != null) return codexSetup.StorageQuota.SizeInBytes; + //private static long GetCodexStorageQuotaInBytes(CodexSetup codexSetup) + //{ + // if (codexSetup.StorageQuota != null) return codexSetup.StorageQuota.SizeInBytes; - // Codex default: 8GB - return 8.GB().SizeInBytes; - } + // // Codex default: 8GB + // return 8.GB().SizeInBytes; + //} - private static string GetDashboardCreateRequest(string dashboardJson) - { - return $"{{\"dashboard\": {dashboardJson} ,\"message\": \"Default Codex Dashboard\",\"overwrite\": false}}"; - } + //private static string GetDashboardCreateRequest(string dashboardJson) + //{ + // return $"{{\"dashboard\": {dashboardJson} ,\"message\": \"Default Codex Dashboard\",\"overwrite\": false}}"; + //} } public class GrafanaStartInfo diff --git a/DistTestCore/Helpers/FullConnectivityHelper.cs b/DistTestCore/Helpers/FullConnectivityHelper.cs index b69af0c0..bad45f0d 100644 --- a/DistTestCore/Helpers/FullConnectivityHelper.cs +++ b/DistTestCore/Helpers/FullConnectivityHelper.cs @@ -1,199 +1,199 @@ -using DistTestCore.Codex; -using Logging; -using NUnit.Framework; +//using DistTestCore.Codex; +//using Logging; +//using NUnit.Framework; -namespace DistTestCore.Helpers -{ - public interface IFullConnectivityImplementation - { - string Description(); - string ValidateEntry(FullConnectivityHelper.Entry entry, FullConnectivityHelper.Entry[] allEntries); - FullConnectivityHelper.PeerConnectionState Check(FullConnectivityHelper.Entry from, FullConnectivityHelper.Entry to); - } +//namespace DistTestCore.Helpers +//{ +// public interface IFullConnectivityImplementation +// { +// string Description(); +// string ValidateEntry(FullConnectivityHelper.Entry entry, FullConnectivityHelper.Entry[] allEntries); +// FullConnectivityHelper.PeerConnectionState Check(FullConnectivityHelper.Entry from, FullConnectivityHelper.Entry to); +// } - public class FullConnectivityHelper - { - private static string Nl = Environment.NewLine; - private readonly BaseLog log; - private readonly IFullConnectivityImplementation implementation; +// public class FullConnectivityHelper +// { +// private static string Nl = Environment.NewLine; +// private readonly BaseLog log; +// private readonly IFullConnectivityImplementation implementation; - public FullConnectivityHelper(BaseLog log, IFullConnectivityImplementation implementation) - { - this.log = log; - this.implementation = implementation; - } +// public FullConnectivityHelper(BaseLog log, IFullConnectivityImplementation implementation) +// { +// this.log = log; +// this.implementation = implementation; +// } - public void AssertFullyConnected(IEnumerable nodes) - { - AssertFullyConnected(nodes.ToArray()); - } +// public void AssertFullyConnected(IEnumerable nodes) +// { +// AssertFullyConnected(nodes.ToArray()); +// } - private void AssertFullyConnected(CodexAccess[] nodes) - { - Log($"Asserting '{implementation.Description()}' for nodes: '{string.Join(",", nodes.Select(n => n.GetName()))}'..."); - var entries = CreateEntries(nodes); - var pairs = CreatePairs(entries); +// private void AssertFullyConnected(CodexAccess[] nodes) +// { +// Log($"Asserting '{implementation.Description()}' for nodes: '{string.Join(",", nodes.Select(n => n.GetName()))}'..."); +// var entries = CreateEntries(nodes); +// var pairs = CreatePairs(entries); - // Each pair gets two chances. - CheckAndRemoveSuccessful(pairs); - CheckAndRemoveSuccessful(pairs); +// // Each pair gets two chances. +// CheckAndRemoveSuccessful(pairs); +// CheckAndRemoveSuccessful(pairs); - if (pairs.Any()) - { - var pairDetails = string.Join(Nl, pairs.SelectMany(p => p.GetResultMessages())); +// if (pairs.Any()) +// { +// var pairDetails = string.Join(Nl, pairs.SelectMany(p => p.GetResultMessages())); - Log($"Connections failed:{Nl}{pairDetails}"); +// Log($"Connections failed:{Nl}{pairDetails}"); - Assert.Fail(string.Join(Nl, pairs.SelectMany(p => p.GetResultMessages()))); - } - else - { - Log($"'{implementation.Description()}' = Success! for nodes: {string.Join(",", nodes.Select(n => n.GetName()))}"); - } - } +// Assert.Fail(string.Join(Nl, pairs.SelectMany(p => p.GetResultMessages()))); +// } +// else +// { +// Log($"'{implementation.Description()}' = Success! for nodes: {string.Join(",", nodes.Select(n => n.GetName()))}"); +// } +// } - private void CheckAndRemoveSuccessful(List pairs) - { - var results = new List(); - foreach (var pair in pairs.ToArray()) - { - pair.Check(); - if (pair.Success) - { - results.AddRange(pair.GetResultMessages()); - pairs.Remove(pair); - } - } - Log($"Connections successful:{Nl}{string.Join(Nl, results)}"); - } +// private void CheckAndRemoveSuccessful(List pairs) +// { +// var results = new List(); +// foreach (var pair in pairs.ToArray()) +// { +// pair.Check(); +// if (pair.Success) +// { +// results.AddRange(pair.GetResultMessages()); +// pairs.Remove(pair); +// } +// } +// Log($"Connections successful:{Nl}{string.Join(Nl, results)}"); +// } - private Entry[] CreateEntries(CodexAccess[] nodes) - { - var entries = nodes.Select(n => new Entry(n)).ToArray(); +// private Entry[] CreateEntries(CodexAccess[] nodes) +// { +// var entries = nodes.Select(n => new Entry(n)).ToArray(); - var errors = entries - .Select(e => implementation.ValidateEntry(e, entries)) - .Where(s => !string.IsNullOrEmpty(s)) - .ToArray(); +// var errors = entries +// .Select(e => implementation.ValidateEntry(e, entries)) +// .Where(s => !string.IsNullOrEmpty(s)) +// .ToArray(); - if (errors.Any()) - { - Assert.Fail("Some node entries failed to validate: " + string.Join(Nl, errors)); - } +// if (errors.Any()) +// { +// Assert.Fail("Some node entries failed to validate: " + string.Join(Nl, errors)); +// } - return entries; - } +// return entries; +// } - private List CreatePairs(Entry[] entries) - { - return CreatePairsIterator(entries).ToList(); - } +// private List CreatePairs(Entry[] entries) +// { +// return CreatePairsIterator(entries).ToList(); +// } - private IEnumerable CreatePairsIterator(Entry[] entries) - { - for (var x = 0; x < entries.Length; x++) - { - for (var y = x + 1; y < entries.Length; y++) - { - yield return new Pair(implementation, entries[x], entries[y]); - } - } - } +// private IEnumerable CreatePairsIterator(Entry[] entries) +// { +// for (var x = 0; x < entries.Length; x++) +// { +// for (var y = x + 1; y < entries.Length; y++) +// { +// yield return new Pair(implementation, entries[x], entries[y]); +// } +// } +// } - private void Log(string msg) - { - log.Log(msg); - } +// private void Log(string msg) +// { +// log.Log(msg); +// } - public class Entry - { - public Entry(CodexAccess node) - { - Node = node; - Response = node.GetDebugInfo(); - } +// public class Entry +// { +// public Entry(CodexAccess node) +// { +// Node = node; +// Response = node.GetDebugInfo(); +// } - public CodexAccess Node { get; } - public CodexDebugResponse Response { get; } +// public CodexAccess Node { get; } +// public CodexDebugResponse Response { get; } - public override string ToString() - { - if (Response == null || string.IsNullOrEmpty(Response.id)) return "UNKNOWN"; - return Response.id; - } - } +// public override string ToString() +// { +// if (Response == null || string.IsNullOrEmpty(Response.id)) return "UNKNOWN"; +// return Response.id; +// } +// } - public enum PeerConnectionState - { - Unknown, - Connection, - NoConnection, - } +// public enum PeerConnectionState +// { +// Unknown, +// Connection, +// NoConnection, +// } - public class Pair - { - private TimeSpan aToBTime = TimeSpan.FromSeconds(0); - private TimeSpan bToATime = TimeSpan.FromSeconds(0); - private readonly IFullConnectivityImplementation implementation; +// public class Pair +// { +// private TimeSpan aToBTime = TimeSpan.FromSeconds(0); +// private TimeSpan bToATime = TimeSpan.FromSeconds(0); +// private readonly IFullConnectivityImplementation implementation; - public Pair(IFullConnectivityImplementation implementation, Entry a, Entry b) - { - this.implementation = implementation; - A = a; - B = b; - } +// public Pair(IFullConnectivityImplementation implementation, Entry a, Entry b) +// { +// this.implementation = implementation; +// A = a; +// B = b; +// } - public Entry A { get; } - public Entry B { get; } - public PeerConnectionState AKnowsB { get; private set; } - public PeerConnectionState BKnowsA { get; private set; } - public bool Success { get { return AKnowsB == PeerConnectionState.Connection && BKnowsA == PeerConnectionState.Connection; } } - public bool Inconclusive { get { return AKnowsB == PeerConnectionState.Unknown || BKnowsA == PeerConnectionState.Unknown; } } +// public Entry A { get; } +// public Entry B { get; } +// public PeerConnectionState AKnowsB { get; private set; } +// public PeerConnectionState BKnowsA { get; private set; } +// public bool Success { get { return AKnowsB == PeerConnectionState.Connection && BKnowsA == PeerConnectionState.Connection; } } +// public bool Inconclusive { get { return AKnowsB == PeerConnectionState.Unknown || BKnowsA == PeerConnectionState.Unknown; } } - public void Check() - { - aToBTime = Measure(() => AKnowsB = Check(A, B)); - bToATime = Measure(() => BKnowsA = Check(B, A)); - } +// public void Check() +// { +// aToBTime = Measure(() => AKnowsB = Check(A, B)); +// bToATime = Measure(() => BKnowsA = Check(B, A)); +// } - public override string ToString() - { - return $"[{string.Join(",", GetResultMessages())}]"; - } +// public override string ToString() +// { +// return $"[{string.Join(",", GetResultMessages())}]"; +// } - public string[] GetResultMessages() - { - var aName = A.ToString(); - var bName = B.ToString(); +// public string[] GetResultMessages() +// { +// var aName = A.ToString(); +// var bName = B.ToString(); - return new[] - { - $"[{aName} --> {bName}] = {AKnowsB} ({aToBTime.TotalSeconds} seconds)", - $"[{aName} <-- {bName}] = {BKnowsA} ({bToATime.TotalSeconds} seconds)" - }; - } +// return new[] +// { +// $"[{aName} --> {bName}] = {AKnowsB} ({aToBTime.TotalSeconds} seconds)", +// $"[{aName} <-- {bName}] = {BKnowsA} ({bToATime.TotalSeconds} seconds)" +// }; +// } - private static TimeSpan Measure(Action action) - { - var start = DateTime.UtcNow; - action(); - return DateTime.UtcNow - start; - } +// private static TimeSpan Measure(Action action) +// { +// var start = DateTime.UtcNow; +// action(); +// return DateTime.UtcNow - start; +// } - private PeerConnectionState Check(Entry from, Entry to) - { - Thread.Sleep(10); +// private PeerConnectionState Check(Entry from, Entry to) +// { +// Thread.Sleep(10); - try - { - return implementation.Check(from, to); - } - catch - { - // Didn't get a conclusive answer. Try again later. - return PeerConnectionState.Unknown; - } - } - } - } -} +// try +// { +// return implementation.Check(from, to); +// } +// catch +// { +// // Didn't get a conclusive answer. Try again later. +// return PeerConnectionState.Unknown; +// } +// } +// } +// } +//} diff --git a/DistTestCore/Helpers/PeerConnectionTestHelpers.cs b/DistTestCore/Helpers/PeerConnectionTestHelpers.cs index 65bb4ce0..39b7004a 100644 --- a/DistTestCore/Helpers/PeerConnectionTestHelpers.cs +++ b/DistTestCore/Helpers/PeerConnectionTestHelpers.cs @@ -1,71 +1,71 @@ -using DistTestCore.Codex; -using Logging; -using static DistTestCore.Helpers.FullConnectivityHelper; +//using DistTestCore.Codex; +//using Logging; +//using static DistTestCore.Helpers.FullConnectivityHelper; -namespace DistTestCore.Helpers -{ - public class PeerConnectionTestHelpers : IFullConnectivityImplementation - { - private readonly FullConnectivityHelper helper; +//namespace DistTestCore.Helpers +//{ +// public class PeerConnectionTestHelpers : IFullConnectivityImplementation +// { +// private readonly FullConnectivityHelper helper; - public PeerConnectionTestHelpers(BaseLog log) - { - helper = new FullConnectivityHelper(log, this); - } +// public PeerConnectionTestHelpers(BaseLog log) +// { +// helper = new FullConnectivityHelper(log, this); +// } - public void AssertFullyConnected(IEnumerable nodes) - { - AssertFullyConnected(nodes.Select(n => ((OnlineCodexNode)n).CodexAccess)); - } +// public void AssertFullyConnected(IEnumerable nodes) +// { +// AssertFullyConnected(nodes.Select(n => ((OnlineCodexNode)n).CodexAccess)); +// } - public void AssertFullyConnected(IEnumerable nodes) - { - helper.AssertFullyConnected(nodes); - } +// public void AssertFullyConnected(IEnumerable nodes) +// { +// helper.AssertFullyConnected(nodes); +// } - public string Description() - { - return "Peer Discovery"; - } +// public string Description() +// { +// return "Peer Discovery"; +// } - public string ValidateEntry(Entry entry, Entry[] allEntries) - { - var result = string.Empty; - foreach (var peer in entry.Response.table.nodes) - { - var expected = GetExpectedDiscoveryEndpoint(allEntries, peer); - if (expected != peer.address) - { - result += $"Node:{entry.Node.GetName()} has incorrect peer table entry. Was: '{peer.address}', expected: '{expected}'. "; - } - } - return result; - } +// public string ValidateEntry(Entry entry, Entry[] allEntries) +// { +// var result = string.Empty; +// foreach (var peer in entry.Response.table.nodes) +// { +// var expected = GetExpectedDiscoveryEndpoint(allEntries, peer); +// if (expected != peer.address) +// { +// result += $"Node:{entry.Node.GetName()} has incorrect peer table entry. Was: '{peer.address}', expected: '{expected}'. "; +// } +// } +// return result; +// } - public PeerConnectionState Check(Entry from, Entry to) - { - var peerId = to.Response.id; +// public PeerConnectionState Check(Entry from, Entry to) +// { +// var peerId = to.Response.id; - var response = from.Node.GetDebugPeer(peerId); - if (!response.IsPeerFound) - { - return PeerConnectionState.NoConnection; - } - if (!string.IsNullOrEmpty(response.peerId) && response.addresses.Any()) - { - return PeerConnectionState.Connection; - } - return PeerConnectionState.Unknown; - } +// var response = from.Node.GetDebugPeer(peerId); +// if (!response.IsPeerFound) +// { +// return PeerConnectionState.NoConnection; +// } +// if (!string.IsNullOrEmpty(response.peerId) && response.addresses.Any()) +// { +// return PeerConnectionState.Connection; +// } +// return PeerConnectionState.Unknown; +// } - private static string GetExpectedDiscoveryEndpoint(Entry[] allEntries, CodexDebugTableNodeResponse node) - { - var peer = allEntries.SingleOrDefault(e => e.Response.table.localNode.peerId == node.peerId); - if (peer == null) return $"peerId: {node.peerId} is not known."; +// private static string GetExpectedDiscoveryEndpoint(Entry[] allEntries, CodexDebugTableNodeResponse node) +// { +// var peer = allEntries.SingleOrDefault(e => e.Response.table.localNode.peerId == node.peerId); +// if (peer == null) return $"peerId: {node.peerId} is not known."; - var ip = peer.Node.Container.Pod.PodInfo.Ip; - var discPort = peer.Node.Container.Recipe.GetPortByTag(CodexContainerRecipe.DiscoveryPortTag); - return $"{ip}:{discPort.Number}"; - } - } -} +// var ip = peer.Node.Container.Pod.PodInfo.Ip; +// var discPort = peer.Node.Container.Recipe.GetPortByTag(CodexContainerRecipe.DiscoveryPortTag); +// return $"{ip}:{discPort.Number}"; +// } +// } +//} diff --git a/DistTestCore/Helpers/PeerDownloadTestHelpers.cs b/DistTestCore/Helpers/PeerDownloadTestHelpers.cs index d5411940..6c535cce 100644 --- a/DistTestCore/Helpers/PeerDownloadTestHelpers.cs +++ b/DistTestCore/Helpers/PeerDownloadTestHelpers.cs @@ -1,89 +1,89 @@ -using DistTestCore.Codex; -using FileUtils; -using Logging; -using Utils; -using static DistTestCore.Helpers.FullConnectivityHelper; +//using DistTestCore.Codex; +//using FileUtils; +//using Logging; +//using Utils; +//using static DistTestCore.Helpers.FullConnectivityHelper; -namespace DistTestCore.Helpers -{ - public class PeerDownloadTestHelpers : IFullConnectivityImplementation - { - private readonly FullConnectivityHelper helper; - private readonly BaseLog log; - private readonly FileManager fileManager; - private ByteSize testFileSize; +//namespace DistTestCore.Helpers +//{ +// public class PeerDownloadTestHelpers : IFullConnectivityImplementation +// { +// private readonly FullConnectivityHelper helper; +// private readonly BaseLog log; +// private readonly FileManager fileManager; +// private ByteSize testFileSize; - public PeerDownloadTestHelpers(BaseLog log, FileManager fileManager) - { - helper = new FullConnectivityHelper(log, this); - testFileSize = 1.MB(); - this.log = log; - this.fileManager = fileManager; - } +// public PeerDownloadTestHelpers(BaseLog log, FileManager fileManager) +// { +// helper = new FullConnectivityHelper(log, this); +// testFileSize = 1.MB(); +// this.log = log; +// this.fileManager = fileManager; +// } - public void AssertFullDownloadInterconnectivity(IEnumerable nodes, ByteSize testFileSize) - { - AssertFullDownloadInterconnectivity(nodes.Select(n => ((OnlineCodexNode)n).CodexAccess), testFileSize); - } +// public void AssertFullDownloadInterconnectivity(IEnumerable nodes, ByteSize testFileSize) +// { +// AssertFullDownloadInterconnectivity(nodes.Select(n => ((OnlineCodexNode)n).CodexAccess), testFileSize); +// } - public void AssertFullDownloadInterconnectivity(IEnumerable nodes, ByteSize testFileSize) - { - this.testFileSize = testFileSize; - helper.AssertFullyConnected(nodes); - } +// public void AssertFullDownloadInterconnectivity(IEnumerable nodes, ByteSize testFileSize) +// { +// this.testFileSize = testFileSize; +// helper.AssertFullyConnected(nodes); +// } - public string Description() - { - return "Download Connectivity"; - } +// public string Description() +// { +// return "Download Connectivity"; +// } - public string ValidateEntry(Entry entry, Entry[] allEntries) - { - return string.Empty; - } +// public string ValidateEntry(Entry entry, Entry[] allEntries) +// { +// return string.Empty; +// } - public PeerConnectionState Check(Entry from, Entry to) - { - return fileManager.ScopedFiles(() => CheckConnectivity(from, to)); - } +// public PeerConnectionState Check(Entry from, Entry to) +// { +// return fileManager.ScopedFiles(() => CheckConnectivity(from, to)); +// } - private PeerConnectionState CheckConnectivity(Entry from, Entry to) - { - var expectedFile = GenerateTestFile(from.Node, to.Node); +// private PeerConnectionState CheckConnectivity(Entry from, Entry to) +// { +// var expectedFile = GenerateTestFile(from.Node, to.Node); - using var uploadStream = File.OpenRead(expectedFile.Filename); - var contentId = Stopwatch.Measure(log, "Upload", () => from.Node.UploadFile(uploadStream)); +// using var uploadStream = File.OpenRead(expectedFile.Filename); +// var contentId = Stopwatch.Measure(log, "Upload", () => from.Node.UploadFile(uploadStream)); - try - { - var downloadedFile = Stopwatch.Measure(log, "Download", () => DownloadFile(to.Node, contentId, expectedFile.Label + "_downloaded")); - expectedFile.AssertIsEqual(downloadedFile); - return PeerConnectionState.Connection; - } - catch - { - // Should an exception occur during the download or file-content assertion, - // We consider that as no-connection for the purpose of this test. - return PeerConnectionState.NoConnection; - } - // Should an exception occur during upload, then this try is inconclusive and we try again next loop. - } +// try +// { +// var downloadedFile = Stopwatch.Measure(log, "Download", () => DownloadFile(to.Node, contentId, expectedFile.Label + "_downloaded")); +// expectedFile.AssertIsEqual(downloadedFile); +// return PeerConnectionState.Connection; +// } +// catch +// { +// // Should an exception occur during the download or file-content assertion, +// // We consider that as no-connection for the purpose of this test. +// return PeerConnectionState.NoConnection; +// } +// // Should an exception occur during upload, then this try is inconclusive and we try again next loop. +// } - private TestFile DownloadFile(CodexAccess node, string contentId, string label) - { - var downloadedFile = fileManager.CreateEmptyTestFile(label); - using var downloadStream = File.OpenWrite(downloadedFile.Filename); - using var stream = node.DownloadFile(contentId); - stream.CopyTo(downloadStream); - return downloadedFile; - } +// private TestFile DownloadFile(CodexAccess node, string contentId, string label) +// { +// var downloadedFile = fileManager.CreateEmptyTestFile(label); +// using var downloadStream = File.OpenWrite(downloadedFile.Filename); +// using var stream = node.DownloadFile(contentId); +// stream.CopyTo(downloadStream); +// return downloadedFile; +// } - private TestFile GenerateTestFile(CodexAccess uploader, CodexAccess downloader) - { - var up = uploader.GetName().Replace("<", "").Replace(">", ""); - var down = downloader.GetName().Replace("<", "").Replace(">", ""); - var label = $"~from:{up}-to:{down}~"; - return fileManager.GenerateTestFile(testFileSize, label); - } - } -} +// private TestFile GenerateTestFile(CodexAccess uploader, CodexAccess downloader) +// { +// var up = uploader.GetName().Replace("<", "").Replace(">", ""); +// var down = downloader.GetName().Replace("<", "").Replace(">", ""); +// var label = $"~from:{up}-to:{down}~"; +// return fileManager.GenerateTestFile(testFileSize, label); +// } +// } +//} diff --git a/DistTestCore/Marketplace/CodexContractsContainerConfig.cs b/DistTestCore/Marketplace/CodexContractsContainerConfig.cs deleted file mode 100644 index 3b669a4b..00000000 --- a/DistTestCore/Marketplace/CodexContractsContainerConfig.cs +++ /dev/null @@ -1,16 +0,0 @@ -using KubernetesWorkflow; - -namespace DistTestCore.Marketplace -{ - public class CodexContractsContainerConfig - { - public CodexContractsContainerConfig(string bootstrapNodeIp, Port jsonRpcPort) - { - BootstrapNodeIp = bootstrapNodeIp; - JsonRpcPort = jsonRpcPort; - } - - public string BootstrapNodeIp { get; } - public Port JsonRpcPort { get; } - } -} diff --git a/DistTestCore/Marketplace/CodexContractsContainerRecipe.cs b/DistTestCore/Marketplace/CodexContractsContainerRecipe.cs deleted file mode 100644 index bd2c906c..00000000 --- a/DistTestCore/Marketplace/CodexContractsContainerRecipe.cs +++ /dev/null @@ -1,25 +0,0 @@ -using KubernetesWorkflow; - -namespace DistTestCore.Marketplace -{ - public class CodexContractsContainerRecipe : DefaultContainerRecipe - { - public const string MarketplaceAddressFilename = "/hardhat/deployments/codexdisttestnetwork/Marketplace.json"; - public const string MarketplaceArtifactFilename = "/hardhat/artifacts/contracts/Marketplace.sol/Marketplace.json"; - - public override string AppName => "codex-contracts"; - public override string Image => "codexstorage/codex-contracts-eth:latest-dist-tests"; - - protected override void InitializeRecipe(StartupConfig startupConfig) - { - var config = startupConfig.Get(); - - var ip = config.BootstrapNodeIp; - var port = config.JsonRpcPort.Number; - - AddEnvVar("DISTTEST_NETWORK_URL", $"http://{ip}:{port}"); - AddEnvVar("HARDHAT_NETWORK", "codexdisttestnetwork"); - AddEnvVar("KEEP_ALIVE", "1"); - } - } -} diff --git a/DistTestCore/Marketplace/CodexContractsStarter.cs b/DistTestCore/Marketplace/CodexContractsStarter.cs deleted file mode 100644 index 4d628b6f..00000000 --- a/DistTestCore/Marketplace/CodexContractsStarter.cs +++ /dev/null @@ -1,103 +0,0 @@ -using KubernetesWorkflow; -using Utils; - -namespace DistTestCore.Marketplace -{ - public class CodexContractsStarter : BaseStarter - { - - public CodexContractsStarter(TestLifecycle lifecycle) - : base(lifecycle) - { - } - - public MarketplaceInfo Start(GethBootstrapNodeInfo bootstrapNode) - { - LogStart("Deploying Codex Marketplace..."); - - var workflow = lifecycle.WorkflowCreator.CreateWorkflow(); - var startupConfig = CreateStartupConfig(bootstrapNode.RunningContainers.Containers[0]); - - var containers = workflow.Start(1, Location.Unspecified, new CodexContractsContainerRecipe(), startupConfig); - if (containers.Containers.Length != 1) throw new InvalidOperationException("Expected 1 Codex contracts container to be created. Test infra failure."); - var container = containers.Containers[0]; - - WaitUntil(() => - { - var logHandler = new ContractsReadyLogHandler(Debug); - workflow.DownloadContainerLog(container, logHandler, null); - return logHandler.Found; - }); - Log("Contracts deployed. Extracting addresses..."); - - var extractor = new ContainerInfoExtractor(lifecycle.Log, workflow, container); - var marketplaceAddress = extractor.ExtractMarketplaceAddress(); - var abi = extractor.ExtractMarketplaceAbi(); - - var interaction = bootstrapNode.StartInteraction(lifecycle); - var tokenAddress = interaction.GetTokenAddress(marketplaceAddress); - - LogEnd("Extract completed. Marketplace deployed."); - - return new MarketplaceInfo(marketplaceAddress, abi, tokenAddress); - } - - private void WaitUntil(Func predicate) - { - Time.WaitUntil(predicate, TimeSpan.FromMinutes(3), TimeSpan.FromSeconds(2)); - } - - private StartupConfig CreateStartupConfig(RunningContainer bootstrapContainer) - { - var startupConfig = new StartupConfig(); - var contractsConfig = new CodexContractsContainerConfig(bootstrapContainer.Pod.PodInfo.Ip, bootstrapContainer.Recipe.GetPortByTag(GethContainerRecipe.HttpPortTag)); - startupConfig.Add(contractsConfig); - return startupConfig; - } - } - - public class MarketplaceInfo - { - public MarketplaceInfo(string address, string abi, string tokenAddress) - { - Address = address; - Abi = abi; - TokenAddress = tokenAddress; - } - - public string Address { get; } - public string Abi { get; } - public string TokenAddress { get; } - } - - public class ContractsReadyLogHandler : LogHandler - { - // Log should contain 'Compiled 15 Solidity files successfully' at some point. - private const string RequiredCompiledString = "Solidity files successfully"; - // When script is done, it prints the ready-string. - private const string ReadyString = "Done! Sleeping indefinitely..."; - private readonly Action debug; - - public ContractsReadyLogHandler(Action debug) - { - this.debug = debug; - debug($"Looking for '{RequiredCompiledString}' and '{ReadyString}' in container logs..."); - } - - public bool SeenCompileString { get; private set; } - public bool Found { get; private set; } - - protected override void ProcessLine(string line) - { - debug(line); - if (line.Contains(RequiredCompiledString)) SeenCompileString = true; - if (line.Contains(ReadyString)) - { - if (!SeenCompileString) throw new Exception("CodexContracts deployment failed. " + - "Solidity files not compiled before process exited."); - - Found = true; - } - } - } -} diff --git a/DistTestCore/Marketplace/ContainerInfoExtractor.cs b/DistTestCore/Marketplace/ContainerInfoExtractor.cs deleted file mode 100644 index 1eac5cbc..00000000 --- a/DistTestCore/Marketplace/ContainerInfoExtractor.cs +++ /dev/null @@ -1,149 +0,0 @@ -using KubernetesWorkflow; -using Logging; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using Utils; - -namespace DistTestCore.Marketplace -{ - public class ContainerInfoExtractor - { - private readonly BaseLog log; - private readonly StartupWorkflow workflow; - private readonly RunningContainer container; - - public ContainerInfoExtractor(BaseLog log, StartupWorkflow workflow, RunningContainer container) - { - this.log = log; - this.workflow = workflow; - this.container = container; - } - - public AllGethAccounts ExtractAccounts() - { - log.Debug(); - var accountsCsv = Retry(() => FetchAccountsCsv()); - if (string.IsNullOrEmpty(accountsCsv)) throw new InvalidOperationException("Unable to fetch accounts.csv for geth node. Test infra failure."); - - var lines = accountsCsv.Split('\n'); - return new AllGethAccounts(lines.Select(ParseLineToAccount).ToArray()); - } - - public string ExtractPubKey() - { - log.Debug(); - var pubKey = Retry(FetchPubKey); - if (string.IsNullOrEmpty(pubKey)) throw new InvalidOperationException("Unable to fetch enode from geth node. Test infra failure."); - - return pubKey; - } - - public string ExtractMarketplaceAddress() - { - log.Debug(); - var marketplaceAddress = Retry(FetchMarketplaceAddress); - if (string.IsNullOrEmpty(marketplaceAddress)) throw new InvalidOperationException("Unable to fetch marketplace account from codex-contracts node. Test infra failure."); - - return marketplaceAddress; - } - - public string ExtractMarketplaceAbi() - { - log.Debug(); - var marketplaceAbi = Retry(FetchMarketplaceAbi); - if (string.IsNullOrEmpty(marketplaceAbi)) throw new InvalidOperationException("Unable to fetch marketplace artifacts from codex-contracts node. Test infra failure."); - - return marketplaceAbi; - } - - private string FetchAccountsCsv() - { - return workflow.ExecuteCommand(container, "cat", GethContainerRecipe.AccountsFilename); - } - - private string FetchMarketplaceAddress() - { - var json = workflow.ExecuteCommand(container, "cat", CodexContractsContainerRecipe.MarketplaceAddressFilename); - var marketplace = JsonConvert.DeserializeObject(json); - return marketplace!.address; - } - - private string FetchMarketplaceAbi() - { - var json = workflow.ExecuteCommand(container, "cat", CodexContractsContainerRecipe.MarketplaceArtifactFilename); - - var artifact = JObject.Parse(json); - var abi = artifact["abi"]; - return abi!.ToString(Formatting.None); - } - - private string FetchPubKey() - { - var enodeFinder = new PubKeyFinder(s => log.Debug(s)); - workflow.DownloadContainerLog(container, enodeFinder, null); - return enodeFinder.GetPubKey(); - } - - private GethAccount ParseLineToAccount(string l) - { - var tokens = l.Replace("\r", "").Split(','); - if (tokens.Length != 2) throw new InvalidOperationException(); - var account = tokens[0]; - var privateKey = tokens[1]; - return new GethAccount(account, privateKey); - } - - private static string Retry(Func fetch) - { - return Time.Retry(fetch, nameof(ContainerInfoExtractor)); - } - } - - public class PubKeyFinder : LogHandler, ILogHandler - { - private const string openTag = "self=enode://"; - private const string openTagQuote = "self=\"enode://"; - private readonly Action debug; - private string pubKey = string.Empty; - - public PubKeyFinder(Action debug) - { - this.debug = debug; - debug($"Looking for '{openTag}' in container logs..."); - } - - public string GetPubKey() - { - if (string.IsNullOrEmpty(pubKey)) throw new Exception("Not found yet exception."); - return pubKey; - } - - protected override void ProcessLine(string line) - { - debug(line); - if (line.Contains(openTag)) - { - ExtractPubKey(openTag, line); - } - else if (line.Contains(openTagQuote)) - { - ExtractPubKey(openTagQuote, line); - } - } - - private void ExtractPubKey(string tag, string line) - { - var openIndex = line.IndexOf(tag) + tag.Length; - var closeIndex = line.IndexOf("@"); - - pubKey = line.Substring( - startIndex: openIndex, - length: closeIndex - openIndex); - } - } - - public class MarketplaceJson - { - public string address { get; set; } = string.Empty; - } -} diff --git a/DistTestCore/Marketplace/GethBootstrapNodeInfo.cs b/DistTestCore/Marketplace/GethBootstrapNodeInfo.cs deleted file mode 100644 index 6825ba58..00000000 --- a/DistTestCore/Marketplace/GethBootstrapNodeInfo.cs +++ /dev/null @@ -1,42 +0,0 @@ -using KubernetesWorkflow; -using NethereumWorkflow; - -namespace DistTestCore.Marketplace -{ - public class GethBootstrapNodeInfo - { - public GethBootstrapNodeInfo(RunningContainers runningContainers, AllGethAccounts allAccounts, string pubKey, Port discoveryPort) - { - RunningContainers = runningContainers; - AllAccounts = allAccounts; - Account = allAccounts.Accounts[0]; - PubKey = pubKey; - DiscoveryPort = discoveryPort; - } - - public RunningContainers RunningContainers { get; } - public AllGethAccounts AllAccounts { get; } - public GethAccount Account { get; } - public string PubKey { get; } - public Port DiscoveryPort { get; } - - public NethereumInteraction StartInteraction(TestLifecycle lifecycle) - { - var address = lifecycle.Configuration.GetAddress(RunningContainers.Containers[0]); - var account = Account; - - var creator = new NethereumInteractionCreator(lifecycle.Log, address.Host, address.Port, account.PrivateKey); - return creator.CreateWorkflow(); - } - } - - public class AllGethAccounts - { - public GethAccount[] Accounts { get; } - - public AllGethAccounts(GethAccount[] accounts) - { - Accounts = accounts; - } - } -} diff --git a/DistTestCore/Marketplace/GethBootstrapNodeStarter.cs b/DistTestCore/Marketplace/GethBootstrapNodeStarter.cs deleted file mode 100644 index d1ebb547..00000000 --- a/DistTestCore/Marketplace/GethBootstrapNodeStarter.cs +++ /dev/null @@ -1,40 +0,0 @@ -using KubernetesWorkflow; - -namespace DistTestCore.Marketplace -{ - public class GethBootstrapNodeStarter : BaseStarter - { - public GethBootstrapNodeStarter(TestLifecycle lifecycle) - : base(lifecycle) - { - } - - public GethBootstrapNodeInfo StartGethBootstrapNode() - { - LogStart("Starting Geth bootstrap node..."); - var startupConfig = CreateBootstrapStartupConfig(); - - var workflow = lifecycle.WorkflowCreator.CreateWorkflow(); - var containers = workflow.Start(1, Location.Unspecified, new GethContainerRecipe(), startupConfig); - if (containers.Containers.Length != 1) throw new InvalidOperationException("Expected 1 Geth bootstrap node to be created. Test infra failure."); - var bootstrapContainer = containers.Containers[0]; - - var extractor = new ContainerInfoExtractor(lifecycle.Log, workflow, bootstrapContainer); - var accounts = extractor.ExtractAccounts(); - var pubKey = extractor.ExtractPubKey(); - var discoveryPort = bootstrapContainer.Recipe.GetPortByTag(GethContainerRecipe.DiscoveryPortTag); - var result = new GethBootstrapNodeInfo(containers, accounts, pubKey, discoveryPort); - - LogEnd($"Geth bootstrap node started with account '{result.Account.Account}'"); - - return result; - } - - private StartupConfig CreateBootstrapStartupConfig() - { - var config = new StartupConfig(); - config.Add(new GethStartupConfig(true, null!, 0, 0)); - return config; - } - } -} diff --git a/DistTestCore/Marketplace/GethCompanionNodeInfo.cs b/DistTestCore/Marketplace/GethCompanionNodeInfo.cs deleted file mode 100644 index 3230d2a5..00000000 --- a/DistTestCore/Marketplace/GethCompanionNodeInfo.cs +++ /dev/null @@ -1,38 +0,0 @@ -using KubernetesWorkflow; -using NethereumWorkflow; - -namespace DistTestCore.Marketplace -{ - public class GethCompanionNodeInfo - { - public GethCompanionNodeInfo(RunningContainer runningContainer, GethAccount[] accounts) - { - RunningContainer = runningContainer; - Accounts = accounts; - } - - public RunningContainer RunningContainer { get; } - public GethAccount[] Accounts { get; } - - public NethereumInteraction StartInteraction(TestLifecycle lifecycle, GethAccount account) - { - var address = lifecycle.Configuration.GetAddress(RunningContainer); - var privateKey = account.PrivateKey; - - var creator = new NethereumInteractionCreator(lifecycle.Log, address.Host, address.Port, privateKey); - return creator.CreateWorkflow(); - } - } - - public class GethAccount - { - public GethAccount(string account, string privateKey) - { - Account = account; - PrivateKey = privateKey; - } - - public string Account { get; } - public string PrivateKey { get; } - } -} diff --git a/DistTestCore/Marketplace/GethCompanionNodeStarter.cs b/DistTestCore/Marketplace/GethCompanionNodeStarter.cs deleted file mode 100644 index 6759e7b4..00000000 --- a/DistTestCore/Marketplace/GethCompanionNodeStarter.cs +++ /dev/null @@ -1,77 +0,0 @@ -using KubernetesWorkflow; -using Utils; - -namespace DistTestCore.Marketplace -{ - public class GethCompanionNodeStarter : BaseStarter - { - private int companionAccountIndex = 0; - - public GethCompanionNodeStarter(TestLifecycle lifecycle) - : base(lifecycle) - { - } - - public GethCompanionNodeInfo StartCompanionNodeFor(CodexSetup codexSetup, MarketplaceNetwork marketplace) - { - LogStart($"Initializing companion for {codexSetup.NumberOfNodes} Codex nodes."); - - var config = CreateCompanionNodeStartupConfig(marketplace.Bootstrap, codexSetup.NumberOfNodes); - - var workflow = lifecycle.WorkflowCreator.CreateWorkflow(); - var containers = workflow.Start(1, Location.Unspecified, new GethContainerRecipe(), CreateStartupConfig(config)); - if (containers.Containers.Length != 1) throw new InvalidOperationException("Expected one Geth companion node to be created. Test infra failure."); - var container = containers.Containers[0]; - - var node = CreateCompanionInfo(container, marketplace, config); - EnsureCompanionNodeIsSynced(node, marketplace); - - LogEnd($"Initialized one companion node for {codexSetup.NumberOfNodes} Codex nodes. Their accounts: [{string.Join(",", node.Accounts.Select(a => a.Account))}]"); - return node; - } - - private GethCompanionNodeInfo CreateCompanionInfo(RunningContainer container, MarketplaceNetwork marketplace, GethStartupConfig config) - { - var accounts = ExtractAccounts(marketplace, config); - return new GethCompanionNodeInfo(container, accounts); - } - - private static GethAccount[] ExtractAccounts(MarketplaceNetwork marketplace, GethStartupConfig config) - { - return marketplace.Bootstrap.AllAccounts.Accounts - .Skip(1 + config.CompanionAccountStartIndex) - .Take(config.NumberOfCompanionAccounts) - .ToArray(); - } - - private void EnsureCompanionNodeIsSynced(GethCompanionNodeInfo node, MarketplaceNetwork marketplace) - { - try - { - Time.WaitUntil(() => - { - var interaction = node.StartInteraction(lifecycle, node.Accounts.First()); - return interaction.IsSynced(marketplace.Marketplace.Address, marketplace.Marketplace.Abi); - }, TimeSpan.FromMinutes(1), TimeSpan.FromSeconds(3)); - } - catch (Exception e) - { - throw new Exception("Geth companion node did not sync within timeout. Test infra failure.", e); - } - } - - private GethStartupConfig CreateCompanionNodeStartupConfig(GethBootstrapNodeInfo bootstrapNode, int numberOfAccounts) - { - var config = new GethStartupConfig(false, bootstrapNode, companionAccountIndex, numberOfAccounts); - companionAccountIndex += numberOfAccounts; - return config; - } - - private StartupConfig CreateStartupConfig(GethStartupConfig gethConfig) - { - var config = new StartupConfig(); - config.Add(gethConfig); - return config; - } - } -} diff --git a/DistTestCore/Marketplace/GethContainerRecipe.cs b/DistTestCore/Marketplace/GethContainerRecipe.cs deleted file mode 100644 index 540b1d33..00000000 --- a/DistTestCore/Marketplace/GethContainerRecipe.cs +++ /dev/null @@ -1,73 +0,0 @@ -using KubernetesWorkflow; - -namespace DistTestCore.Marketplace -{ - public class GethContainerRecipe : DefaultContainerRecipe - { - private const string defaultArgs = "--ipcdisable --syncmode full"; - - public const string HttpPortTag = "http_port"; - public const string DiscoveryPortTag = "disc_port"; - public const string AccountsFilename = "accounts.csv"; - - public override string AppName => "geth"; - public override string Image => "codexstorage/dist-tests-geth:latest"; - - protected override void InitializeRecipe(StartupConfig startupConfig) - { - var config = startupConfig.Get(); - - var args = CreateArgs(config); - - AddEnvVar("GETH_ARGS", args); - } - - private string CreateArgs(GethStartupConfig config) - { - var discovery = AddInternalPort(tag: DiscoveryPortTag); - - if (config.IsBootstrapNode) - { - return CreateBootstapArgs(discovery); - } - - return CreateCompanionArgs(discovery, config); - } - - private string CreateBootstapArgs(Port discovery) - { - AddEnvVar("ENABLE_MINER", "1"); - UnlockAccounts(0, 1); - var exposedPort = AddExposedPort(tag: HttpPortTag); - return $"--http.port {exposedPort.Number} --port {discovery.Number} --discovery.port {discovery.Number} {defaultArgs}"; - } - - private string CreateCompanionArgs(Port discovery, GethStartupConfig config) - { - UnlockAccounts( - config.CompanionAccountStartIndex + 1, - config.NumberOfCompanionAccounts); - - var port = AddInternalPort(); - var authRpc = AddInternalPort(); - var httpPort = AddExposedPort(tag: HttpPortTag); - - var bootPubKey = config.BootstrapNode.PubKey; - var bootIp = config.BootstrapNode.RunningContainers.Containers[0].Pod.PodInfo.Ip; - var bootPort = config.BootstrapNode.DiscoveryPort.Number; - var bootstrapArg = $"--bootnodes enode://{bootPubKey}@{bootIp}:{bootPort} --nat=extip:{bootIp}"; - - return $"--port {port.Number} --discovery.port {discovery.Number} --authrpc.port {authRpc.Number} --http.addr 0.0.0.0 --http.port {httpPort.Number} --ws --ws.addr 0.0.0.0 --ws.port {httpPort.Number} {bootstrapArg} {defaultArgs}"; - } - - private void UnlockAccounts(int startIndex, int numberOfAccounts) - { - if (startIndex < 0) throw new ArgumentException(); - if (numberOfAccounts < 1) throw new ArgumentException(); - if (startIndex + numberOfAccounts > 1000) throw new ArgumentException("Out of accounts!"); - - AddEnvVar("UNLOCK_START_INDEX", startIndex.ToString()); - AddEnvVar("UNLOCK_NUMBER", numberOfAccounts.ToString()); - } - } -} diff --git a/DistTestCore/Marketplace/GethStartResult.cs b/DistTestCore/Marketplace/GethStartResult.cs deleted file mode 100644 index 0ba1e58a..00000000 --- a/DistTestCore/Marketplace/GethStartResult.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Newtonsoft.Json; - -namespace DistTestCore.Marketplace -{ - public class GethStartResult - { - public GethStartResult(IMarketplaceAccessFactory marketplaceAccessFactory, MarketplaceNetwork marketplaceNetwork, GethCompanionNodeInfo companionNode) - { - MarketplaceAccessFactory = marketplaceAccessFactory; - MarketplaceNetwork = marketplaceNetwork; - CompanionNode = companionNode; - } - - [JsonIgnore] - public IMarketplaceAccessFactory MarketplaceAccessFactory { get; } - public MarketplaceNetwork MarketplaceNetwork { get; } - public GethCompanionNodeInfo CompanionNode { get; } - } -} diff --git a/DistTestCore/Marketplace/GethStartupConfig.cs b/DistTestCore/Marketplace/GethStartupConfig.cs deleted file mode 100644 index 7aee0788..00000000 --- a/DistTestCore/Marketplace/GethStartupConfig.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace DistTestCore.Marketplace -{ - public class GethStartupConfig - { - public GethStartupConfig(bool isBootstrapNode, GethBootstrapNodeInfo bootstrapNode, int companionAccountStartIndex, int numberOfCompanionAccounts) - { - IsBootstrapNode = isBootstrapNode; - BootstrapNode = bootstrapNode; - CompanionAccountStartIndex = companionAccountStartIndex; - NumberOfCompanionAccounts = numberOfCompanionAccounts; - } - - public bool IsBootstrapNode { get; } - public GethBootstrapNodeInfo BootstrapNode { get; } - public int CompanionAccountStartIndex { get; } - public int NumberOfCompanionAccounts { get; } - } -} diff --git a/DistTestCore/Marketplace/MarketplaceAccess.cs b/DistTestCore/Marketplace/MarketplaceAccess.cs deleted file mode 100644 index 06715826..00000000 --- a/DistTestCore/Marketplace/MarketplaceAccess.cs +++ /dev/null @@ -1,243 +0,0 @@ -using DistTestCore.Codex; -using DistTestCore.Helpers; -using Logging; -using Newtonsoft.Json; -using NUnit.Framework; -using NUnit.Framework.Constraints; -using System.Numerics; -using Utils; - -namespace DistTestCore.Marketplace -{ - public interface IMarketplaceAccess - { - string MakeStorageAvailable(ByteSize size, TestToken minPricePerBytePerSecond, TestToken maxCollateral, TimeSpan maxDuration); - StoragePurchaseContract RequestStorage(ContentId contentId, TestToken pricePerSlotPerSecond, TestToken requiredCollateral, uint minRequiredNumberOfNodes, int proofProbability, TimeSpan duration); - void AssertThatBalance(IResolveConstraint constraint, string message = ""); - TestToken GetBalance(); - } - - public class MarketplaceAccess : IMarketplaceAccess - { - private readonly TestLifecycle lifecycle; - private readonly MarketplaceNetwork marketplaceNetwork; - private readonly GethAccount account; - private readonly CodexAccess codexAccess; - - public MarketplaceAccess(TestLifecycle lifecycle, MarketplaceNetwork marketplaceNetwork, GethAccount account, CodexAccess codexAccess) - { - this.lifecycle = lifecycle; - this.marketplaceNetwork = marketplaceNetwork; - this.account = account; - this.codexAccess = codexAccess; - } - - public StoragePurchaseContract RequestStorage(ContentId contentId, TestToken pricePerSlotPerSecond, TestToken requiredCollateral, uint minRequiredNumberOfNodes, int proofProbability, TimeSpan duration) - { - var request = new CodexSalesRequestStorageRequest - { - duration = ToDecInt(duration.TotalSeconds), - proofProbability = ToDecInt(proofProbability), - reward = ToDecInt(pricePerSlotPerSecond), - collateral = ToDecInt(requiredCollateral), - expiry = null, - nodes = minRequiredNumberOfNodes, - tolerance = null, - }; - - Log($"Requesting storage for: {contentId.Id}... (" + - $"pricePerSlotPerSecond: {pricePerSlotPerSecond}, " + - $"requiredCollateral: {requiredCollateral}, " + - $"minRequiredNumberOfNodes: {minRequiredNumberOfNodes}, " + - $"proofProbability: {proofProbability}, " + - $"duration: {Time.FormatDuration(duration)})"); - - var response = codexAccess.RequestStorage(request, contentId.Id); - - if (response == "Purchasing not available") - { - throw new InvalidOperationException(response); - } - - Log($"Storage requested successfully. PurchaseId: '{response}'."); - - return new StoragePurchaseContract(lifecycle.Log, codexAccess, response, duration); - } - - public string MakeStorageAvailable(ByteSize totalSpace, TestToken minPriceForTotalSpace, TestToken maxCollateral, TimeSpan maxDuration) - { - var request = new CodexSalesAvailabilityRequest - { - size = ToDecInt(totalSpace.SizeInBytes), - duration = ToDecInt(maxDuration.TotalSeconds), - maxCollateral = ToDecInt(maxCollateral), - minPrice = ToDecInt(minPriceForTotalSpace) - }; - - Log($"Making storage available... (" + - $"size: {totalSpace}, " + - $"minPriceForTotalSpace: {minPriceForTotalSpace}, " + - $"maxCollateral: {maxCollateral}, " + - $"maxDuration: {Time.FormatDuration(maxDuration)})"); - - var response = codexAccess.SalesAvailability(request); - - Log($"Storage successfully made available. Id: {response.id}"); - - return response.id; - } - - private string ToDecInt(double d) - { - var i = new BigInteger(d); - return i.ToString("D"); - } - - public string ToDecInt(TestToken t) - { - var i = new BigInteger(t.Amount); - return i.ToString("D"); - } - - public void AssertThatBalance(IResolveConstraint constraint, string message = "") - { - AssertHelpers.RetryAssert(constraint, GetBalance, message); - } - - public TestToken GetBalance() - { - var interaction = marketplaceNetwork.StartInteraction(lifecycle); - var amount = interaction.GetBalance(marketplaceNetwork.Marketplace.TokenAddress, account.Account); - var balance = new TestToken(amount); - - Log($"Balance of {account.Account} is {balance}."); - - return balance; - } - - private void Log(string msg) - { - lifecycle.Log.Log($"{codexAccess.Container.Name} {msg}"); - } - } - - public class MarketplaceUnavailable : IMarketplaceAccess - { - public StoragePurchaseContract RequestStorage(ContentId contentId, TestToken pricePerBytePerSecond, TestToken requiredCollateral, uint minRequiredNumberOfNodes, int proofProbability, TimeSpan duration) - { - Unavailable(); - return null!; - } - - public string MakeStorageAvailable(ByteSize size, TestToken minPricePerBytePerSecond, TestToken maxCollateral, TimeSpan duration) - { - Unavailable(); - return string.Empty; - } - - public void AssertThatBalance(IResolveConstraint constraint, string message = "") - { - Unavailable(); - } - - public TestToken GetBalance() - { - Unavailable(); - return new TestToken(0); - } - - private void Unavailable() - { - Assert.Fail("Incorrect test setup: Marketplace was not enabled for this group of Codex nodes. Add 'EnableMarketplace(...)' after 'SetupCodexNodes()' to enable it."); - throw new InvalidOperationException(); - } - } - - public class StoragePurchaseContract - { - private readonly BaseLog log; - private readonly CodexAccess codexAccess; - private DateTime? contractStartUtc; - - public StoragePurchaseContract(BaseLog log, CodexAccess codexAccess, string purchaseId, TimeSpan contractDuration) - { - this.log = log; - this.codexAccess = codexAccess; - PurchaseId = purchaseId; - ContractDuration = contractDuration; - } - - public string PurchaseId { get; } - public TimeSpan ContractDuration { get; } - - public void WaitForStorageContractStarted() - { - WaitForStorageContractStarted(TimeSpan.FromSeconds(30)); - } - - public void WaitForStorageContractFinished() - { - if (!contractStartUtc.HasValue) - { - WaitForStorageContractStarted(); - } - var gracePeriod = TimeSpan.FromSeconds(10); - var currentContractTime = DateTime.UtcNow - contractStartUtc!.Value; - var timeout = (ContractDuration - currentContractTime) + gracePeriod; - WaitForStorageContractState(timeout, "finished"); - } - - /// - /// Wait for contract to start. Max timeout depends on contract filesize. Allows more time for larger files. - /// - public void WaitForStorageContractStarted(ByteSize contractFileSize) - { - var filesizeInMb = contractFileSize.SizeInBytes / (1024 * 1024); - var maxWaitTime = TimeSpan.FromSeconds(filesizeInMb * 10.0); - - WaitForStorageContractStarted(maxWaitTime); - } - - public void WaitForStorageContractStarted(TimeSpan timeout) - { - WaitForStorageContractState(timeout, "started"); - contractStartUtc = DateTime.UtcNow; - } - - private void WaitForStorageContractState(TimeSpan timeout, string desiredState) - { - var lastState = ""; - var waitStart = DateTime.UtcNow; - - log.Log($"Waiting for {Time.FormatDuration(timeout)} for contract '{PurchaseId}' to reach state '{desiredState}'."); - while (lastState != desiredState) - { - var purchaseStatus = codexAccess.GetPurchaseStatus(PurchaseId); - var statusJson = JsonConvert.SerializeObject(purchaseStatus); - if (purchaseStatus != null && purchaseStatus.state != lastState) - { - lastState = purchaseStatus.state; - log.Debug("Purchase status: " + statusJson); - } - - Thread.Sleep(1000); - - if (lastState == "errored") - { - Assert.Fail("Contract errored: " + statusJson); - } - - if (DateTime.UtcNow - waitStart > timeout) - { - Assert.Fail($"Contract did not reach '{desiredState}' within timeout. {statusJson}"); - } - } - log.Log($"Contract '{desiredState}'."); - } - - public CodexStoragePurchase GetPurchaseStatus(string purchaseId) - { - return codexAccess.GetPurchaseStatus(purchaseId); - } - } -} diff --git a/DistTestCore/Marketplace/MarketplaceAccessFactory.cs b/DistTestCore/Marketplace/MarketplaceAccessFactory.cs deleted file mode 100644 index ac595567..00000000 --- a/DistTestCore/Marketplace/MarketplaceAccessFactory.cs +++ /dev/null @@ -1,41 +0,0 @@ -using DistTestCore.Codex; - -namespace DistTestCore.Marketplace -{ - public interface IMarketplaceAccessFactory - { - IMarketplaceAccess CreateMarketplaceAccess(CodexAccess access); - } - - public class MarketplaceUnavailableAccessFactory : IMarketplaceAccessFactory - { - public IMarketplaceAccess CreateMarketplaceAccess(CodexAccess access) - { - return new MarketplaceUnavailable(); - } - } - - public class GethMarketplaceAccessFactory : IMarketplaceAccessFactory - { - private readonly TestLifecycle lifecycle; - private readonly MarketplaceNetwork marketplaceNetwork; - - public GethMarketplaceAccessFactory(TestLifecycle lifecycle, MarketplaceNetwork marketplaceNetwork) - { - this.lifecycle = lifecycle; - this.marketplaceNetwork = marketplaceNetwork; - } - - public IMarketplaceAccess CreateMarketplaceAccess(CodexAccess access) - { - var companionNode = GetGethCompanionNode(access); - return new MarketplaceAccess(lifecycle, marketplaceNetwork, companionNode, access); - } - - private GethAccount GetGethCompanionNode(CodexAccess access) - { - var account = access.Container.Recipe.Additionals.Single(a => a is GethAccount); - return (GethAccount)account; - } - } -} diff --git a/DistTestCore/Marketplace/MarketplaceInitialConfig.cs b/DistTestCore/Marketplace/MarketplaceInitialConfig.cs deleted file mode 100644 index c51d79f8..00000000 --- a/DistTestCore/Marketplace/MarketplaceInitialConfig.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace DistTestCore.Marketplace -{ - public class MarketplaceInitialConfig - { - public MarketplaceInitialConfig(Ether initialEth, TestToken initialTestTokens, bool isValidator) - { - InitialEth = initialEth; - InitialTestTokens = initialTestTokens; - IsValidator = isValidator; - } - - public Ether InitialEth { get; } - public TestToken InitialTestTokens { get; } - public bool IsValidator { get; } - public int? AccountIndexOverride { get; set; } - } -} diff --git a/DistTestCore/Marketplace/MarketplaceNetwork.cs b/DistTestCore/Marketplace/MarketplaceNetwork.cs deleted file mode 100644 index bba80a29..00000000 --- a/DistTestCore/Marketplace/MarketplaceNetwork.cs +++ /dev/null @@ -1,21 +0,0 @@ -using NethereumWorkflow; - -namespace DistTestCore.Marketplace -{ - public class MarketplaceNetwork - { - public MarketplaceNetwork(GethBootstrapNodeInfo bootstrap, MarketplaceInfo marketplace) - { - Bootstrap = bootstrap; - Marketplace = marketplace; - } - - public GethBootstrapNodeInfo Bootstrap { get; } - public MarketplaceInfo Marketplace { get; } - - public NethereumInteraction StartInteraction(TestLifecycle lifecycle) - { - return Bootstrap.StartInteraction(lifecycle); - } - } -} diff --git a/DistTestCore/Metrics/GrafanaContainerRecipe.cs b/DistTestCore/Metrics/GrafanaContainerRecipe.cs deleted file mode 100644 index 24ab599b..00000000 --- a/DistTestCore/Metrics/GrafanaContainerRecipe.cs +++ /dev/null @@ -1,25 +0,0 @@ -using KubernetesWorkflow; - -namespace DistTestCore.Metrics -{ - public class GrafanaContainerRecipe : DefaultContainerRecipe - { - public override string AppName => "grafana"; - public override string Image => "grafana/grafana-oss:10.0.3"; - - public const string DefaultAdminUser = "adminium"; - public const string DefaultAdminPassword = "passwordium"; - - protected override void InitializeRecipe(StartupConfig startupConfig) - { - AddExposedPort(3000); - - AddEnvVar("GF_AUTH_ANONYMOUS_ENABLED", "true"); - AddEnvVar("GF_AUTH_ANONYMOUS_ORG_NAME", "Main Org."); - AddEnvVar("GF_AUTH_ANONYMOUS_ORG_ROLE", "Editor"); - - AddEnvVar("GF_SECURITY_ADMIN_USER", DefaultAdminUser); - AddEnvVar("GF_SECURITY_ADMIN_PASSWORD", DefaultAdminPassword); - } - } -} diff --git a/DistTestCore/Metrics/MetricsAccess.cs b/DistTestCore/Metrics/MetricsAccess.cs deleted file mode 100644 index 23b6522d..00000000 --- a/DistTestCore/Metrics/MetricsAccess.cs +++ /dev/null @@ -1,81 +0,0 @@ -using DistTestCore.Helpers; -using KubernetesWorkflow; -using Logging; -using NUnit.Framework; -using NUnit.Framework.Constraints; -using Utils; - -namespace DistTestCore.Metrics -{ - public interface IMetricsAccess - { - void AssertThat(string metricName, IResolveConstraint constraint, string message = ""); - } - - public class MetricsAccess : IMetricsAccess - { - private readonly BaseLog log; - private readonly ITimeSet timeSet; - private readonly MetricsQuery query; - private readonly RunningContainer node; - - public MetricsAccess(BaseLog log, ITimeSet timeSet, MetricsQuery query, RunningContainer node) - { - this.log = log; - this.timeSet = timeSet; - this.query = query; - this.node = node; - } - - public void AssertThat(string metricName, IResolveConstraint constraint, string message = "") - { - AssertHelpers.RetryAssert(constraint, () => - { - var metricSet = GetMetricWithTimeout(metricName); - var metricValue = metricSet.Values[0].Value; - - log.Log($"{node.Name} metric '{metricName}' = {metricValue}"); - return metricValue; - }, message); - } - - public Metrics? GetAllMetrics() - { - return query.GetAllMetricsForNode(node); - } - - private MetricsSet GetMetricWithTimeout(string metricName) - { - var start = DateTime.UtcNow; - - while (true) - { - var mostRecent = GetMostRecent(metricName); - if (mostRecent != null) return mostRecent; - if (DateTime.UtcNow - start > timeSet.WaitForMetricTimeout()) - { - Assert.Fail($"Timeout: Unable to get metric '{metricName}'."); - throw new TimeoutException(); - } - - Time.Sleep(TimeSpan.FromSeconds(2)); - } - } - - private MetricsSet? GetMostRecent(string metricName) - { - var result = query.GetMostRecent(metricName, node); - if (result == null) return null; - return result.Sets.LastOrDefault(); - } - } - - public class MetricsUnavailable : IMetricsAccess - { - public void AssertThat(string metricName, IResolveConstraint constraint, string message = "") - { - Assert.Fail("Incorrect test setup: Metrics were not enabled for this group of Codex nodes. Add 'EnableMetrics()' after 'SetupCodexNodes()' to enable it."); - throw new InvalidOperationException(); - } - } -} diff --git a/DistTestCore/Metrics/MetricsAccessFactory.cs b/DistTestCore/Metrics/MetricsAccessFactory.cs deleted file mode 100644 index 18dae041..00000000 --- a/DistTestCore/Metrics/MetricsAccessFactory.cs +++ /dev/null @@ -1,35 +0,0 @@ -using KubernetesWorkflow; - -namespace DistTestCore.Metrics -{ - public interface IMetricsAccessFactory - { - IMetricsAccess CreateMetricsAccess(RunningContainer codexContainer); - } - - public class MetricsUnavailableAccessFactory : IMetricsAccessFactory - { - public IMetricsAccess CreateMetricsAccess(RunningContainer codexContainer) - { - return new MetricsUnavailable(); - } - } - - public class CodexNodeMetricsAccessFactory : IMetricsAccessFactory - { - private readonly TestLifecycle lifecycle; - private readonly RunningContainers prometheusContainer; - - public CodexNodeMetricsAccessFactory(TestLifecycle lifecycle, RunningContainers prometheusContainer) - { - this.lifecycle = lifecycle; - this.prometheusContainer = prometheusContainer; - } - - public IMetricsAccess CreateMetricsAccess(RunningContainer codexContainer) - { - var query = new MetricsQuery(lifecycle, prometheusContainer); - return new MetricsAccess(lifecycle.Log, lifecycle.TimeSet, query, codexContainer); - } - } -} diff --git a/DistTestCore/Metrics/MetricsDownloader.cs b/DistTestCore/Metrics/MetricsDownloader.cs deleted file mode 100644 index d0d11cdc..00000000 --- a/DistTestCore/Metrics/MetricsDownloader.cs +++ /dev/null @@ -1,80 +0,0 @@ -using Logging; -using System.Globalization; - -namespace DistTestCore.Metrics -{ - public class MetricsDownloader - { - private readonly BaseLog log; - - public MetricsDownloader(BaseLog log) - { - this.log = log; - } - - public void DownloadAllMetricsForNode(string nodeName, MetricsAccess access) - { - var metrics = access.GetAllMetrics(); - if (metrics == null || metrics.Sets.Length == 0 || metrics.Sets.All(s => s.Values.Length == 0)) return; - - var headers = new[] { "timestamp" }.Concat(metrics.Sets.Select(s => s.Name)).ToArray(); - var map = CreateValueMap(metrics); - - WriteToFile(nodeName, headers, map); - } - - private void WriteToFile(string nodeName, string[] headers, Dictionary> map) - { - var file = log.CreateSubfile("csv"); - log.Log($"Downloading metrics for {nodeName} to file {file.FullFilename}"); - - file.WriteRaw(string.Join(",", headers)); - - foreach (var pair in map) - { - file.WriteRaw(string.Join(",", new[] { FormatTimestamp(pair.Key) }.Concat(pair.Value))); - } - } - - private Dictionary> CreateValueMap(Metrics metrics) - { - var map = CreateForAllTimestamps(metrics); - foreach (var metric in metrics.Sets) - { - AddToMap(map, metric); - } - return map; - - } - - private Dictionary> CreateForAllTimestamps(Metrics metrics) - { - var result = new Dictionary>(); - var timestamps = metrics.Sets.SelectMany(s => s.Values).Select(v => v.Timestamp).Distinct().ToArray(); - foreach (var timestamp in timestamps) result.Add(timestamp, new List()); - return result; - } - - private void AddToMap(Dictionary> map, MetricsSet metric) - { - foreach (var key in map.Keys) - { - map[key].Add(GetValueAtTimestamp(key, metric)); - } - } - - private string GetValueAtTimestamp(DateTime key, MetricsSet metric) - { - var value = metric.Values.SingleOrDefault(v => v.Timestamp == key); - if (value == null) return ""; - return value.Value.ToString(CultureInfo.InvariantCulture); - } - - private string FormatTimestamp(DateTime key) - { - var origin = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); - var diff = key - origin; - return Math.Floor(diff.TotalSeconds).ToString(CultureInfo.InvariantCulture); - } - } -} diff --git a/DistTestCore/Metrics/MetricsMode.cs b/DistTestCore/Metrics/MetricsMode.cs deleted file mode 100644 index 60b4f5ef..00000000 --- a/DistTestCore/Metrics/MetricsMode.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace DistTestCore.Metrics -{ - public enum MetricsMode - { - None, - Record, - Dashboard - } -} diff --git a/DistTestCore/Metrics/MetricsQuery.cs b/DistTestCore/Metrics/MetricsQuery.cs deleted file mode 100644 index baffe66f..00000000 --- a/DistTestCore/Metrics/MetricsQuery.cs +++ /dev/null @@ -1,198 +0,0 @@ -using DistTestCore.Codex; -using KubernetesWorkflow; -using System.Globalization; - -namespace DistTestCore.Metrics -{ - public class MetricsQuery - { - private readonly Http http; - - public MetricsQuery(TestLifecycle lifecycle, RunningContainers runningContainers) - { - RunningContainers = runningContainers; - - var address = lifecycle.Configuration.GetAddress(runningContainers.Containers[0]); - - http = new Http( - lifecycle.Log, - lifecycle.TimeSet, - address, - "api/v1"); - } - - public RunningContainers RunningContainers { get; } - - public Metrics? GetMostRecent(string metricName, RunningContainer node) - { - var response = GetLastOverTime(metricName, GetInstanceStringForNode(node)); - if (response == null) return null; - - return new Metrics - { - Sets = response.data.result.Select(r => - { - return new MetricsSet - { - Instance = r.metric.instance, - Values = MapSingleValue(r.value) - }; - }).ToArray() - }; - } - - public Metrics? GetMetrics(string metricName) - { - var response = GetAll(metricName); - if (response == null) return null; - return MapResponseToMetrics(response); - } - - public Metrics? GetAllMetricsForNode(RunningContainer node) - { - var response = http.HttpGetJson($"query?query={GetInstanceStringForNode(node)}{GetQueryTimeRange()}"); - if (response.status != "success") return null; - return MapResponseToMetrics(response); - } - - private PrometheusQueryResponse? GetLastOverTime(string metricName, string instanceString) - { - var response = http.HttpGetJson($"query?query=last_over_time({metricName}{instanceString}{GetQueryTimeRange()})"); - if (response.status != "success") return null; - return response; - } - - private PrometheusQueryResponse? GetAll(string metricName) - { - var response = http.HttpGetJson($"query?query={metricName}{GetQueryTimeRange()}"); - if (response.status != "success") return null; - return response; - } - - private Metrics MapResponseToMetrics(PrometheusQueryResponse response) - { - return new Metrics - { - Sets = response.data.result.Select(r => - { - return new MetricsSet - { - Name = r.metric.__name__, - Instance = r.metric.instance, - Values = MapMultipleValues(r.values) - }; - }).ToArray() - }; - } - - private MetricsSetValue[] MapSingleValue(object[] value) - { - if (value != null && value.Length > 0) - { - return new[] - { - MapValue(value) - }; - } - return Array.Empty(); - } - - private MetricsSetValue[] MapMultipleValues(object[][] values) - { - if (values != null && values.Length > 0) - { - return values.Select(v => MapValue(v)).ToArray(); - } - return Array.Empty(); - } - - private MetricsSetValue MapValue(object[] value) - { - if (value.Length != 2) throw new InvalidOperationException("Expected value to be [double, string]."); - - return new MetricsSetValue - { - Timestamp = ToTimestamp(value[0]), - Value = ToValue(value[1]) - }; - } - - private string GetInstanceNameForNode(RunningContainer node) - { - var ip = node.Pod.PodInfo.Ip; - var port = node.Recipe.GetPortByTag(CodexContainerRecipe.MetricsPortTag).Number; - return $"{ip}:{port}"; - } - - private string GetInstanceStringForNode(RunningContainer node) - { - return "{instance=\"" + GetInstanceNameForNode(node) + "\"}"; - } - - private string GetQueryTimeRange() - { - return "[12h]"; - } - - private double ToValue(object v) - { - return Convert.ToDouble(v, CultureInfo.InvariantCulture); - } - - private DateTime ToTimestamp(object v) - { - var unixSeconds = ToValue(v); - return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(unixSeconds); - } - } - - public class Metrics - { - public MetricsSet[] Sets { get; set; } = Array.Empty(); - } - - public class MetricsSet - { - public string Name { get; set; } = string.Empty; - public string Instance { get; set; } = string.Empty; - public MetricsSetValue[] Values { get; set; } = Array.Empty(); - } - - public class MetricsSetValue - { - public DateTime Timestamp { get; set; } - public double Value { get; set; } - } - - public class PrometheusQueryResponse - { - public string status { get; set; } = string.Empty; - public PrometheusQueryResponseData data { get; set; } = new(); - } - - public class PrometheusQueryResponseData - { - public string resultType { get; set; } = string.Empty; - public PrometheusQueryResponseDataResultEntry[] result { get; set; } = Array.Empty(); - } - - public class PrometheusQueryResponseDataResultEntry - { - public ResultEntryMetric metric { get; set; } = new(); - public object[] value { get; set; } = Array.Empty(); - public object[][] values { get; set; } = Array.Empty(); - } - - public class ResultEntryMetric - { - public string __name__ { get; set; } = string.Empty; - public string instance { get; set; } = string.Empty; - public string job { get; set; } = string.Empty; - } - - public class PrometheusAllNamesResponse - { - public string status { get; set; } = string.Empty; - public string[] data { get; set; } = Array.Empty(); - } -} diff --git a/DistTestCore/Metrics/PrometheusContainerRecipe.cs b/DistTestCore/Metrics/PrometheusContainerRecipe.cs deleted file mode 100644 index 62287121..00000000 --- a/DistTestCore/Metrics/PrometheusContainerRecipe.cs +++ /dev/null @@ -1,18 +0,0 @@ -using KubernetesWorkflow; - -namespace DistTestCore.Metrics -{ - public class PrometheusContainerRecipe : DefaultContainerRecipe - { - public override string AppName => "prometheus"; - public override string Image => "codexstorage/dist-tests-prometheus:latest"; - - protected override void InitializeRecipe(StartupConfig startupConfig) - { - var config = startupConfig.Get(); - - AddExposedPortAndVar("PROM_PORT"); - AddEnvVar("PROM_CONFIG", config.PrometheusConfigBase64); - } - } -} diff --git a/DistTestCore/Metrics/PrometheusStartupConfig.cs b/DistTestCore/Metrics/PrometheusStartupConfig.cs deleted file mode 100644 index 7bf7fe62..00000000 --- a/DistTestCore/Metrics/PrometheusStartupConfig.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace DistTestCore.Metrics -{ - public class PrometheusStartupConfig - { - public PrometheusStartupConfig(string prometheusConfigBase64) - { - PrometheusConfigBase64 = prometheusConfigBase64; - } - - public string PrometheusConfigBase64 { get; } - } -} diff --git a/DistTestCore/PrometheusStarter.cs b/DistTestCore/PrometheusStarter.cs index f19978c3..bfba12ba 100644 --- a/DistTestCore/PrometheusStarter.cs +++ b/DistTestCore/PrometheusStarter.cs @@ -1,6 +1,4 @@ -using DistTestCore.Codex; -using DistTestCore.Metrics; -using KubernetesWorkflow; +using KubernetesWorkflow; using System.Text; namespace DistTestCore @@ -14,39 +12,40 @@ namespace DistTestCore public RunningContainers CollectMetricsFor(RunningContainers[] containers) { - LogStart($"Starting metrics server for {containers.Describe()}"); - var startupConfig = new StartupConfig(); - startupConfig.Add(new PrometheusStartupConfig(GeneratePrometheusConfig(containers.Containers()))); + //LogStart($"Starting metrics server for {containers.Describe()}"); + //var startupConfig = new StartupConfig(); + //startupConfig.Add(new PrometheusStartupConfig(GeneratePrometheusConfig(containers.Containers()))); - var workflow = lifecycle.WorkflowCreator.CreateWorkflow(); - var runningContainers = workflow.Start(1, Location.Unspecified, new PrometheusContainerRecipe(), startupConfig); - if (runningContainers.Containers.Length != 1) throw new InvalidOperationException("Expected only 1 Prometheus container to be created."); + //var workflow = lifecycle.WorkflowCreator.CreateWorkflow(); + //var runningContainers = workflow.Start(1, Location.Unspecified, new PrometheusContainerRecipe(), startupConfig); + //if (runningContainers.Containers.Length != 1) throw new InvalidOperationException("Expected only 1 Prometheus container to be created."); - return runningContainers; + //return runningContainers; + return null!; } - private string GeneratePrometheusConfig(RunningContainer[] nodes) - { - var config = ""; - config += "global:\n"; - config += " scrape_interval: 10s\n"; - config += " scrape_timeout: 10s\n"; - config += "\n"; - config += "scrape_configs:\n"; - config += " - job_name: services\n"; - config += " metrics_path: /metrics\n"; - config += " static_configs:\n"; - config += " - targets:\n"; + //private string GeneratePrometheusConfig(RunningContainer[] nodes) + //{ + // var config = ""; + // config += "global:\n"; + // config += " scrape_interval: 10s\n"; + // config += " scrape_timeout: 10s\n"; + // config += "\n"; + // config += "scrape_configs:\n"; + // config += " - job_name: services\n"; + // config += " metrics_path: /metrics\n"; + // config += " static_configs:\n"; + // config += " - targets:\n"; - foreach (var node in nodes) - { - var ip = node.Pod.PodInfo.Ip; - var port = node.Recipe.GetPortByTag(CodexContainerRecipe.MetricsPortTag).Number; - config += $" - '{ip}:{port}'\n"; - } + // foreach (var node in nodes) + // { + // var ip = node.Pod.PodInfo.Ip; + // var port = node.Recipe.GetPortByTag(CodexContainerRecipe.MetricsPortTag).Number; + // config += $" - '{ip}:{port}'\n"; + // } - var bytes = Encoding.ASCII.GetBytes(config); - return Convert.ToBase64String(bytes); - } + // var bytes = Encoding.ASCII.GetBytes(config); + // return Convert.ToBase64String(bytes); + //} } } diff --git a/DistTestCore/TestLifecycle.cs b/DistTestCore/TestLifecycle.cs index 0a364c8d..eeb65c6e 100644 --- a/DistTestCore/TestLifecycle.cs +++ b/DistTestCore/TestLifecycle.cs @@ -1,7 +1,4 @@ -using DistTestCore.Codex; -using DistTestCore.Logs; -using DistTestCore.Marketplace; -using DistTestCore.Metrics; +using DistTestCore.Logs; using FileUtils; using KubernetesWorkflow; using Logging; @@ -22,12 +19,12 @@ namespace DistTestCore WorkflowCreator = new WorkflowCreator(log, configuration.GetK8sConfiguration(timeSet), testNamespace); FileManager = new FileManager(Log, configuration.GetFileManagerFolder()); - CodexStarter = new CodexStarter(this); + //CodexStarter = new CodexStarter(this); PrometheusStarter = new PrometheusStarter(this); GrafanaStarter = new GrafanaStarter(this); - GethStarter = new GethStarter(this); + //GethStarter = new GethStarter(this); testStart = DateTime.UtcNow; - CodexVersion = null; + //CodexVersion = null; Log.WriteLogTag(); } @@ -37,15 +34,15 @@ namespace DistTestCore public ITimeSet TimeSet { get; } public WorkflowCreator WorkflowCreator { get; } public FileManager FileManager { get; } - public CodexStarter CodexStarter { get; } + //public CodexStarter CodexStarter { get; } public PrometheusStarter PrometheusStarter { get; } public GrafanaStarter GrafanaStarter { get; } - public GethStarter GethStarter { get; } - public CodexDebugVersionResponse? CodexVersion { get; private set; } + //public GethStarter GethStarter { get; } + //public CodexDebugVersionResponse? CodexVersion { get; private set; } public void DeleteAllResources() { - CodexStarter.DeleteAllResources(); + //CodexStarter.DeleteAllResources(); FileManager.DeleteAllTestFiles(); } @@ -56,7 +53,7 @@ namespace DistTestCore var handler = new LogDownloadHandler(container, description, subFile); Log.Log($"Downloading logs for {description} to file '{subFile.FullFilename}'"); - CodexStarter.DownloadLog(container, handler, tailLines); + //CodexStarter.DownloadLog(container, handler, tailLines); return new DownloadedLog(subFile, description); } @@ -67,28 +64,30 @@ namespace DistTestCore return Time.FormatDuration(testDuration); } - public void SetCodexVersion(CodexDebugVersionResponse version) - { - if (CodexVersion == null) CodexVersion = version; - } + //public void SetCodexVersion(CodexDebugVersionResponse version) + //{ + // if (CodexVersion == null) CodexVersion = version; + //} public ApplicationIds GetApplicationIds() { - return new ApplicationIds( - codexId: GetCodexId(), - gethId: new GethContainerRecipe().Image, - prometheusId: new PrometheusContainerRecipe().Image, - codexContractsId: new CodexContractsContainerRecipe().Image, - grafanaId: new GrafanaContainerRecipe().Image - ); + //return new ApplicationIds( + // codexId: GetCodexId(), + // gethId: new GethContainerRecipe().Image, + // prometheusId: new PrometheusContainerRecipe().Image, + // codexContractsId: new CodexContractsContainerRecipe().Image, + // grafanaId: new GrafanaContainerRecipe().Image + //); + return null!; } private string GetCodexId() { - var v = CodexVersion; - if (v == null) return new CodexContainerRecipe().Image; - if (v.version != "untagged build") return v.version; - return v.revision; + return ""; + //var v = CodexVersion; + //if (v == null) return new CodexContainerRecipe().Image; + //if (v.version != "untagged build") return v.version; + //return v.revision; } } } diff --git a/Tests/BasicTests/ContinuousSubstitute.cs b/Tests/BasicTests/ContinuousSubstitute.cs deleted file mode 100644 index 6f4ba163..00000000 --- a/Tests/BasicTests/ContinuousSubstitute.cs +++ /dev/null @@ -1,252 +0,0 @@ -using DistTestCore; -using NUnit.Framework; -using Utils; - -namespace Tests.BasicTests -{ - [Ignore("Used for debugging continuous tests")] - [TestFixture] - public class ContinuousSubstitute : AutoBootstrapDistTest - { - [Test] - public void ContinuousTestSubstitute() - { - var group = SetupCodexNodes(5, o => o - .EnableMetrics() - .EnableMarketplace(100000.TestTokens(), 0.Eth(), isValidator: true) - .WithBlockTTL(TimeSpan.FromMinutes(2)) - .WithBlockMaintenanceInterval(TimeSpan.FromMinutes(2)) - .WithBlockMaintenanceNumber(10000) - .WithBlockTTL(TimeSpan.FromMinutes(2)) - .WithStorageQuota(1.GB())); - - var nodes = group.Cast().ToArray(); - - foreach (var node in nodes) - { - node.Marketplace.MakeStorageAvailable( - size: 500.MB(), - minPricePerBytePerSecond: 1.TestTokens(), - maxCollateral: 1024.TestTokens(), - maxDuration: TimeSpan.FromMinutes(5)); - } - - var endTime = DateTime.UtcNow + TimeSpan.FromHours(10); - while (DateTime.UtcNow < endTime) - { - var allNodes = nodes.ToList(); - var primary = allNodes.PickOneRandom(); - var secondary = allNodes.PickOneRandom(); - - Log("Run Test"); - PerformTest(primary, secondary); - - Thread.Sleep(TimeSpan.FromSeconds(5)); - } - } - - [Test] - public void PeerTest() - { - var group = SetupCodexNodes(5, o => o - .EnableMetrics() - .EnableMarketplace(100000.TestTokens(), 0.Eth(), isValidator: true) - .WithBlockTTL(TimeSpan.FromMinutes(2)) - .WithBlockMaintenanceInterval(TimeSpan.FromMinutes(2)) - .WithBlockMaintenanceNumber(10000) - .WithBlockTTL(TimeSpan.FromMinutes(2)) - .WithStorageQuota(1.GB())); - - var nodes = group.Cast().ToArray(); - - var checkTime = DateTime.UtcNow + TimeSpan.FromMinutes(1); - var endTime = DateTime.UtcNow + TimeSpan.FromHours(10); - while (DateTime.UtcNow < endTime) - { - CreatePeerConnectionTestHelpers().AssertFullyConnected(GetAllOnlineCodexNodes()); - CheckRoutingTables(GetAllOnlineCodexNodes()); - - var node = RandomUtils.PickOneRandom(nodes.ToList()); - var file = GenerateTestFile(50.MB()); - node.UploadFile(file); - - Thread.Sleep(20000); - } - } - - private void CheckRoutingTables(IEnumerable nodes) - { - var all = nodes.ToArray(); - var allIds = all.Select(n => n.GetDebugInfo().table.localNode.nodeId).ToArray(); - - var errors = all.Select(n => AreAllPresent(n, allIds)).Where(s => !string.IsNullOrEmpty(s)).ToArray(); - - if (errors.Any()) - { - Assert.Fail(string.Join(Environment.NewLine, errors)); - } - } - - private string AreAllPresent(IOnlineCodexNode n, string[] allIds) - { - var info = n.GetDebugInfo(); - var known = info.table.nodes.Select(n => n.nodeId).ToArray(); - var expected = allIds.Where(i => i != info.table.localNode.nodeId).ToArray(); - - if (!expected.All(ex => known.Contains(ex))) - { - return $"Not all of '{string.Join(",", expected)}' were present in routing table: '{string.Join(",", known)}'"; - } - - return string.Empty; - } - - private ByteSize fileSize = 80.MB(); - - private void PerformTest(IOnlineCodexNode primary, IOnlineCodexNode secondary) - { - ScopedTestFiles(() => - { - var testFile = GenerateTestFile(fileSize); - - var contentId = primary.UploadFile(testFile); - - var downloadedFile = secondary.DownloadContent(contentId); - - testFile.AssertIsEqual(downloadedFile); - }); - } - - [Test] - public void HoldMyBeerTest() - { - var blockExpirationTime = TimeSpan.FromMinutes(3); - var group = SetupCodexNodes(3, o => o - .EnableMetrics() - .WithBlockTTL(blockExpirationTime) - .WithBlockMaintenanceInterval(TimeSpan.FromMinutes(2)) - .WithBlockMaintenanceNumber(10000) - .WithStorageQuota(2000.MB())); - - var nodes = group.Cast().ToArray(); - - var endTime = DateTime.UtcNow + TimeSpan.FromHours(24); - - var filesize = 80.MB(); - double codexDefaultBlockSize = 31 * 64 * 33; - var numberOfBlocks = Convert.ToInt64(Math.Ceiling(filesize.SizeInBytes / codexDefaultBlockSize)); - var sizeInBytes = filesize.SizeInBytes; - Assert.That(numberOfBlocks, Is.EqualTo(1282)); - - var startTime = DateTime.UtcNow; - var successfulUploads = 0; - var successfulDownloads = 0; - - while (DateTime.UtcNow < endTime) - { - foreach (var node in nodes) - { - try - { - Thread.Sleep(TimeSpan.FromSeconds(5)); - - ScopedTestFiles(() => - { - var uploadStartTime = DateTime.UtcNow; - var file = GenerateTestFile(filesize); - var cid = node.UploadFile(file); - - var cidTag = cid.Id.Substring(cid.Id.Length - 6); - Measure("upload-log-asserts", () => - { - var uploadLog = node.DownloadLog(tailLines: 50000); - - var storeLines = uploadLog.FindLinesThatContain("Stored data", "topics=\"codex node\""); - uploadLog.DeleteFile(); - - var storeLine = GetLineForCidTag(storeLines, cidTag); - AssertStoreLineContains(storeLine, numberOfBlocks, sizeInBytes); - }); - successfulUploads++; - - var uploadTimeTaken = DateTime.UtcNow - uploadStartTime; - if (uploadTimeTaken >= blockExpirationTime.Subtract(TimeSpan.FromSeconds(10))) - { - Assert.Fail("Upload took too long. Blocks already expired."); - } - - var dl = node.DownloadContent(cid); - file.AssertIsEqual(dl); - - Measure("download-log-asserts", () => - { - var downloadLog = node.DownloadLog(tailLines: 50000); - - var sentLines = downloadLog.FindLinesThatContain("Sent bytes", "topics=\"codex restapi\""); - downloadLog.DeleteFile(); - - var sentLine = GetLineForCidTag(sentLines, cidTag); - AssertSentLineContains(sentLine, sizeInBytes); - }); - successfulDownloads++; - }); - } - catch - { - var testDuration = DateTime.UtcNow - startTime; - Log("Test failed. Delaying shut-down by 30 seconds to collect metrics."); - Log($"Test failed after {Time.FormatDuration(testDuration)} and {successfulUploads} successful uploads and {successfulDownloads} successful downloads"); - Thread.Sleep(TimeSpan.FromSeconds(30)); - throw; - } - } - - Thread.Sleep(TimeSpan.FromSeconds(5)); - } - } - - private void AssertSentLineContains(string sentLine, long sizeInBytes) - { - var tag = "bytes="; - var token = sentLine.Substring(sentLine.IndexOf(tag) + tag.Length); - var bytes = Convert.ToInt64(token); - Assert.AreEqual(sizeInBytes, bytes, $"Sent bytes: Number of bytes incorrect. Line: '{sentLine}'"); - } - - private void AssertStoreLineContains(string storeLine, long numberOfBlocks, long sizeInBytes) - { - var tokens = storeLine.Split(" "); - - var blocksToken = GetToken(tokens, "blocks="); - var sizeToken = GetToken(tokens, "size="); - if (blocksToken == null) Assert.Fail("blockToken not found in " + storeLine); - if (sizeToken == null) Assert.Fail("sizeToken not found in " + storeLine); - - var blocks = Convert.ToInt64(blocksToken); - var size = Convert.ToInt64(sizeToken?.Replace("'NByte", "")); - - var lineLog = $" Line: '{storeLine}'"; - Assert.AreEqual(numberOfBlocks, blocks, "Stored data: Number of blocks incorrect." + lineLog); - Assert.AreEqual(sizeInBytes, size, "Stored data: Number of blocks incorrect." + lineLog); - } - - private string GetLineForCidTag(string[] lines, string cidTag) - { - var result = lines.SingleOrDefault(l => l.Contains(cidTag)); - if (result == null) - { - Assert.Fail($"Failed to find '{cidTag}' in lines: '{string.Join(",", lines)}'"); - throw new Exception(); - } - - return result; - } - - private string? GetToken(string[] tokens, string tag) - { - var token = tokens.SingleOrDefault(t => t.StartsWith(tag)); - if (token == null) return null; - return token.Substring(tag.Length); - } - } -} diff --git a/Tests/BasicTests/ExampleTests.cs b/Tests/BasicTests/ExampleTests.cs deleted file mode 100644 index 76b37aba..00000000 --- a/Tests/BasicTests/ExampleTests.cs +++ /dev/null @@ -1,86 +0,0 @@ -using DistTestCore; -using NUnit.Framework; -using Utils; - -namespace Tests.BasicTests -{ - [TestFixture] - public class ExampleTests : DistTest - { - [Test] - public void CodexLogExample() - { - var primary = SetupCodexNodes(2)[0]; - - primary.UploadFile(GenerateTestFile(5.MB())); - - var log = primary.DownloadLog(); - - log.AssertLogContains("Uploaded file"); - } - - [Test] - public void TwoMetricsExample() - { - var group = SetupCodexNodes(2, s => s.EnableMetrics()); - var group2 = SetupCodexNodes(2, s => s.EnableMetrics()); - - var primary = group[0]; - var secondary = group[1]; - var primary2 = group2[0]; - var secondary2 = group2[1]; - - primary.ConnectToPeer(secondary); - primary2.ConnectToPeer(secondary2); - - Thread.Sleep(TimeSpan.FromMinutes(2)); - - primary.Metrics.AssertThat("libp2p_peers", Is.EqualTo(1)); - primary2.Metrics.AssertThat("libp2p_peers", Is.EqualTo(1)); - } - - [Test] - public void MarketplaceExample() - { - var sellerInitialBalance = 234.TestTokens(); - var buyerInitialBalance = 1000.TestTokens(); - var fileSize = 10.MB(); - - var seller = SetupCodexNode(s => s - .WithStorageQuota(11.GB()) - .EnableMarketplace(sellerInitialBalance)); - - seller.Marketplace.AssertThatBalance(Is.EqualTo(sellerInitialBalance)); - seller.Marketplace.MakeStorageAvailable( - size: 10.GB(), - minPricePerBytePerSecond: 1.TestTokens(), - maxCollateral: 20.TestTokens(), - maxDuration: TimeSpan.FromMinutes(3)); - - var testFile = GenerateTestFile(fileSize); - - var buyer = SetupCodexNode(s => s - .WithBootstrapNode(seller) - .EnableMarketplace(buyerInitialBalance)); - - buyer.Marketplace.AssertThatBalance(Is.EqualTo(buyerInitialBalance)); - - var contentId = buyer.UploadFile(testFile); - var purchaseContract = buyer.Marketplace.RequestStorage(contentId, - pricePerSlotPerSecond: 2.TestTokens(), - requiredCollateral: 10.TestTokens(), - minRequiredNumberOfNodes: 1, - proofProbability: 5, - duration: TimeSpan.FromMinutes(1)); - - purchaseContract.WaitForStorageContractStarted(fileSize); - - seller.Marketplace.AssertThatBalance(Is.LessThan(sellerInitialBalance), "Collateral was not placed."); - - purchaseContract.WaitForStorageContractFinished(); - - seller.Marketplace.AssertThatBalance(Is.GreaterThan(sellerInitialBalance), "Seller was not paid for storage."); - buyer.Marketplace.AssertThatBalance(Is.LessThan(buyerInitialBalance), "Buyer was not charged for storage."); - } - } -} diff --git a/Tests/BasicTests/NetworkIsolationTest.cs b/Tests/BasicTests/NetworkIsolationTest.cs deleted file mode 100644 index e1c6e7b3..00000000 --- a/Tests/BasicTests/NetworkIsolationTest.cs +++ /dev/null @@ -1,46 +0,0 @@ -using DistTestCore; -using NUnit.Framework; -using Utils; - -namespace Tests.BasicTests -{ - // Warning! - // This is a test to check network-isolation in the test-infrastructure. - // It requires parallelism(2) or greater to run. - [TestFixture] - [Ignore("Disabled until a solution is implemented.")] - public class NetworkIsolationTest : DistTest - { - private IOnlineCodexNode? node = null; - - [Test] - public void SetUpANodeAndWait() - { - node = SetupCodexNode(); - - Time.WaitUntil(() => node == null, TimeSpan.FromMinutes(5), TimeSpan.FromSeconds(5)); - } - - [Test] - public void ForeignNodeConnects() - { - var myNode = SetupCodexNode(); - - Time.WaitUntil(() => node != null, TimeSpan.FromMinutes(1), TimeSpan.FromSeconds(5)); - - try - { - myNode.ConnectToPeer(node!); - } - catch - { - // Good! This connection should be prohibited by the network isolation policy. - node = null; - return; - } - - Assert.Fail("Connection could be established between two Codex nodes running in different namespaces. " + - "This may cause cross-test interference. Network isolation policy should be applied. Test infra failure."); - } - } -} diff --git a/Tests/BasicTests/OneClientTests.cs b/Tests/BasicTests/OneClientTests.cs deleted file mode 100644 index a31be3ce..00000000 --- a/Tests/BasicTests/OneClientTests.cs +++ /dev/null @@ -1,41 +0,0 @@ -using DistTestCore; -using NUnit.Framework; -using Utils; - -namespace Tests.BasicTests -{ - [TestFixture] - public class OneClientTests : DistTest - { - [Test] - public void OneClientTest() - { - var primary = SetupCodexNode(); - - PerformOneClientTest(primary); - } - - [Test] - public void RestartTest() - { - var primary = SetupCodexNode(); - - var setup = primary.BringOffline(); - - primary = BringOnline(setup)[0]; - - PerformOneClientTest(primary); - } - - private void PerformOneClientTest(IOnlineCodexNode primary) - { - var testFile = GenerateTestFile(1.MB()); - - var contentId = primary.UploadFile(testFile); - - var downloadedFile = primary.DownloadContent(contentId); - - testFile.AssertIsEqual(downloadedFile); - } - } -} diff --git a/Tests/BasicTests/ThreeClientTest.cs b/Tests/BasicTests/ThreeClientTest.cs deleted file mode 100644 index c857e35f..00000000 --- a/Tests/BasicTests/ThreeClientTest.cs +++ /dev/null @@ -1,25 +0,0 @@ -using DistTestCore; -using NUnit.Framework; -using Utils; - -namespace Tests.BasicTests -{ - [TestFixture] - public class ThreeClientTest : AutoBootstrapDistTest - { - [Test] - public void ThreeClient() - { - var primary = SetupCodexNode(); - var secondary = SetupCodexNode(); - - var testFile = GenerateTestFile(10.MB()); - - var contentId = primary.UploadFile(testFile); - - var downloadedFile = secondary.DownloadContent(contentId); - - testFile.AssertIsEqual(downloadedFile); - } - } -} diff --git a/Tests/BasicTests/TwoClientTests.cs b/Tests/BasicTests/TwoClientTests.cs index 4bebc20a..ed16790b 100644 --- a/Tests/BasicTests/TwoClientTests.cs +++ b/Tests/BasicTests/TwoClientTests.cs @@ -2,6 +2,7 @@ using KubernetesWorkflow; using NUnit.Framework; using Utils; +using CodexPlugin; namespace Tests.BasicTests { @@ -11,7 +12,7 @@ namespace Tests.BasicTests [Test] public void TwoClientTest() { - var group = SetupCodexNodes(2); + var group = this.SetupCodexNodes(2); var primary = group[0]; var secondary = group[1]; @@ -22,8 +23,8 @@ namespace Tests.BasicTests [Test] public void TwoClientsTwoLocationsTest() { - var primary = SetupCodexNode(s => s.At(Location.One)); - var secondary = SetupCodexNode(s => s.At(Location.Two)); + var primary = this.SetupCodexNode(s => s.At(Location.One)); + var secondary = this.SetupCodexNode(s => s.At(Location.Two)); PerformTwoClientTest(primary, secondary); } diff --git a/Tests/DownloadConnectivityTests/FullyConnectedDownloadTests.cs b/Tests/DownloadConnectivityTests/FullyConnectedDownloadTests.cs deleted file mode 100644 index 9fb5630a..00000000 --- a/Tests/DownloadConnectivityTests/FullyConnectedDownloadTests.cs +++ /dev/null @@ -1,42 +0,0 @@ -using DistTestCore; -using NUnit.Framework; -using Utils; - -namespace Tests.DownloadConnectivityTests -{ - [TestFixture] - public class FullyConnectedDownloadTests : AutoBootstrapDistTest - { - [Test] - public void MetricsDoesNotInterfereWithPeerDownload() - { - SetupCodexNodes(2, s => s.EnableMetrics()); - - AssertAllNodesConnected(); - } - - [Test] - public void MarketplaceDoesNotInterfereWithPeerDownload() - { - SetupCodexNodes(2, s => s.EnableMetrics().EnableMarketplace(1000.TestTokens())); - - AssertAllNodesConnected(); - } - - [Test] - [Combinatorial] - public void FullyConnectedDownloadTest( - [Values(3, 5)] int numberOfNodes, - [Values(10, 80)] int sizeMBs) - { - SetupCodexNodes(numberOfNodes); - - AssertAllNodesConnected(sizeMBs); - } - - private void AssertAllNodesConnected(int sizeMBs = 10) - { - CreatePeerDownloadTestHelpers().AssertFullDownloadInterconnectivity(GetAllOnlineCodexNodes(), sizeMBs.MB()); - } - } -} diff --git a/Tests/PeerDiscoveryTests/LayeredDiscoveryTests.cs b/Tests/PeerDiscoveryTests/LayeredDiscoveryTests.cs deleted file mode 100644 index 8cd32a2d..00000000 --- a/Tests/PeerDiscoveryTests/LayeredDiscoveryTests.cs +++ /dev/null @@ -1,52 +0,0 @@ -using DistTestCore; -using NUnit.Framework; - -namespace Tests.PeerDiscoveryTests -{ - [TestFixture] - public class LayeredDiscoveryTests : DistTest - { - [Test] - public void TwoLayersTest() - { - var root = SetupCodexNode(); - var l1Source = SetupCodexNode(s => s.WithBootstrapNode(root)); - var l1Node = SetupCodexNode(s => s.WithBootstrapNode(root)); - var l2Target = SetupCodexNode(s => s.WithBootstrapNode(l1Node)); - - AssertAllNodesConnected(); - } - - [Test] - public void ThreeLayersTest() - { - var root = SetupCodexNode(); - var l1Source = SetupCodexNode(s => s.WithBootstrapNode(root)); - var l1Node = SetupCodexNode(s => s.WithBootstrapNode(root)); - var l2Node = SetupCodexNode(s => s.WithBootstrapNode(l1Node)); - var l3Target = SetupCodexNode(s => s.WithBootstrapNode(l2Node)); - - AssertAllNodesConnected(); - } - - [TestCase(3)] - [TestCase(5)] - [TestCase(10)] - [TestCase(20)] - public void NodeChainTest(int chainLength) - { - var node = SetupCodexNode(); - for (var i = 1; i < chainLength; i++) - { - node = SetupCodexNode(s => s.WithBootstrapNode(node)); - } - - AssertAllNodesConnected(); - } - - private void AssertAllNodesConnected() - { - CreatePeerConnectionTestHelpers().AssertFullyConnected(GetAllOnlineCodexNodes()); - } - } -} diff --git a/Tests/PeerDiscoveryTests/PeerDiscoveryTests.cs b/Tests/PeerDiscoveryTests/PeerDiscoveryTests.cs deleted file mode 100644 index fcb44fdc..00000000 --- a/Tests/PeerDiscoveryTests/PeerDiscoveryTests.cs +++ /dev/null @@ -1,51 +0,0 @@ -using DistTestCore; -using NUnit.Framework; - -namespace Tests.PeerDiscoveryTests -{ - [TestFixture] - public class PeerDiscoveryTests : AutoBootstrapDistTest - { - [Test] - public void CanReportUnknownPeerId() - { - var unknownId = "16Uiu2HAkv2CHWpff3dj5iuVNERAp8AGKGNgpGjPexJZHSqUstfsK"; - var node = SetupCodexNode(); - - var result = node.GetDebugPeer(unknownId); - Assert.That(result.IsPeerFound, Is.False); - } - - [Test] - public void MetricsDoesNotInterfereWithPeerDiscovery() - { - SetupCodexNodes(2, s => s.EnableMetrics()); - - AssertAllNodesConnected(); - } - - [Test] - public void MarketplaceDoesNotInterfereWithPeerDiscovery() - { - SetupCodexNodes(2, s => s.EnableMarketplace(1000.TestTokens())); - - AssertAllNodesConnected(); - } - - [TestCase(2)] - [TestCase(3)] - [TestCase(10)] - [TestCase(20)] - public void VariableNodes(int number) - { - SetupCodexNodes(number); - - AssertAllNodesConnected(); - } - - private void AssertAllNodesConnected() - { - CreatePeerConnectionTestHelpers().AssertFullyConnected(GetAllOnlineCodexNodes()); - } - } -} diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index ab5558b2..16dbb662 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -13,6 +13,7 @@ + diff --git a/cs-codex-dist-testing.sln b/cs-codex-dist-testing.sln index b0802684..59b290c5 100644 --- a/cs-codex-dist-testing.sln +++ b/cs-codex-dist-testing.sln @@ -5,8 +5,6 @@ VisualStudioVersion = 17.4.33213.308 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Tests\Tests.csproj", "{57F57B85-A537-4D3A-B7AE-B72C66B74AAB}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestsLong", "LongTests\TestsLong.csproj", "{AFCE270E-F844-4A7C-9006-69AE622BB1F4}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DistTestCore", "DistTestCore\DistTestCore.csproj", "{47F31305-6E68-4827-8E39-7B41DAA1CE7A}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KubernetesWorkflow", "KubernetesWorkflow\KubernetesWorkflow.csproj", "{359123AA-3D9B-4442-80F4-19E32E3EC9EA}" @@ -27,6 +25,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CodexNetDownloader", "Codex EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileUtils", "FileUtils\FileUtils.csproj", "{ECC954DA-8D4E-49EE-83AD-80085A43DEEB}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodexPlugin", "CodexPlugin\CodexPlugin.csproj", "{DE4E802C-288C-45C4-84B6-8A5A6A96EF49}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -37,10 +37,6 @@ Global {57F57B85-A537-4D3A-B7AE-B72C66B74AAB}.Debug|Any CPU.Build.0 = Debug|Any CPU {57F57B85-A537-4D3A-B7AE-B72C66B74AAB}.Release|Any CPU.ActiveCfg = Release|Any CPU {57F57B85-A537-4D3A-B7AE-B72C66B74AAB}.Release|Any CPU.Build.0 = Release|Any CPU - {AFCE270E-F844-4A7C-9006-69AE622BB1F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AFCE270E-F844-4A7C-9006-69AE622BB1F4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AFCE270E-F844-4A7C-9006-69AE622BB1F4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AFCE270E-F844-4A7C-9006-69AE622BB1F4}.Release|Any CPU.Build.0 = Release|Any CPU {47F31305-6E68-4827-8E39-7B41DAA1CE7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {47F31305-6E68-4827-8E39-7B41DAA1CE7A}.Debug|Any CPU.Build.0 = Debug|Any CPU {47F31305-6E68-4827-8E39-7B41DAA1CE7A}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -81,6 +77,10 @@ Global {ECC954DA-8D4E-49EE-83AD-80085A43DEEB}.Debug|Any CPU.Build.0 = Debug|Any CPU {ECC954DA-8D4E-49EE-83AD-80085A43DEEB}.Release|Any CPU.ActiveCfg = Release|Any CPU {ECC954DA-8D4E-49EE-83AD-80085A43DEEB}.Release|Any CPU.Build.0 = Release|Any CPU + {DE4E802C-288C-45C4-84B6-8A5A6A96EF49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DE4E802C-288C-45C4-84B6-8A5A6A96EF49}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DE4E802C-288C-45C4-84B6-8A5A6A96EF49}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DE4E802C-288C-45C4-84B6-8A5A6A96EF49}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE