From 6d4910b1f54b7e98100c8e65857f2baeb578de1b Mon Sep 17 00:00:00 2001 From: David Fowler Date: Wed, 25 Mar 2020 11:35:21 -0700 Subject: [PATCH] Random cleanup (#198) * Random cleanup - Remove fully qualified namespaces - Deleted some unused types - Move types to infrastructure - Move path normalization to ApplicationFactory layer - Renamed IngressService to HttpProxyService --- src/Microsoft.Tye.Core/ApplicationFactory.cs | 30 +++-- src/Microsoft.Tye.Core/Service.cs | 36 ------ .../AggregateApplicationProcessor.cs | 4 +- src/Microsoft.Tye.Hosting/DockerRunner.cs | 10 +- .../EventPipeDiagnosticsRunner.cs | 4 +- ...{IngressService.cs => HttpProxyService.cs} | 115 +----------------- .../IApplicationProcessor.cs | 4 +- .../Infrastructure/ConnectionRetryHandler.cs | 67 ++++++++++ .../{ => Infrastructure}/ProxyExtensions.cs | 0 .../Infrastructure/ServiceLoggerProvider.cs | 61 ++++++++++ .../Model/PortMapping.cs | 15 --- .../Model/ServiceState.cs | 14 --- src/Microsoft.Tye.Hosting/ProcessRunner.cs | 26 ++-- src/Microsoft.Tye.Hosting/ProxyService.cs | 6 +- .../TransformProjectsIntoContainers.cs | 13 +- src/Microsoft.Tye.Hosting/TyeDashboardApi.cs | 6 +- src/Microsoft.Tye.Hosting/TyeHost.cs | 19 +-- src/tye/ApplicationBuilderExtensions.cs | 22 ++-- 18 files changed, 209 insertions(+), 243 deletions(-) delete mode 100644 src/Microsoft.Tye.Core/Service.cs rename src/Microsoft.Tye.Hosting/{IngressService.cs => HttpProxyService.cs} (63%) create mode 100644 src/Microsoft.Tye.Hosting/Infrastructure/ConnectionRetryHandler.cs rename src/Microsoft.Tye.Hosting/{ => Infrastructure}/ProxyExtensions.cs (100%) create mode 100644 src/Microsoft.Tye.Hosting/Infrastructure/ServiceLoggerProvider.cs delete mode 100644 src/Microsoft.Tye.Hosting/Model/PortMapping.cs delete mode 100644 src/Microsoft.Tye.Hosting/Model/ServiceState.cs diff --git a/src/Microsoft.Tye.Core/ApplicationFactory.cs b/src/Microsoft.Tye.Core/ApplicationFactory.cs index 7952cb16..3ebcf0d2 100644 --- a/src/Microsoft.Tye.Core/ApplicationFactory.cs +++ b/src/Microsoft.Tye.Core/ApplicationFactory.cs @@ -55,17 +55,33 @@ namespace Microsoft.Tye } else if (!string.IsNullOrEmpty(configService.Image)) { - var container = new ContainerServiceBuilder(configService.Name, configService.Image); - container.Args = configService.Args; - container.Replicas = configService.Replicas ?? 1; + var container = new ContainerServiceBuilder(configService.Name, configService.Image) + { + Args = configService.Args, + Replicas = configService.Replicas ?? 1 + }; service = container; } else if (!string.IsNullOrEmpty(configService.Executable)) { - var executable = new ExecutableServiceBuilder(configService.Name, configService.Executable); - executable.Args = configService.Args; - executable.WorkingDirectory = configService.WorkingDirectory; - executable.Replicas = configService.Replicas ?? 1; + var expandedExecutable = Environment.ExpandEnvironmentVariables(configService.Executable); + var workingDirectory = ""; + + // Special handling of .dlls as executables (it will be executed as dotnet {dll}) + if (Path.GetExtension(expandedExecutable) == ".dll") + { + expandedExecutable = Path.GetFullPath(Path.Combine(builder.Source.Directory.FullName, expandedExecutable)); + workingDirectory = Path.GetDirectoryName(expandedExecutable)!; + } + + var executable = new ExecutableServiceBuilder(configService.Name, expandedExecutable) + { + Args = configService.Args, + WorkingDirectory = configService.WorkingDirectory != null ? + Path.GetFullPath(Path.Combine(builder.Source.Directory.FullName, Environment.ExpandEnvironmentVariables(configService.WorkingDirectory))) : + workingDirectory, + Replicas = configService.Replicas ?? 1 + }; service = executable; } else if (configService.External) diff --git a/src/Microsoft.Tye.Core/Service.cs b/src/Microsoft.Tye.Core/Service.cs deleted file mode 100644 index 34348d12..00000000 --- a/src/Microsoft.Tye.Core/Service.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Generic; - -namespace Microsoft.Tye -{ - public sealed class Service - { - public Service(string name) - { - if (name is null) - { - throw new ArgumentNullException(nameof(name)); - } - - Name = name; - } - - public string Name { get; } - - public GeneratedAssets GeneratedAssets { get; } = new GeneratedAssets(); - - public Source? Source { get; set; } - - public Dictionary Environment { get; set; } = new Dictionary(); - - // Represents bindings *published* by this service - // See GeneratedAssets for bindings consumed by the service - public List Bindings { get; } = new List(); - - public int Replicas { get; set; } - } -} diff --git a/src/Microsoft.Tye.Hosting/AggregateApplicationProcessor.cs b/src/Microsoft.Tye.Hosting/AggregateApplicationProcessor.cs index 2b557056..900aa069 100644 --- a/src/Microsoft.Tye.Hosting/AggregateApplicationProcessor.cs +++ b/src/Microsoft.Tye.Hosting/AggregateApplicationProcessor.cs @@ -18,7 +18,7 @@ namespace Microsoft.Tye.Hosting _applicationProcessors = applicationProcessors; } - public async Task StartAsync(Tye.Hosting.Model.Application application) + public async Task StartAsync(Application application) { foreach (var processor in _applicationProcessors) { @@ -26,7 +26,7 @@ namespace Microsoft.Tye.Hosting } } - public async Task StopAsync(Tye.Hosting.Model.Application application) + public async Task StopAsync(Application application) { // Shutdown in the opposite order foreach (var processor in _applicationProcessors.Reverse()) diff --git a/src/Microsoft.Tye.Hosting/DockerRunner.cs b/src/Microsoft.Tye.Hosting/DockerRunner.cs index 889f71f1..dd930e9d 100644 --- a/src/Microsoft.Tye.Hosting/DockerRunner.cs +++ b/src/Microsoft.Tye.Hosting/DockerRunner.cs @@ -22,7 +22,7 @@ namespace Microsoft.Tye.Hosting _logger = logger; } - public Task StartAsync(Tye.Hosting.Model.Application application) + public Task StartAsync(Application application) { var tasks = new Task[application.Services.Count]; var index = 0; @@ -34,7 +34,7 @@ namespace Microsoft.Tye.Hosting return Task.WhenAll(tasks); } - public Task StopAsync(Tye.Hosting.Model.Application application) + public Task StopAsync(Application application) { var services = application.Services; @@ -49,7 +49,7 @@ namespace Microsoft.Tye.Hosting return Task.WhenAll(tasks); } - private async Task StartContainerAsync(Tye.Hosting.Model.Application application, Tye.Hosting.Model.Service service, DockerRunInfo docker) + private async Task StartContainerAsync(Application application, Service service, DockerRunInfo docker) { if (!await DockerDetector.Instance.IsDockerInstalled.Value) { @@ -260,7 +260,7 @@ namespace Microsoft.Tye.Hosting service.Items[typeof(DockerInformation)] = dockerInfo; } - private static void PrintStdOutAndErr(Tye.Hosting.Model.Service service, string replica, ProcessResult result) + private static void PrintStdOutAndErr(Service service, string replica, ProcessResult result) { if (result.ExitCode != 0) { @@ -276,7 +276,7 @@ namespace Microsoft.Tye.Hosting } } - private async Task StopContainerAsync(Tye.Hosting.Model.Service service) + private async Task StopContainerAsync(Service service) { if (service.Items.TryGetValue(typeof(DockerInformation), out var value) && value is DockerInformation di) { diff --git a/src/Microsoft.Tye.Hosting/EventPipeDiagnosticsRunner.cs b/src/Microsoft.Tye.Hosting/EventPipeDiagnosticsRunner.cs index 99800bb5..eb7798fa 100644 --- a/src/Microsoft.Tye.Hosting/EventPipeDiagnosticsRunner.cs +++ b/src/Microsoft.Tye.Hosting/EventPipeDiagnosticsRunner.cs @@ -23,7 +23,7 @@ namespace Microsoft.Tye.Hosting _diagnosticsCollector = diagnosticsCollector; } - public Task StartAsync(Tye.Hosting.Model.Application application) + public Task StartAsync(Application application) { foreach (var service in application.Services.Values) { @@ -38,7 +38,7 @@ namespace Microsoft.Tye.Hosting return Task.CompletedTask; } - public Task StopAsync(Tye.Hosting.Model.Application application) + public Task StopAsync(Application application) { foreach (var service in application.Services.Values) { diff --git a/src/Microsoft.Tye.Hosting/IngressService.cs b/src/Microsoft.Tye.Hosting/HttpProxyService.cs similarity index 63% rename from src/Microsoft.Tye.Hosting/IngressService.cs rename to src/Microsoft.Tye.Hosting/HttpProxyService.cs index 9adefcac..ea05b847 100644 --- a/src/Microsoft.Tye.Hosting/IngressService.cs +++ b/src/Microsoft.Tye.Hosting/HttpProxyService.cs @@ -6,9 +6,6 @@ using System; using System.Collections.Generic; using System.Net; using System.Net.Http; -using System.Net.Sockets; -using System.Reactive.Subjects; -using System.Runtime.ExceptionServices; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; @@ -23,17 +20,17 @@ using Microsoft.Tye.Hosting.Model; namespace Microsoft.Tye.Hosting { - public class IngressService : IApplicationProcessor + public partial class HttpProxyService : IApplicationProcessor { private List _webApplications = new List(); private readonly ILogger _logger; - public IngressService(ILogger logger) + public HttpProxyService(ILogger logger) { _logger = logger; } - public async Task StartAsync(Model.Application application) + public async Task StartAsync(Application application) { var invoker = new HttpMessageInvoker(new ConnectionRetryHandler(new SocketsHttpHandler { @@ -161,7 +158,7 @@ namespace Microsoft.Tye.Hosting } } - public async Task StopAsync(Model.Application application) + public async Task StopAsync(Application application) { foreach (var webApp in _webApplications) { @@ -179,109 +176,5 @@ namespace Microsoft.Tye.Hosting } } } - - private class ConnectionRetryHandler : DelegatingHandler - { - private static readonly int MaxRetries = 3; - private static readonly TimeSpan InitialRetryDelay = TimeSpan.FromMilliseconds(1000); - - public ConnectionRetryHandler(HttpMessageHandler innerHandler) - : base(innerHandler) - { - } - - protected override async Task SendAsync( - HttpRequestMessage request, - CancellationToken cancellationToken) - { - HttpResponseMessage? response = null; - var delay = InitialRetryDelay; - Exception? exception = null; - - for (var i = 0; i < MaxRetries; i++) - { - try - { - response = await base.SendAsync(request, cancellationToken); - } - catch (HttpRequestException ex) when (ex.InnerException is SocketException) - { - if (i == MaxRetries - 1) - { - throw; - } - - exception = ex; - } - - if (response != null && - (response.IsSuccessStatusCode || response.StatusCode != HttpStatusCode.ServiceUnavailable)) - { - return response; - } - - await Task.Delay(delay, cancellationToken); - delay *= 2; - } - - if (exception != null) - { - ExceptionDispatchInfo.Throw(exception); - } - - throw new TimeoutException(); - } - } - - private class ServiceLoggerProvider : ILoggerProvider - { - private readonly Subject _logs; - - public ServiceLoggerProvider(Subject logs) - { - _logs = logs; - } - - public ILogger CreateLogger(string categoryName) - { - return new ServiceLogger(categoryName, _logs); - } - - public void Dispose() - { - } - - private class ServiceLogger : ILogger - { - private readonly string _categoryName; - private readonly Subject _logs; - - public ServiceLogger(string categoryName, Subject logs) - { - _categoryName = categoryName; - _logs = logs; - } - - public IDisposable? BeginScope(TState state) - { - return null; - } - - public bool IsEnabled(LogLevel logLevel) - { - return true; - } - - public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) - { - _logs.OnNext($"[{logLevel}]: {formatter(state, exception)}"); - - if (exception != null) - { - _logs.OnNext(exception.ToString()); - } - } - } - } } } diff --git a/src/Microsoft.Tye.Hosting/IApplicationProcessor.cs b/src/Microsoft.Tye.Hosting/IApplicationProcessor.cs index 1f4a2d56..9284cb50 100644 --- a/src/Microsoft.Tye.Hosting/IApplicationProcessor.cs +++ b/src/Microsoft.Tye.Hosting/IApplicationProcessor.cs @@ -9,8 +9,8 @@ namespace Microsoft.Tye.Hosting { public interface IApplicationProcessor { - Task StartAsync(Tye.Hosting.Model.Application application); + Task StartAsync(Application application); - Task StopAsync(Tye.Hosting.Model.Application application); + Task StopAsync(Application application); } } diff --git a/src/Microsoft.Tye.Hosting/Infrastructure/ConnectionRetryHandler.cs b/src/Microsoft.Tye.Hosting/Infrastructure/ConnectionRetryHandler.cs new file mode 100644 index 00000000..43091d40 --- /dev/null +++ b/src/Microsoft.Tye.Hosting/Infrastructure/ConnectionRetryHandler.cs @@ -0,0 +1,67 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Net; +using System.Net.Http; +using System.Net.Sockets; +using System.Runtime.ExceptionServices; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.Tye.Hosting +{ + internal class ConnectionRetryHandler : DelegatingHandler + { + private static readonly int MaxRetries = 3; + private static readonly TimeSpan InitialRetryDelay = TimeSpan.FromMilliseconds(1000); + + public ConnectionRetryHandler(HttpMessageHandler innerHandler) + : base(innerHandler) + { + } + + protected override async Task SendAsync( + HttpRequestMessage request, + CancellationToken cancellationToken) + { + HttpResponseMessage? response = null; + var delay = InitialRetryDelay; + Exception? exception = null; + + for (var i = 0; i < MaxRetries; i++) + { + try + { + response = await base.SendAsync(request, cancellationToken); + } + catch (HttpRequestException ex) when (ex.InnerException is SocketException) + { + if (i == MaxRetries - 1) + { + throw; + } + + exception = ex; + } + + if (response != null && + (response.IsSuccessStatusCode || response.StatusCode != HttpStatusCode.ServiceUnavailable)) + { + return response; + } + + await Task.Delay(delay, cancellationToken); + delay *= 2; + } + + if (exception != null) + { + ExceptionDispatchInfo.Throw(exception); + } + + throw new TimeoutException(); + } + } +} diff --git a/src/Microsoft.Tye.Hosting/ProxyExtensions.cs b/src/Microsoft.Tye.Hosting/Infrastructure/ProxyExtensions.cs similarity index 100% rename from src/Microsoft.Tye.Hosting/ProxyExtensions.cs rename to src/Microsoft.Tye.Hosting/Infrastructure/ProxyExtensions.cs diff --git a/src/Microsoft.Tye.Hosting/Infrastructure/ServiceLoggerProvider.cs b/src/Microsoft.Tye.Hosting/Infrastructure/ServiceLoggerProvider.cs new file mode 100644 index 00000000..eac51434 --- /dev/null +++ b/src/Microsoft.Tye.Hosting/Infrastructure/ServiceLoggerProvider.cs @@ -0,0 +1,61 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Reactive.Subjects; +using Microsoft.Extensions.Logging; + +namespace Microsoft.Tye.Hosting +{ + internal class ServiceLoggerProvider : ILoggerProvider + { + private readonly Subject _logs; + + public ServiceLoggerProvider(Subject logs) + { + _logs = logs; + } + + public ILogger CreateLogger(string categoryName) + { + return new ServiceLogger(categoryName, _logs); + } + + public void Dispose() + { + } + + private class ServiceLogger : ILogger + { + private readonly string _categoryName; + private readonly Subject _logs; + + public ServiceLogger(string categoryName, Subject logs) + { + _categoryName = categoryName; + _logs = logs; + } + + public IDisposable? BeginScope(TState state) + { + return null; + } + + public bool IsEnabled(LogLevel logLevel) + { + return true; + } + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + { + _logs.OnNext($"[{logLevel}]: {formatter(state, exception)}"); + + if (exception != null) + { + _logs.OnNext(exception.ToString()); + } + } + } + } +} diff --git a/src/Microsoft.Tye.Hosting/Model/PortMapping.cs b/src/Microsoft.Tye.Hosting/Model/PortMapping.cs deleted file mode 100644 index 305c6e20..00000000 --- a/src/Microsoft.Tye.Hosting/Model/PortMapping.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; - -namespace Microsoft.Tye.Hosting.Model -{ - public class PortMapping - { - public int ExternalPort { get; set; } - - public List InternalPorts { get; set; } = new List(); - } -} diff --git a/src/Microsoft.Tye.Hosting/Model/ServiceState.cs b/src/Microsoft.Tye.Hosting/Model/ServiceState.cs deleted file mode 100644 index 6adcf6b2..00000000 --- a/src/Microsoft.Tye.Hosting/Model/ServiceState.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace Microsoft.Tye.Hosting.Model -{ - public enum ServiceState - { - Starting, - Running, - NotRunning, - Stopped - } -} diff --git a/src/Microsoft.Tye.Hosting/ProcessRunner.cs b/src/Microsoft.Tye.Hosting/ProcessRunner.cs index 5899a8e7..f7b009e0 100644 --- a/src/Microsoft.Tye.Hosting/ProcessRunner.cs +++ b/src/Microsoft.Tye.Hosting/ProcessRunner.cs @@ -4,14 +4,14 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; -using Microsoft.Tye.Hosting.Model; using Microsoft.Extensions.Logging; -using System.Diagnostics; +using Microsoft.Tye.Hosting.Model; namespace Microsoft.Tye.Hosting { @@ -26,7 +26,7 @@ namespace Microsoft.Tye.Hosting _options = options; } - public Task StartAsync(Tye.Hosting.Model.Application application) + public Task StartAsync(Application application) { var tasks = new Task[application.Services.Count]; var index = 0; @@ -44,12 +44,12 @@ namespace Microsoft.Tye.Hosting return Task.WhenAll(tasks); } - public Task StopAsync(Tye.Hosting.Model.Application application) + public Task StopAsync(Application application) { return KillRunningProcesses(application.Services); } - private async Task LaunchService(Tye.Hosting.Model.Application application, Tye.Hosting.Model.Service service) + private async Task LaunchService(Application application, Service service) { var serviceDescription = service.Description; var serviceName = serviceDescription.Name; @@ -60,20 +60,15 @@ namespace Microsoft.Tye.Hosting if (serviceDescription.RunInfo is ProjectRunInfo project) { - path = string.IsNullOrEmpty(project.RunCommand) ? project.TargetAssemblyPath : project.RunCommand; + path = project.RunCommand; workingDirectory = project.ProjectFile.Directory.FullName; args = project.Args == null ? project.RunArguments : project.RunArguments + " " + project.Args; service.Status.ProjectFilePath = project.ProjectFile.FullName; } else if (serviceDescription.RunInfo is ExecutableRunInfo executable) { - var expandedExecutable = Environment.ExpandEnvironmentVariables(executable.Executable); - path = Path.GetExtension(expandedExecutable) == ".dll" ? - Path.GetFullPath(Path.Combine(application.ContextDirectory, expandedExecutable)) : - expandedExecutable; - workingDirectory = executable.WorkingDirectory != null ? - Path.GetFullPath(Path.Combine(application.ContextDirectory, Environment.ExpandEnvironmentVariables(executable.WorkingDirectory))) : - Path.GetDirectoryName(path)!; + path = executable.Executable; + workingDirectory = executable.WorkingDirectory!; args = executable.Args ?? ""; } else @@ -93,6 +88,7 @@ namespace Microsoft.Tye.Hosting service.Status.Args = args; var processInfo = new ProcessInfo(new Task[service.Description.Replicas]); + if (service.Status.ProjectFilePath != null && service.Description.RunInfo is ProjectRunInfo project2 && project2.Build && @@ -278,9 +274,9 @@ namespace Microsoft.Tye.Hosting service.Items[typeof(ProcessInfo)] = processInfo; } - private Task KillRunningProcesses(IDictionary services) + private Task KillRunningProcesses(IDictionary services) { - static async Task KillProcessAsync(Tye.Hosting.Model.Service service) + static async Task KillProcessAsync(Service service) { if (service.Items.TryGetValue(typeof(ProcessInfo), out var stateObj) && stateObj is ProcessInfo state) { diff --git a/src/Microsoft.Tye.Hosting/ProxyService.cs b/src/Microsoft.Tye.Hosting/ProxyService.cs index 86059fb9..a3a610b3 100644 --- a/src/Microsoft.Tye.Hosting/ProxyService.cs +++ b/src/Microsoft.Tye.Hosting/ProxyService.cs @@ -17,6 +17,7 @@ using Microsoft.AspNetCore.Connections.Features; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; +using Microsoft.Tye.Hosting.Model; namespace Microsoft.Tye.Hosting { @@ -30,7 +31,7 @@ namespace Microsoft.Tye.Hosting _logger = logger; } - public async Task StartAsync(Tye.Hosting.Model.Application application) + public async Task StartAsync(Application application) { _host = new HostBuilder() .ConfigureServer(server => @@ -41,7 +42,6 @@ namespace Microsoft.Tye.Hosting { if (service.Description.RunInfo == null) { - // We eventually want to proxy everything, this is temporary continue; } @@ -195,7 +195,7 @@ namespace Microsoft.Tye.Hosting await _host.StartAsync(); } - public async Task StopAsync(Tye.Hosting.Model.Application application) + public async Task StopAsync(Application application) { if (_host != null) { diff --git a/src/Microsoft.Tye.Hosting/TransformProjectsIntoContainers.cs b/src/Microsoft.Tye.Hosting/TransformProjectsIntoContainers.cs index 6cb26ba2..6b1c9847 100644 --- a/src/Microsoft.Tye.Hosting/TransformProjectsIntoContainers.cs +++ b/src/Microsoft.Tye.Hosting/TransformProjectsIntoContainers.cs @@ -2,10 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; using System.Collections.Generic; -using System.IO; -using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Microsoft.Tye.Hosting.Model; @@ -21,7 +18,7 @@ namespace Microsoft.Tye.Hosting _logger = logger; } - public Task StartAsync(Model.Application application) + public Task StartAsync(Application application) { // This transforms a ProjectRunInfo into a container var tasks = new List(); @@ -29,14 +26,14 @@ namespace Microsoft.Tye.Hosting { if (s.Description.RunInfo is ProjectRunInfo project) { - tasks.Add(TransformProjectToContainer(application, s, project)); + tasks.Add(TransformProjectToContainer(s, project)); } } return Task.WhenAll(tasks); } - private async Task TransformProjectToContainer(Model.Application application, Model.Service service, ProjectRunInfo project) + private async Task TransformProjectToContainer(Service service, ProjectRunInfo project) { var serviceDescription = service.Description; var serviceName = serviceDescription.Name; @@ -67,13 +64,13 @@ namespace Microsoft.Tye.Hosting // We transform the project information into the following docker command: // docker run -w /app -v {publishDir}:/app -it {image} dotnet {outputfile}.dll - // We swap the slashes since we're going to run on linux var containerImage = DetermineContainerImage(targetFramework); var outputFileName = project.AssemblyName + ".dll"; var dockerRunInfo = new DockerRunInfo(containerImage, $"dotnet {outputFileName} {project.Args}") { WorkingDirectory = "/app" }; + dockerRunInfo.VolumeMappings[project.PublishOutputPath] = "/app"; // Make volume mapping works when running as a container @@ -92,7 +89,7 @@ namespace Microsoft.Tye.Hosting return "mcr.microsoft.com/dotnet/core/sdk:3.1-buster"; } - public Task StopAsync(Model.Application application) + public Task StopAsync(Application application) { return Task.CompletedTask; } diff --git a/src/Microsoft.Tye.Hosting/TyeDashboardApi.cs b/src/Microsoft.Tye.Hosting/TyeDashboardApi.cs index 7a8e467c..ff4f0763 100644 --- a/src/Microsoft.Tye.Hosting/TyeDashboardApi.cs +++ b/src/Microsoft.Tye.Hosting/TyeDashboardApi.cs @@ -58,7 +58,7 @@ namespace Microsoft.Tye.Hosting private async Task Services(HttpContext context) { - var app = context.RequestServices.GetRequiredService(); + var app = context.RequestServices.GetRequiredService(); context.Response.ContentType = "application/json"; @@ -75,7 +75,7 @@ namespace Microsoft.Tye.Hosting private async Task Service(HttpContext context) { - var app = context.RequestServices.GetRequiredService(); + var app = context.RequestServices.GetRequiredService(); var name = (string)context.Request.RouteValues["name"]; context.Response.ContentType = "application/json"; @@ -258,7 +258,7 @@ namespace Microsoft.Tye.Hosting private async Task Metrics(HttpContext context) { - var app = context.RequestServices.GetRequiredService(); + var app = context.RequestServices.GetRequiredService(); var sb = new StringBuilder(); diff --git a/src/Microsoft.Tye.Hosting/TyeHost.cs b/src/Microsoft.Tye.Hosting/TyeHost.cs index 0af35ac2..c3f4f07d 100644 --- a/src/Microsoft.Tye.Hosting/TyeHost.cs +++ b/src/Microsoft.Tye.Hosting/TyeHost.cs @@ -16,6 +16,7 @@ using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Tye.Hosting.Diagnostics; +using Microsoft.Tye.Hosting.Model; using Serilog; using Serilog.Core; using Serilog.Events; @@ -32,23 +33,23 @@ namespace Microsoft.Tye.Hosting private IHostApplicationLifetime? _lifetime; private AggregateApplicationProcessor? _processor; - private readonly Tye.Hosting.Model.Application _application; + private readonly Application _application; private readonly string[] _args; private readonly string[] _servicesToDebug; - public TyeHost(Tye.Hosting.Model.Application application, string[] args) + public TyeHost(Application application, string[] args) : this(application, args, new string[0]) { } - public TyeHost(Tye.Hosting.Model.Application application, string[] args, string[] servicesToDebug) + public TyeHost(Application application, string[] args, string[] servicesToDebug) { _application = application; _args = args; _servicesToDebug = servicesToDebug; } - public Tye.Hosting.Model.Application Application => _application; + public Application Application => _application; public WebApplication? DashboardWebApplication { get; set; } @@ -118,7 +119,7 @@ namespace Microsoft.Tye.Hosting } private static WebApplication BuildWebApplication( - Tye.Hosting.Model.Application application, + Application application, string[] args, ILogEventSink? sink) { @@ -229,7 +230,7 @@ namespace Microsoft.Tye.Hosting } } - private static bool IsPortInUseByBinding(Model.Application application, int port) + private static bool IsPortInUseByBinding(Application application, int port) { foreach (var service in application.Services) { @@ -245,7 +246,7 @@ namespace Microsoft.Tye.Hosting return false; } - private static AggregateApplicationProcessor CreateApplicationProcessor(string[] args, string[] _servicesToDebug, Microsoft.Extensions.Logging.ILogger logger, IConfiguration configuration) + private static AggregateApplicationProcessor CreateApplicationProcessor(string[] args, string[] servicesToDebug, Microsoft.Extensions.Logging.ILogger logger, IConfiguration configuration) { var diagnosticOptions = DiagnosticOptions.FromConfiguration(configuration); var diagnosticsCollector = new DiagnosticsCollector(logger, diagnosticOptions); @@ -257,9 +258,9 @@ namespace Microsoft.Tye.Hosting { new EventPipeDiagnosticsRunner(logger, diagnosticsCollector), new ProxyService(logger), - new IngressService(logger), + new HttpProxyService(logger), new DockerRunner(logger), - new ProcessRunner(logger, ProcessRunnerOptions.FromArgs(args, _servicesToDebug)), + new ProcessRunner(logger, ProcessRunnerOptions.FromArgs(args, servicesToDebug)), }; // If the docker command is specified then transform the ProjectRunInfo into DockerRunInfo diff --git a/src/tye/ApplicationBuilderExtensions.cs b/src/tye/ApplicationBuilderExtensions.cs index c2359de2..46d9f13b 100644 --- a/src/tye/ApplicationBuilderExtensions.cs +++ b/src/tye/ApplicationBuilderExtensions.cs @@ -10,9 +10,9 @@ namespace Microsoft.Tye.ConfigModel { public static class ApplicationBuilderExtensions { - public static Tye.Hosting.Model.Application ToHostingApplication(this ApplicationBuilder application) + public static Application ToHostingApplication(this ApplicationBuilder application) { - var services = new Dictionary(); + var services = new Dictionary(); foreach (var service in application.Services) { RunInfo? runInfo; @@ -82,7 +82,7 @@ namespace Microsoft.Tye.ConfigModel throw new InvalidOperationException($"Cannot figure out how to run service '{service.Name}'."); } - var description = new Tye.Hosting.Model.ServiceDescription(service.Name, runInfo) + var description = new ServiceDescription(service.Name, runInfo) { Replicas = replicas, }; @@ -90,7 +90,7 @@ namespace Microsoft.Tye.ConfigModel foreach (var binding in service.Bindings) { - description.Bindings.Add(new Tye.Hosting.Model.ServiceBinding() + description.Bindings.Add(new Hosting.Model.ServiceBinding() { ConnectionString = binding.ConnectionString, Host = binding.Host, @@ -102,29 +102,29 @@ namespace Microsoft.Tye.ConfigModel }); } - services.Add(service.Name, new Tye.Hosting.Model.Service(description)); + services.Add(service.Name, new Service(description)); } // Ingress get turned into services for hosting foreach (var ingress in application.Ingress) { - var rules = new List(); + var rules = new List(); foreach (var rule in ingress.Rules) { - rules.Add(new Tye.Hosting.Model.IngressRule(rule.Host, rule.Path, rule.Service!)); + rules.Add(new IngressRule(rule.Host, rule.Path, rule.Service!)); } var runInfo = new IngressRunInfo(rules); - var description = new Tye.Hosting.Model.ServiceDescription(ingress.Name, runInfo) + var description = new ServiceDescription(ingress.Name, runInfo) { Replicas = ingress.Replicas, }; foreach (var binding in ingress.Bindings) { - description.Bindings.Add(new Tye.Hosting.Model.ServiceBinding() + description.Bindings.Add(new Hosting.Model.ServiceBinding() { AutoAssignPort = binding.AutoAssignPort, Name = binding.Name, @@ -133,10 +133,10 @@ namespace Microsoft.Tye.ConfigModel }); } - services.Add(ingress.Name, new Tye.Hosting.Model.Service(description)); + services.Add(ingress.Name, new Service(description)); } - return new Tye.Hosting.Model.Application(application.Source, services); + return new Application(application.Source, services); } } }