diff --git a/src/CLI/ArgumentParser.cs b/src/CLI/ArgumentParser.cs new file mode 100644 index 0000000..34d26f0 --- /dev/null +++ b/src/CLI/ArgumentParser.cs @@ -0,0 +1,40 @@ +using System; + +namespace CLI +{ + public class ArgumentParser + { + public bool Deploy { get; set; } = false; + public bool CleanStorage { get; set; } = false; + private bool[] matched; + private string[] arguments; + + public void Parse(string[] args) + { + arguments = args; + matched = new bool[args.Length]; + + Deploy = ParseArgument("--single-box-deploy"); + CleanStorage = ParseArgument("--clean-storage"); + + for (int i = 0; i < matched.Length; i++) + { + if (!matched[i]) + { + throw new Exception($"Did not recognize argument {args[i]}. Allowed arguments are \"--single-box-deploy\" and \"--clean-storage\""); + } + } + } + + private bool ParseArgument(string argument) + { + int cliOption = Array.FindIndex(arguments, option => option.Equals(argument)); + if (cliOption != -1) + { + matched[cliOption] = true; + return true; + } + return false; + } + } +} diff --git a/src/CLI/Deployer.cs b/src/CLI/Deployer.cs new file mode 100644 index 0000000..4759860 --- /dev/null +++ b/src/CLI/Deployer.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using ScaleUnitManagement.ScaleUnitFeatureManager.Common; +using ScaleUnitManagement.ScaleUnitFeatureManager.Hub; +using ScaleUnitManagement.ScaleUnitFeatureManager.ScaleUnit; +using ScaleUnitManagement.ScaleUnitFeatureManager.Utilities; +using ScaleUnitManagement.Utilities; +using ScaleUnitManagement.WorkloadSetupOrchestrator; + +namespace CLI +{ + internal class Deployer + { + private readonly List sortedScaleUnitInstances; + + public Deployer() + { + sortedScaleUnitInstances = Config.ScaleUnitInstances(); + sortedScaleUnitInstances.Sort(); + } + + public async Task Deploy() + { + if (!Config.UseSingleOneBox()) + { + throw new Exception("You can only use automatic deployment in a SingleOneBox environment"); + } + + await InitializeEnvironments(); + await PrepareEnvironments(); + await InstallWorkloads(); + + Console.WriteLine("\nHub and spoke environments have been deployed successfully!\n"); + } + + public async Task CleanStorage() + { + foreach (ScaleUnitInstance scaleUnit in sortedScaleUnitInstances) + { + Console.WriteLine($"\nCleaning environment on {scaleUnit.PrintableName()}"); + using var context = ScaleUnitContext.CreateContext(scaleUnit.ScaleUnitId); + var storageAccountManager = new StorageAccountManager(); + await storageAccountManager.CleanStorageAccount(); + } + } + + private async Task InitializeEnvironments() + { + foreach (ScaleUnitInstance scaleUnit in sortedScaleUnitInstances) + { + Console.WriteLine($"\nInitializing environment on {scaleUnit.PrintableName()}"); + using var context = ScaleUnitContext.CreateContext(scaleUnit.ScaleUnitId); + List steps = GetSteps(); + await RunSteps(steps); + + Console.WriteLine($"\nAll initialization steps completed for {scaleUnit.PrintableName()}"); + } + } + + private List GetSteps() + { + var sf = new StepFactory(); + List steps = sf.GetStepsOfType(); + if (ScaleUnitContext.GetScaleUnitId() == "@@") + { + steps.AddRange(sf.GetStepsOfType()); + } + else + { + steps.AddRange(sf.GetStepsOfType()); + } + steps.Sort((x, y) => x.Priority().CompareTo(y.Priority())); + return steps; + } + + private async Task RunSteps(List steps) + { + for (int i = 0; i < steps.Count; i++) + { + try + { + Console.WriteLine("\nExecuting step: " + steps[i].Label()); + await steps[i].Run(); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error occurred while enabling scale unit feature:\n{ex}"); + } + } + } + + private async Task PrepareEnvironments() + { + foreach (ScaleUnitInstance scaleUnit in sortedScaleUnitInstances) + { + using var context = ScaleUnitContext.CreateContext(scaleUnit.ScaleUnitId); + Console.WriteLine($"\nPreparing {scaleUnit.PrintableName()} for installation"); + if (scaleUnit.ScaleUnitId.Equals("@@")) + { + await new HubConfigurationManager().Configure(); + } + else + { + await new ScaleUnitConfigurationManager().Configure(); + } + } + } + + private async Task InstallWorkloads() + { + foreach (ScaleUnitInstance scaleUnit in sortedScaleUnitInstances) + { + using var context = ScaleUnitContext.CreateContext(scaleUnit.ScaleUnitId); + Console.WriteLine($"\nInstalling workloads on {scaleUnit.PrintableName()}"); + if (scaleUnit.IsHub()) + { + await new HubWorkloadInstaller().Install(); + } + else + { + await new ScaleUnitWorkloadInstaller().Install(); + } + } + } + } +} + + diff --git a/src/CLI/Program.cs b/src/CLI/Program.cs index 430d224..f59cbb4 100644 --- a/src/CLI/Program.cs +++ b/src/CLI/Program.cs @@ -1,3 +1,4 @@ +using System; using System.Threading.Tasks; using CLIFramework; using ScaleUnitManagement.ScaleUnitFeatureManager.Utilities; @@ -6,12 +7,38 @@ namespace CLI { public class Program { - public static async Task Main(string[] args) { CheckForAdminAccess.ValidateCurrentUserIsProcessAdmin(); - await CLIController.Run(new RootMenu()); + if (args.Length == 0) + { + await CLIController.Run(new RootMenu()); + return; + } + + var argumentParser = new ArgumentParser(); + try + { + argumentParser.Parse(args); + } + catch (Exception ex) + { + Console.WriteLine(ex); + return; + } + + var deployer = new Deployer(); + + if (argumentParser.CleanStorage) + { + await deployer.CleanStorage(); + } + + if (argumentParser.Deploy) + { + await deployer.Deploy(); + } } } } diff --git a/src/ScaleUnitManagementTests/ArgumentParserTest.cs b/src/ScaleUnitManagementTests/ArgumentParserTest.cs new file mode 100644 index 0000000..54f8a44 --- /dev/null +++ b/src/ScaleUnitManagementTests/ArgumentParserTest.cs @@ -0,0 +1,52 @@ +using System; +using CLI; +using FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace ScaleUnitManagementTests +{ + [TestClass] + public sealed class ArgumentParserTest + { + private ArgumentParser argumentParser; + + [TestInitialize] + public void Setup() + { + argumentParser = new ArgumentParser(); + } + + [TestMethod] + public void BeforeParsing_HasInitialValues() + { + // Arrange + Act + Assert + argumentParser.Deploy.Should().BeFalse(); + argumentParser.CleanStorage.Should().BeFalse(); + } + + [TestMethod] + public void Parse_WithValidArguments_SetsValues() + { + // Arrange + Act + string[] arguments = { "--single-box-deploy", "--clean-storage" }; + argumentParser.Parse(arguments); + + // Assert + argumentParser.Deploy.Should().BeTrue(); + argumentParser.CleanStorage.Should().BeTrue(); + } + + [TestMethod] + public void Parse_WithInvalidArgument_ThrowsError() + { + // Arrange + string[] arguments = { "--single-box-deploy --unknown-argument" }; + + // Act + Action act = () => argumentParser.Parse(arguments); + + // Assert + act.Should().Throw(); + } + } +} diff --git a/src/ScaleUnitManagementTests/ScaleUnitManagementTests.csproj b/src/ScaleUnitManagementTests/ScaleUnitManagementTests.csproj index 7d520dc..98b3c6d 100644 --- a/src/ScaleUnitManagementTests/ScaleUnitManagementTests.csproj +++ b/src/ScaleUnitManagementTests/ScaleUnitManagementTests.csproj @@ -15,6 +15,7 @@ +