From 4e1981b2d7815c741adee70f4bb95fb5b2cf505d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dalibor=20Mesari=C4=87?= Date: Fri, 19 Feb 2021 20:13:33 +0100 Subject: [PATCH 1/5] Add start stop button on ServiceDetails page --- .../Dashboard/Pages/ServiceDetails.razor | 19 ++++++++++ src/Microsoft.Tye.Hosting/ProcessRunner.cs | 6 +-- src/Microsoft.Tye.Hosting/TyeDashboardApi.cs | 38 ++++++++++++++++++- src/Microsoft.Tye.Hosting/TyeHost.cs | 19 ++++++++-- 4 files changed, 74 insertions(+), 8 deletions(-) diff --git a/src/Microsoft.Tye.Hosting/Dashboard/Pages/ServiceDetails.razor b/src/Microsoft.Tye.Hosting/Dashboard/Pages/ServiceDetails.razor index 875912c55..1567c9956 100644 --- a/src/Microsoft.Tye.Hosting/Dashboard/Pages/ServiceDetails.razor +++ b/src/Microsoft.Tye.Hosting/Dashboard/Pages/ServiceDetails.razor @@ -1,5 +1,6 @@ @page "/services/{ServiceName}" @inject Application application +@inject HttpClient Http @if (Service == null) { @@ -9,6 +10,14 @@ else {

@Service.Description.Name

+ @if (_service?.Replicas != null) { + if (_service.Replicas.Any()) { + + } else { + + } + } + switch (Service.ServiceType) { case ServiceType.Container: @@ -36,4 +45,14 @@ else { application.Services.TryGetValue(ServiceName, out _service); } + + private async Task OnServiceStop() + { + await Http.GetAsync($"/api/v1/services/{ServiceName}/stop"); + } + + private async Task OnServiceStart() + { + await Http.GetAsync($"/api/v1/services/{ServiceName}/start"); + } } \ No newline at end of file diff --git a/src/Microsoft.Tye.Hosting/ProcessRunner.cs b/src/Microsoft.Tye.Hosting/ProcessRunner.cs index 706cfadcc..77d3895de 100644 --- a/src/Microsoft.Tye.Hosting/ProcessRunner.cs +++ b/src/Microsoft.Tye.Hosting/ProcessRunner.cs @@ -170,7 +170,7 @@ service.Description.RunInfo is ProjectRunInfo project2 && } } - private void LaunchService(Application application, Service service) + public void LaunchService(Application application, Service service) { var serviceDescription = service.Description; var processInfo = new ProcessInfo(new Task[service.Description.Replicas]); @@ -458,7 +458,7 @@ async Task RunApplicationAsync(IEnumerable<(int ExternalPort, int Port, string? service.Items[typeof(ProcessInfo)] = processInfo; } - private Task KillRunningProcesses(IDictionary services) + public Task KillRunningProcesses(IDictionary services) { static Task KillProcessAsync(Service service) { @@ -471,7 +471,7 @@ static Task KillProcessAsync(Service service) } return Task.CompletedTask; } - + var index = 0; var tasks = new Task[services.Count]; foreach (var s in services.Values) diff --git a/src/Microsoft.Tye.Hosting/TyeDashboardApi.cs b/src/Microsoft.Tye.Hosting/TyeDashboardApi.cs index 62c18329f..fe8fb0f10 100644 --- a/src/Microsoft.Tye.Hosting/TyeDashboardApi.cs +++ b/src/Microsoft.Tye.Hosting/TyeDashboardApi.cs @@ -20,8 +20,9 @@ namespace Microsoft.Tye.Hosting public class TyeDashboardApi { private readonly JsonSerializerOptions _options; + private readonly ProcessRunner _processRunner; - public TyeDashboardApi() + public TyeDashboardApi(ProcessRunner processRunner) { _options = new JsonSerializerOptions() { @@ -31,12 +32,15 @@ public TyeDashboardApi() }; _options.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)); + _processRunner = processRunner; } public void MapRoutes(IEndpointRouteBuilder endpoints) { endpoints.MapGet("/api/v1", ServiceIndex); endpoints.MapGet("/api/v1/services", Services); + endpoints.MapGet("/api/v1/services/{name}/stop", ServiceStop); + endpoints.MapGet("/api/v1/services/{name}/start", ServiceStart); endpoints.MapGet("/api/v1/services/{name}", Service); endpoints.MapGet("/api/v1/logs/{name}", Logs); endpoints.MapGet("/api/v1/metrics", AllMetrics); @@ -95,6 +99,38 @@ private Task Service(HttpContext context) return JsonSerializer.SerializeAsync(context.Response.Body, serviceJson, _options); } + private Task ServiceStart(HttpContext context) + { + var app = context.RequestServices.GetRequiredService(); + + var name = (string?)context.Request.RouteValues["name"]; + if (!string.IsNullOrEmpty(name) && app.Services.TryGetValue(name, out var service)) + { + _processRunner.LaunchService(app, service); + } + + context.Response.Redirect($"/services/{name}"); + + return Task.CompletedTask; + } + + private async Task ServiceStop(HttpContext context) + { + var app = context.RequestServices.GetRequiredService(); + + var name = (string?)context.Request.RouteValues["name"]; + if (!string.IsNullOrEmpty(name) && app.Services.TryGetValue(name, out var service)) + { + var services = new Dictionary(); + services.Add(name, service); + await _processRunner.KillRunningProcesses(services); + } + + context.Response.Redirect($"/services/{name}"); + + return; + } + private static V1Service CreateServiceJson(Service service) { var description = service.Description; diff --git a/src/Microsoft.Tye.Hosting/TyeHost.cs b/src/Microsoft.Tye.Hosting/TyeHost.cs index f073e441c..33b9363be 100644 --- a/src/Microsoft.Tye.Hosting/TyeHost.cs +++ b/src/Microsoft.Tye.Hosting/TyeHost.cs @@ -81,10 +81,10 @@ public async Task StartAsync() _logger.LogInformation("Executing application from {Source}", _application.Source); - ConfigureApplication(app); - _replicaRegistry = new ReplicaRegistry(_application.ContextDirectory, _logger); + ConfigureApplication(app); + _processor = CreateApplicationProcessor(_replicaRegistry, _options, _logger); await app.StartAsync(); @@ -175,6 +175,15 @@ private static WebApplication BuildWebApplication(Application application, HostO }); builder.Services.AddSingleton(application); + + builder.Services.AddScoped(sp => + { + var server = sp.GetRequiredService(); + var addressFeature = server.Features.Get(); + string baseAddress = addressFeature.Addresses.First(); + return new System.Net.Http.HttpClient { BaseAddress = new Uri(baseAddress) }; + }); + var app = builder.Build(); return app; } @@ -193,9 +202,11 @@ private void ConfigureApplication(WebApplication app) app.UseRouting(); - var api = new TyeDashboardApi(); + if (_logger != null && _replicaRegistry != null) { + var api = new TyeDashboardApi(new ProcessRunner(_logger, _replicaRegistry, ProcessRunnerOptions.FromHostOptions(_options))); - api.MapRoutes(app); + api.MapRoutes(app); + } app.MapBlazorHub(); app.MapFallbackToPage("/_Host"); From e473f59b955b8adaba544737e40faab98c9e2be7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dalibor=20Mesari=C4=87?= Date: Fri, 19 Feb 2021 20:55:15 +0100 Subject: [PATCH 2/5] Fix whitespace warnings --- src/Microsoft.Tye.Hosting/ProcessRunner.cs | 2 +- src/Microsoft.Tye.Hosting/TyeDashboardApi.cs | 4 ++-- src/Microsoft.Tye.Hosting/TyeHost.cs | 5 +++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.Tye.Hosting/ProcessRunner.cs b/src/Microsoft.Tye.Hosting/ProcessRunner.cs index 77d3895de..183e21fce 100644 --- a/src/Microsoft.Tye.Hosting/ProcessRunner.cs +++ b/src/Microsoft.Tye.Hosting/ProcessRunner.cs @@ -471,7 +471,7 @@ static Task KillProcessAsync(Service service) } return Task.CompletedTask; } - + var index = 0; var tasks = new Task[services.Count]; foreach (var s in services.Values) diff --git a/src/Microsoft.Tye.Hosting/TyeDashboardApi.cs b/src/Microsoft.Tye.Hosting/TyeDashboardApi.cs index fe8fb0f10..b150d5066 100644 --- a/src/Microsoft.Tye.Hosting/TyeDashboardApi.cs +++ b/src/Microsoft.Tye.Hosting/TyeDashboardApi.cs @@ -108,7 +108,7 @@ private Task ServiceStart(HttpContext context) { _processRunner.LaunchService(app, service); } - + context.Response.Redirect($"/services/{name}"); return Task.CompletedTask; @@ -125,7 +125,7 @@ private async Task ServiceStop(HttpContext context) services.Add(name, service); await _processRunner.KillRunningProcesses(services); } - + context.Response.Redirect($"/services/{name}"); return; diff --git a/src/Microsoft.Tye.Hosting/TyeHost.cs b/src/Microsoft.Tye.Hosting/TyeHost.cs index 33b9363be..2fd067385 100644 --- a/src/Microsoft.Tye.Hosting/TyeHost.cs +++ b/src/Microsoft.Tye.Hosting/TyeHost.cs @@ -177,7 +177,7 @@ private static WebApplication BuildWebApplication(Application application, HostO builder.Services.AddSingleton(application); builder.Services.AddScoped(sp => - { + { var server = sp.GetRequiredService(); var addressFeature = server.Features.Get(); string baseAddress = addressFeature.Addresses.First(); @@ -202,7 +202,8 @@ private void ConfigureApplication(WebApplication app) app.UseRouting(); - if (_logger != null && _replicaRegistry != null) { + if (_logger != null && _replicaRegistry != null) + { var api = new TyeDashboardApi(new ProcessRunner(_logger, _replicaRegistry, ProcessRunnerOptions.FromHostOptions(_options))); api.MapRoutes(app); From 91ee730b8f389c05bebcf9bc356aaf6a89da5308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dalibor=20Mesari=C4=87?= Date: Tue, 16 Mar 2021 20:19:05 +0100 Subject: [PATCH 3/5] Fix after merge --- src/Microsoft.Tye.Hosting/TyeHost.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Microsoft.Tye.Hosting/TyeHost.cs b/src/Microsoft.Tye.Hosting/TyeHost.cs index 02e98304b..8df183345 100644 --- a/src/Microsoft.Tye.Hosting/TyeHost.cs +++ b/src/Microsoft.Tye.Hosting/TyeHost.cs @@ -98,8 +98,6 @@ public async Task StartAsync() _replicaRegistry = new ReplicaRegistry(_application.ContextDirectory, _logger); - ConfigureApplication(app); - _processor = CreateApplicationProcessor(_replicaRegistry, _options, _logger); await app.StartAsync(); From 972e5712ebea1ff28e1ea6ed6d59a38216e5dc4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dalibor=20Mesari=C4=87?= Date: Wed, 7 Apr 2021 22:38:52 +0200 Subject: [PATCH 4/5] Make start and stop service endpoints POST --- .../Dashboard/Pages/ServiceDetails.razor | 4 ++-- src/Microsoft.Tye.Hosting/TyeDashboardApi.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.Tye.Hosting/Dashboard/Pages/ServiceDetails.razor b/src/Microsoft.Tye.Hosting/Dashboard/Pages/ServiceDetails.razor index 1567c9956..e8f3d4f38 100644 --- a/src/Microsoft.Tye.Hosting/Dashboard/Pages/ServiceDetails.razor +++ b/src/Microsoft.Tye.Hosting/Dashboard/Pages/ServiceDetails.razor @@ -48,11 +48,11 @@ else private async Task OnServiceStop() { - await Http.GetAsync($"/api/v1/services/{ServiceName}/stop"); + await Http.PostAsync($"/api/v1/services/{ServiceName}/stop", null); } private async Task OnServiceStart() { - await Http.GetAsync($"/api/v1/services/{ServiceName}/start"); + await Http.PostAsync($"/api/v1/services/{ServiceName}/start", null); } } \ No newline at end of file diff --git a/src/Microsoft.Tye.Hosting/TyeDashboardApi.cs b/src/Microsoft.Tye.Hosting/TyeDashboardApi.cs index b150d5066..1b687f8da 100644 --- a/src/Microsoft.Tye.Hosting/TyeDashboardApi.cs +++ b/src/Microsoft.Tye.Hosting/TyeDashboardApi.cs @@ -39,8 +39,8 @@ public void MapRoutes(IEndpointRouteBuilder endpoints) { endpoints.MapGet("/api/v1", ServiceIndex); endpoints.MapGet("/api/v1/services", Services); - endpoints.MapGet("/api/v1/services/{name}/stop", ServiceStop); - endpoints.MapGet("/api/v1/services/{name}/start", ServiceStart); + endpoints.MapPost("/api/v1/services/{name}/stop", ServiceStop); + endpoints.MapPost("/api/v1/services/{name}/start", ServiceStart); endpoints.MapGet("/api/v1/services/{name}", Service); endpoints.MapGet("/api/v1/logs/{name}", Logs); endpoints.MapGet("/api/v1/metrics", AllMetrics); From 8cbfb0544901df2cd378f049cedbd68621cd6742 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dalibor=20Mesari=C4=87?= Date: Mon, 2 Jan 2023 14:23:30 +0100 Subject: [PATCH 5/5] Fix compiler warning --- src/Microsoft.Tye.Hosting/TyeHost.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Tye.Hosting/TyeHost.cs b/src/Microsoft.Tye.Hosting/TyeHost.cs index dae659616..70536fd39 100644 --- a/src/Microsoft.Tye.Hosting/TyeHost.cs +++ b/src/Microsoft.Tye.Hosting/TyeHost.cs @@ -208,7 +208,7 @@ private IHost BuildWebApplication(Application application, HostOptions options, { var server = sp.GetRequiredService(); var addressFeature = server.Features.Get(); - string baseAddress = addressFeature.Addresses.First(); + var baseAddress = addressFeature?.Addresses.FirstOrDefault() ?? string.Empty; return new System.Net.Http.HttpClient { BaseAddress = new Uri(baseAddress) }; }); })