From 2da11c7365160ae073bbc41c03eb2da2a6d87e84 Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Tue, 14 Feb 2023 10:55:51 +0300 Subject: [PATCH 1/6] Create SuiteAppSettingsService.cs --- .../Services/SuiteAppSettingsService.cs | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs new file mode 100644 index 0000000000..c453c35349 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs @@ -0,0 +1,73 @@ +using System; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Newtonsoft.Json.Linq; +using Volo.Abp.Cli.Utils; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Cli.Commands.Services; + +public class SuiteAppSettingsService : ITransientDependency +{ + private const int DefaultPort = 3000; + + public CmdHelper CmdHelper { get; } + + public SuiteAppSettingsService(CmdHelper cmdHelper) + { + CmdHelper = cmdHelper; + } + public async Task GetSuitePortAsync(string version) + { + var filePath = GetFilePathOrNull(version); + + if (filePath == null) + { + return DefaultPort; + } + + var content = File.ReadAllText(filePath); + + var contentAsJson = JObject.Parse(content); + + var url = contentAsJson["AbpSuite"]?["ApplicationUrl"]?.ToString(); + + if (url == null) + { + return DefaultPort; + } + + return Convert.ToInt32(url.Split(":").Last()); + } + + private string GetFilePathOrNull(string version) + { + var suiteVersion = version; + + if (suiteVersion == null) + { + return null; + } + + var path = Path.Combine( + "%USERPROFILE%", + ".dotnet", + "tools", + ".store", + "volo.abp.suite", + suiteVersion, + "volo.abp.suite", + suiteVersion, + "content", + "appsettings.json" + ); + + if (!File.Exists(path)) + { + return null; + } + + return path; + } +} \ No newline at end of file From ea8c65c292dc496975ce3b9b7552673beb149df7 Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Tue, 14 Feb 2023 10:56:20 +0300 Subject: [PATCH 2/6] Check if suite is already working or port is in use by another process --- .../Volo/Abp/Cli/Commands/SuiteCommand.cs | 65 ++++++++++++++----- 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SuiteCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SuiteCommand.cs index 73198c93bc..b93dc6808f 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SuiteCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/SuiteCommand.cs @@ -35,23 +35,26 @@ public class SuiteCommand : IConsoleCommand, ITransientDependency private readonly NuGetService _nuGetService; private readonly AuthService _authService; private readonly CliHttpClientFactory _cliHttpClientFactory; + private readonly SuiteAppSettingsService _suiteAppSettingsService; private const string SuitePackageName = "Volo.Abp.Suite"; public ILogger Logger { get; set; } - private const string AbpSuiteHost = "http://localhost:3000"; + private int _abpSuitePort = 3000; public SuiteCommand( AbpNuGetIndexUrlService nuGetIndexUrlService, NuGetService nuGetService, ICmdHelper cmdHelper, AuthService authService, - CliHttpClientFactory cliHttpClientFactory) + CliHttpClientFactory cliHttpClientFactory, + SuiteAppSettingsService suiteAppSettingsService) { CmdHelper = cmdHelper; _nuGetIndexUrlService = nuGetIndexUrlService; _nuGetService = nuGetService; _authService = authService; _cliHttpClientFactory = cliHttpClientFactory; + _suiteAppSettingsService = suiteAppSettingsService; Logger = NullLogger.Instance; } @@ -72,17 +75,20 @@ public class SuiteCommand : IConsoleCommand, ITransientDependency commandLineArgs.Options.ContainsKey(Options.Preview.Long); var version = commandLineArgs.Options.GetOrNull(Options.Version.Short, Options.Version.Long); + var currentSuiteVersionAsString = GetCurrentSuiteVersion(); switch (operationType) { case "": case null: - await InstallSuiteIfNotInstalledAsync(); + await InstallSuiteIfNotInstalledAsync(currentSuiteVersionAsString); + _abpSuitePort = await _suiteAppSettingsService.GetSuitePortAsync(currentSuiteVersionAsString); RunSuite(); break; case "generate": - await InstallSuiteIfNotInstalledAsync(); + await InstallSuiteIfNotInstalledAsync(currentSuiteVersionAsString); + _abpSuitePort = await _suiteAppSettingsService.GetSuitePortAsync(currentSuiteVersionAsString); var suiteProcess = StartSuite(); System.Threading.Thread.Sleep(500); //wait for initialization of the app await GenerateCrudPageAsync(commandLineArgs); @@ -130,7 +136,7 @@ public class SuiteCommand : IConsoleCommand, ITransientDependency } var IsSolutionBuiltResponse = await client.GetAsync( - $"{AbpSuiteHost}/api/abpSuite/solutions/{solutionId.ToString()}/is-built" + $"http://localhost:{_abpSuitePort}/api/abpSuite/solutions/{solutionId.ToString()}/is-built" ); var IsSolutionBuilt = Convert.ToBoolean(await IsSolutionBuiltResponse.Content.ReadAsStringAsync()); @@ -148,7 +154,7 @@ public class SuiteCommand : IConsoleCommand, ITransientDependency ); var responseMessage = await client.PostAsync( - $"{AbpSuiteHost}/api/abpSuite/crudPageGenerator/{solutionId.ToString()}/save-and-generate-entity", + $"http://localhost:{_abpSuitePort}/api/abpSuite/crudPageGenerator/{solutionId.ToString()}/save-and-generate-entity", entityContent ); @@ -178,7 +184,7 @@ public class SuiteCommand : IConsoleCommand, ITransientDependency } var responseMessage = await client.GetHttpResponseMessageWithRetryAsync( - "http://localhost:3000/api/abpSuite/solutions", + $"http://localhost:{_abpSuitePort}/api/abpSuite/solutions", _cliHttpClientFactory.GetCancellationToken(TimeSpan.FromMinutes(10)), Logger, timeIntervals.ToArray()); @@ -216,7 +222,7 @@ public class SuiteCommand : IConsoleCommand, ITransientDependency ); var responseMessage = await client.PostAsync( - "http://localhost:3000/api/abpSuite/addSolution", + $"http://localhost:{_abpSuitePort}/api/abpSuite/addSolution", entityContent, _cliHttpClientFactory.GetCancellationToken(TimeSpan.FromMinutes(10)) ); @@ -234,11 +240,9 @@ public class SuiteCommand : IConsoleCommand, ITransientDependency } } - private async Task InstallSuiteIfNotInstalledAsync() + private async Task InstallSuiteIfNotInstalledAsync(string currentSuiteVersion) { - var currentSuiteVersionAsString = GetCurrentSuiteVersion(); - - if (string.IsNullOrEmpty(currentSuiteVersionAsString)) + if (string.IsNullOrEmpty(currentSuiteVersion)) { await InstallSuiteAsync(); } @@ -430,6 +434,19 @@ public class SuiteCommand : IConsoleCommand, ITransientDependency Logger.LogWarning("Couldn't check ABP Suite installed status: " + ex.Message); } + if (IsSuiteAlreadyRunning()) + { + Logger.LogInformation("Opening suite..."); + CmdHelper.Open($"http://localhost:{_abpSuitePort}"); + return; + } + + if (IsPortAlreadyInUse()) + { + Logger.LogError($"Port \"{_abpSuitePort}\" is already in use."); + return; + } + CmdHelper.RunCmd("abp-suite"); } @@ -453,23 +470,32 @@ public class SuiteCommand : IConsoleCommand, ITransientDependency return null; } + if (IsPortAlreadyInUse()) + { + Logger.LogError($"Port \"{_abpSuitePort}\" is already in use."); + return null; + } + return CmdHelper.RunCmdAndGetProcess("abp-suite --no-browser"); } private bool IsSuiteAlreadyRunning() + { + return GetProcessesRelatedWithSuite().Any(); + } + + private bool IsPortAlreadyInUse() { var ipGP = IPGlobalProperties.GetIPGlobalProperties(); var endpoints = ipGP.GetActiveTcpListeners(); - return endpoints.Any(e => e.Port == 3000); + return endpoints.Any(e => e.Port == _abpSuitePort); } private void KillSuite() { try { - var suiteProcesses = (from p in Process.GetProcesses() - where p.ProcessName.ToLower().Contains("abp-suite") - select p); + var suiteProcesses = GetProcessesRelatedWithSuite(); foreach (var suiteProcess in suiteProcesses) { @@ -483,6 +509,13 @@ public class SuiteCommand : IConsoleCommand, ITransientDependency } } + private IEnumerable GetProcessesRelatedWithSuite() + { + return (from p in Process.GetProcesses() + where p.ProcessName.ToLower().Contains("abp-suite") + select p); + } + public string GetUsageInfo() { var sb = new StringBuilder(); From 98daaa35d3521e1b0e2f5fba6da03dc79d534ebd Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Tue, 14 Feb 2023 11:51:02 +0300 Subject: [PATCH 3/6] Cli: Fix Suite's appsettings.json path --- .../Abp/Cli/Commands/Services/SuiteAppSettingsService.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs index c453c35349..f3b7d63a42 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs @@ -51,7 +51,7 @@ public class SuiteAppSettingsService : ITransientDependency } var path = Path.Combine( - "%USERPROFILE%", + Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".dotnet", "tools", ".store", @@ -59,7 +59,9 @@ public class SuiteAppSettingsService : ITransientDependency suiteVersion, "volo.abp.suite", suiteVersion, - "content", + "tools", + "net7.0", + "any", "appsettings.json" ); From 0d9107ba02cd692dcd33f35051fd24d96bf6b109 Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Tue, 14 Feb 2023 12:01:14 +0300 Subject: [PATCH 4/6] Cli: Add GetSuitePortAsync without parameter --- .../Services/SuiteAppSettingsService.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs index f3b7d63a42..9b696c08ee 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs @@ -18,6 +18,10 @@ public class SuiteAppSettingsService : ITransientDependency { CmdHelper = cmdHelper; } + public async Task GetSuitePortAsync() + { + return await GetSuitePortAsync(GetCurrentSuiteVersion()); + } public async Task GetSuitePortAsync(string version) { var filePath = GetFilePathOrNull(version); @@ -72,4 +76,19 @@ public class SuiteAppSettingsService : ITransientDependency return path; } + + private string GetCurrentSuiteVersion() + { + var dotnetToolList = CmdHelper.RunCmdAndGetOutput("dotnet tool list -g", out int exitCode); + + var suiteLine = dotnetToolList.Split(Environment.NewLine) + .FirstOrDefault(l => l.ToLower().StartsWith("volo.abp.suite ")); + + if (string.IsNullOrEmpty(suiteLine)) + { + return null; + } + + return suiteLine.Split(" ", StringSplitOptions.RemoveEmptyEntries)[1]; + } } \ No newline at end of file From 1fcc300cdfb01db55ff2db1cfa83cf215ff9e551 Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Tue, 14 Feb 2023 12:08:46 +0300 Subject: [PATCH 5/6] Update SuiteAppSettingsService.cs --- .../Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs index 9b696c08ee..d74241f103 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs @@ -18,10 +18,12 @@ public class SuiteAppSettingsService : ITransientDependency { CmdHelper = cmdHelper; } + public async Task GetSuitePortAsync() { return await GetSuitePortAsync(GetCurrentSuiteVersion()); } + public async Task GetSuitePortAsync(string version) { var filePath = GetFilePathOrNull(version); From 6b1342705d8632b518af237df5103e49bf7aa3a3 Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Tue, 14 Feb 2023 16:19:20 +0300 Subject: [PATCH 6/6] Update SuiteAppSettingsService.cs --- .../Cli/Commands/Services/SuiteAppSettingsService.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs index d74241f103..d274234ded 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SuiteAppSettingsService.cs @@ -49,9 +49,7 @@ public class SuiteAppSettingsService : ITransientDependency private string GetFilePathOrNull(string version) { - var suiteVersion = version; - - if (suiteVersion == null) + if (version == null) { return null; } @@ -62,9 +60,9 @@ public class SuiteAppSettingsService : ITransientDependency "tools", ".store", "volo.abp.suite", - suiteVersion, + version, "volo.abp.suite", - suiteVersion, + version, "tools", "net7.0", "any", @@ -93,4 +91,4 @@ public class SuiteAppSettingsService : ITransientDependency return suiteLine.Split(" ", StringSplitOptions.RemoveEmptyEntries)[1]; } -} \ No newline at end of file +}