Browse Source

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
pull/209/head
David Fowler 7 years ago
committed by GitHub
parent
commit
6d4910b1f5
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 30
      src/Microsoft.Tye.Core/ApplicationFactory.cs
  2. 36
      src/Microsoft.Tye.Core/Service.cs
  3. 4
      src/Microsoft.Tye.Hosting/AggregateApplicationProcessor.cs
  4. 10
      src/Microsoft.Tye.Hosting/DockerRunner.cs
  5. 4
      src/Microsoft.Tye.Hosting/EventPipeDiagnosticsRunner.cs
  6. 115
      src/Microsoft.Tye.Hosting/HttpProxyService.cs
  7. 4
      src/Microsoft.Tye.Hosting/IApplicationProcessor.cs
  8. 67
      src/Microsoft.Tye.Hosting/Infrastructure/ConnectionRetryHandler.cs
  9. 0
      src/Microsoft.Tye.Hosting/Infrastructure/ProxyExtensions.cs
  10. 61
      src/Microsoft.Tye.Hosting/Infrastructure/ServiceLoggerProvider.cs
  11. 15
      src/Microsoft.Tye.Hosting/Model/PortMapping.cs
  12. 14
      src/Microsoft.Tye.Hosting/Model/ServiceState.cs
  13. 26
      src/Microsoft.Tye.Hosting/ProcessRunner.cs
  14. 6
      src/Microsoft.Tye.Hosting/ProxyService.cs
  15. 13
      src/Microsoft.Tye.Hosting/TransformProjectsIntoContainers.cs
  16. 6
      src/Microsoft.Tye.Hosting/TyeDashboardApi.cs
  17. 19
      src/Microsoft.Tye.Hosting/TyeHost.cs
  18. 22
      src/tye/ApplicationBuilderExtensions.cs

30
src/Microsoft.Tye.Core/ApplicationFactory.cs

@ -55,17 +55,33 @@ namespace Microsoft.Tye
} }
else if (!string.IsNullOrEmpty(configService.Image)) else if (!string.IsNullOrEmpty(configService.Image))
{ {
var container = new ContainerServiceBuilder(configService.Name, configService.Image); var container = new ContainerServiceBuilder(configService.Name, configService.Image)
container.Args = configService.Args; {
container.Replicas = configService.Replicas ?? 1; Args = configService.Args,
Replicas = configService.Replicas ?? 1
};
service = container; service = container;
} }
else if (!string.IsNullOrEmpty(configService.Executable)) else if (!string.IsNullOrEmpty(configService.Executable))
{ {
var executable = new ExecutableServiceBuilder(configService.Name, configService.Executable); var expandedExecutable = Environment.ExpandEnvironmentVariables(configService.Executable);
executable.Args = configService.Args; var workingDirectory = "";
executable.WorkingDirectory = configService.WorkingDirectory;
executable.Replicas = configService.Replicas ?? 1; // 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; service = executable;
} }
else if (configService.External) else if (configService.External)

36
src/Microsoft.Tye.Core/Service.cs

@ -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<string, object> Environment { get; set; } = new Dictionary<string, object>();
// Represents bindings *published* by this service
// See GeneratedAssets for bindings consumed by the service
public List<ServiceBinding> Bindings { get; } = new List<ServiceBinding>();
public int Replicas { get; set; }
}
}

4
src/Microsoft.Tye.Hosting/AggregateApplicationProcessor.cs

@ -18,7 +18,7 @@ namespace Microsoft.Tye.Hosting
_applicationProcessors = applicationProcessors; _applicationProcessors = applicationProcessors;
} }
public async Task StartAsync(Tye.Hosting.Model.Application application) public async Task StartAsync(Application application)
{ {
foreach (var processor in _applicationProcessors) 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 // Shutdown in the opposite order
foreach (var processor in _applicationProcessors.Reverse()) foreach (var processor in _applicationProcessors.Reverse())

10
src/Microsoft.Tye.Hosting/DockerRunner.cs

@ -22,7 +22,7 @@ namespace Microsoft.Tye.Hosting
_logger = logger; _logger = logger;
} }
public Task StartAsync(Tye.Hosting.Model.Application application) public Task StartAsync(Application application)
{ {
var tasks = new Task[application.Services.Count]; var tasks = new Task[application.Services.Count];
var index = 0; var index = 0;
@ -34,7 +34,7 @@ namespace Microsoft.Tye.Hosting
return Task.WhenAll(tasks); return Task.WhenAll(tasks);
} }
public Task StopAsync(Tye.Hosting.Model.Application application) public Task StopAsync(Application application)
{ {
var services = application.Services; var services = application.Services;
@ -49,7 +49,7 @@ namespace Microsoft.Tye.Hosting
return Task.WhenAll(tasks); 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) if (!await DockerDetector.Instance.IsDockerInstalled.Value)
{ {
@ -260,7 +260,7 @@ namespace Microsoft.Tye.Hosting
service.Items[typeof(DockerInformation)] = dockerInfo; 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) 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) if (service.Items.TryGetValue(typeof(DockerInformation), out var value) && value is DockerInformation di)
{ {

4
src/Microsoft.Tye.Hosting/EventPipeDiagnosticsRunner.cs

@ -23,7 +23,7 @@ namespace Microsoft.Tye.Hosting
_diagnosticsCollector = diagnosticsCollector; _diagnosticsCollector = diagnosticsCollector;
} }
public Task StartAsync(Tye.Hosting.Model.Application application) public Task StartAsync(Application application)
{ {
foreach (var service in application.Services.Values) foreach (var service in application.Services.Values)
{ {
@ -38,7 +38,7 @@ namespace Microsoft.Tye.Hosting
return Task.CompletedTask; return Task.CompletedTask;
} }
public Task StopAsync(Tye.Hosting.Model.Application application) public Task StopAsync(Application application)
{ {
foreach (var service in application.Services.Values) foreach (var service in application.Services.Values)
{ {

115
src/Microsoft.Tye.Hosting/IngressService.cs → src/Microsoft.Tye.Hosting/HttpProxyService.cs

@ -6,9 +6,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Net.Sockets;
using System.Reactive.Subjects;
using System.Runtime.ExceptionServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
@ -23,17 +20,17 @@ using Microsoft.Tye.Hosting.Model;
namespace Microsoft.Tye.Hosting namespace Microsoft.Tye.Hosting
{ {
public class IngressService : IApplicationProcessor public partial class HttpProxyService : IApplicationProcessor
{ {
private List<WebApplication> _webApplications = new List<WebApplication>(); private List<WebApplication> _webApplications = new List<WebApplication>();
private readonly ILogger _logger; private readonly ILogger _logger;
public IngressService(ILogger logger) public HttpProxyService(ILogger logger)
{ {
_logger = logger; _logger = logger;
} }
public async Task StartAsync(Model.Application application) public async Task StartAsync(Application application)
{ {
var invoker = new HttpMessageInvoker(new ConnectionRetryHandler(new SocketsHttpHandler 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) 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<HttpResponseMessage> 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<string> _logs;
public ServiceLoggerProvider(Subject<string> 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<string> _logs;
public ServiceLogger(string categoryName, Subject<string> logs)
{
_categoryName = categoryName;
_logs = logs;
}
public IDisposable? BeginScope<TState>(TState state)
{
return null;
}
public bool IsEnabled(LogLevel logLevel)
{
return true;
}
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
_logs.OnNext($"[{logLevel}]: {formatter(state, exception)}");
if (exception != null)
{
_logs.OnNext(exception.ToString());
}
}
}
}
} }
} }

4
src/Microsoft.Tye.Hosting/IApplicationProcessor.cs

@ -9,8 +9,8 @@ namespace Microsoft.Tye.Hosting
{ {
public interface IApplicationProcessor 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);
} }
} }

67
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<HttpResponseMessage> 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();
}
}
}

0
src/Microsoft.Tye.Hosting/ProxyExtensions.cs → src/Microsoft.Tye.Hosting/Infrastructure/ProxyExtensions.cs

61
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<string> _logs;
public ServiceLoggerProvider(Subject<string> 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<string> _logs;
public ServiceLogger(string categoryName, Subject<string> logs)
{
_categoryName = categoryName;
_logs = logs;
}
public IDisposable? BeginScope<TState>(TState state)
{
return null;
}
public bool IsEnabled(LogLevel logLevel)
{
return true;
}
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
_logs.OnNext($"[{logLevel}]: {formatter(state, exception)}");
if (exception != null)
{
_logs.OnNext(exception.ToString());
}
}
}
}
}

15
src/Microsoft.Tye.Hosting/Model/PortMapping.cs

@ -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<int> InternalPorts { get; set; } = new List<int>();
}
}

14
src/Microsoft.Tye.Hosting/Model/ServiceState.cs

@ -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
}
}

26
src/Microsoft.Tye.Hosting/ProcessRunner.cs

@ -4,14 +4,14 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Tye.Hosting.Model;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Diagnostics; using Microsoft.Tye.Hosting.Model;
namespace Microsoft.Tye.Hosting namespace Microsoft.Tye.Hosting
{ {
@ -26,7 +26,7 @@ namespace Microsoft.Tye.Hosting
_options = options; _options = options;
} }
public Task StartAsync(Tye.Hosting.Model.Application application) public Task StartAsync(Application application)
{ {
var tasks = new Task[application.Services.Count]; var tasks = new Task[application.Services.Count];
var index = 0; var index = 0;
@ -44,12 +44,12 @@ namespace Microsoft.Tye.Hosting
return Task.WhenAll(tasks); return Task.WhenAll(tasks);
} }
public Task StopAsync(Tye.Hosting.Model.Application application) public Task StopAsync(Application application)
{ {
return KillRunningProcesses(application.Services); 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 serviceDescription = service.Description;
var serviceName = serviceDescription.Name; var serviceName = serviceDescription.Name;
@ -60,20 +60,15 @@ namespace Microsoft.Tye.Hosting
if (serviceDescription.RunInfo is ProjectRunInfo project) if (serviceDescription.RunInfo is ProjectRunInfo project)
{ {
path = string.IsNullOrEmpty(project.RunCommand) ? project.TargetAssemblyPath : project.RunCommand; path = project.RunCommand;
workingDirectory = project.ProjectFile.Directory.FullName; workingDirectory = project.ProjectFile.Directory.FullName;
args = project.Args == null ? project.RunArguments : project.RunArguments + " " + project.Args; args = project.Args == null ? project.RunArguments : project.RunArguments + " " + project.Args;
service.Status.ProjectFilePath = project.ProjectFile.FullName; service.Status.ProjectFilePath = project.ProjectFile.FullName;
} }
else if (serviceDescription.RunInfo is ExecutableRunInfo executable) else if (serviceDescription.RunInfo is ExecutableRunInfo executable)
{ {
var expandedExecutable = Environment.ExpandEnvironmentVariables(executable.Executable); path = executable.Executable;
path = Path.GetExtension(expandedExecutable) == ".dll" ? workingDirectory = executable.WorkingDirectory!;
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)!;
args = executable.Args ?? ""; args = executable.Args ?? "";
} }
else else
@ -93,6 +88,7 @@ namespace Microsoft.Tye.Hosting
service.Status.Args = args; service.Status.Args = args;
var processInfo = new ProcessInfo(new Task[service.Description.Replicas]); var processInfo = new ProcessInfo(new Task[service.Description.Replicas]);
if (service.Status.ProjectFilePath != null && if (service.Status.ProjectFilePath != null &&
service.Description.RunInfo is ProjectRunInfo project2 && service.Description.RunInfo is ProjectRunInfo project2 &&
project2.Build && project2.Build &&
@ -278,9 +274,9 @@ namespace Microsoft.Tye.Hosting
service.Items[typeof(ProcessInfo)] = processInfo; service.Items[typeof(ProcessInfo)] = processInfo;
} }
private Task KillRunningProcesses(IDictionary<string, Tye.Hosting.Model.Service> services) private Task KillRunningProcesses(IDictionary<string, Service> 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) if (service.Items.TryGetValue(typeof(ProcessInfo), out var stateObj) && stateObj is ProcessInfo state)
{ {

6
src/Microsoft.Tye.Hosting/ProxyService.cs

@ -17,6 +17,7 @@ using Microsoft.AspNetCore.Connections.Features;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Tye.Hosting.Model;
namespace Microsoft.Tye.Hosting namespace Microsoft.Tye.Hosting
{ {
@ -30,7 +31,7 @@ namespace Microsoft.Tye.Hosting
_logger = logger; _logger = logger;
} }
public async Task StartAsync(Tye.Hosting.Model.Application application) public async Task StartAsync(Application application)
{ {
_host = new HostBuilder() _host = new HostBuilder()
.ConfigureServer(server => .ConfigureServer(server =>
@ -41,7 +42,6 @@ namespace Microsoft.Tye.Hosting
{ {
if (service.Description.RunInfo == null) if (service.Description.RunInfo == null)
{ {
// We eventually want to proxy everything, this is temporary
continue; continue;
} }
@ -195,7 +195,7 @@ namespace Microsoft.Tye.Hosting
await _host.StartAsync(); await _host.StartAsync();
} }
public async Task StopAsync(Tye.Hosting.Model.Application application) public async Task StopAsync(Application application)
{ {
if (_host != null) if (_host != null)
{ {

13
src/Microsoft.Tye.Hosting/TransformProjectsIntoContainers.cs

@ -2,10 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license. // The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Tye.Hosting.Model; using Microsoft.Tye.Hosting.Model;
@ -21,7 +18,7 @@ namespace Microsoft.Tye.Hosting
_logger = logger; _logger = logger;
} }
public Task StartAsync(Model.Application application) public Task StartAsync(Application application)
{ {
// This transforms a ProjectRunInfo into a container // This transforms a ProjectRunInfo into a container
var tasks = new List<Task>(); var tasks = new List<Task>();
@ -29,14 +26,14 @@ namespace Microsoft.Tye.Hosting
{ {
if (s.Description.RunInfo is ProjectRunInfo project) if (s.Description.RunInfo is ProjectRunInfo project)
{ {
tasks.Add(TransformProjectToContainer(application, s, project)); tasks.Add(TransformProjectToContainer(s, project));
} }
} }
return Task.WhenAll(tasks); 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 serviceDescription = service.Description;
var serviceName = serviceDescription.Name; var serviceName = serviceDescription.Name;
@ -67,13 +64,13 @@ namespace Microsoft.Tye.Hosting
// We transform the project information into the following docker command: // We transform the project information into the following docker command:
// docker run -w /app -v {publishDir}:/app -it {image} dotnet {outputfile}.dll // 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 containerImage = DetermineContainerImage(targetFramework);
var outputFileName = project.AssemblyName + ".dll"; var outputFileName = project.AssemblyName + ".dll";
var dockerRunInfo = new DockerRunInfo(containerImage, $"dotnet {outputFileName} {project.Args}") var dockerRunInfo = new DockerRunInfo(containerImage, $"dotnet {outputFileName} {project.Args}")
{ {
WorkingDirectory = "/app" WorkingDirectory = "/app"
}; };
dockerRunInfo.VolumeMappings[project.PublishOutputPath] = "/app"; dockerRunInfo.VolumeMappings[project.PublishOutputPath] = "/app";
// Make volume mapping works when running as a container // 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"; return "mcr.microsoft.com/dotnet/core/sdk:3.1-buster";
} }
public Task StopAsync(Model.Application application) public Task StopAsync(Application application)
{ {
return Task.CompletedTask; return Task.CompletedTask;
} }

6
src/Microsoft.Tye.Hosting/TyeDashboardApi.cs

@ -58,7 +58,7 @@ namespace Microsoft.Tye.Hosting
private async Task Services(HttpContext context) private async Task Services(HttpContext context)
{ {
var app = context.RequestServices.GetRequiredService<Tye.Hosting.Model.Application>(); var app = context.RequestServices.GetRequiredService<Application>();
context.Response.ContentType = "application/json"; context.Response.ContentType = "application/json";
@ -75,7 +75,7 @@ namespace Microsoft.Tye.Hosting
private async Task Service(HttpContext context) private async Task Service(HttpContext context)
{ {
var app = context.RequestServices.GetRequiredService<Tye.Hosting.Model.Application>(); var app = context.RequestServices.GetRequiredService<Application>();
var name = (string)context.Request.RouteValues["name"]; var name = (string)context.Request.RouteValues["name"];
context.Response.ContentType = "application/json"; context.Response.ContentType = "application/json";
@ -258,7 +258,7 @@ namespace Microsoft.Tye.Hosting
private async Task Metrics(HttpContext context) private async Task Metrics(HttpContext context)
{ {
var app = context.RequestServices.GetRequiredService<Tye.Hosting.Model.Application>(); var app = context.RequestServices.GetRequiredService<Application>();
var sb = new StringBuilder(); var sb = new StringBuilder();

19
src/Microsoft.Tye.Hosting/TyeHost.cs

@ -16,6 +16,7 @@ using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Tye.Hosting.Diagnostics; using Microsoft.Tye.Hosting.Diagnostics;
using Microsoft.Tye.Hosting.Model;
using Serilog; using Serilog;
using Serilog.Core; using Serilog.Core;
using Serilog.Events; using Serilog.Events;
@ -32,23 +33,23 @@ namespace Microsoft.Tye.Hosting
private IHostApplicationLifetime? _lifetime; private IHostApplicationLifetime? _lifetime;
private AggregateApplicationProcessor? _processor; private AggregateApplicationProcessor? _processor;
private readonly Tye.Hosting.Model.Application _application; private readonly Application _application;
private readonly string[] _args; private readonly string[] _args;
private readonly string[] _servicesToDebug; 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]) : 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; _application = application;
_args = args; _args = args;
_servicesToDebug = servicesToDebug; _servicesToDebug = servicesToDebug;
} }
public Tye.Hosting.Model.Application Application => _application; public Application Application => _application;
public WebApplication? DashboardWebApplication { get; set; } public WebApplication? DashboardWebApplication { get; set; }
@ -118,7 +119,7 @@ namespace Microsoft.Tye.Hosting
} }
private static WebApplication BuildWebApplication( private static WebApplication BuildWebApplication(
Tye.Hosting.Model.Application application, Application application,
string[] args, string[] args,
ILogEventSink? sink) 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) foreach (var service in application.Services)
{ {
@ -245,7 +246,7 @@ namespace Microsoft.Tye.Hosting
return false; 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 diagnosticOptions = DiagnosticOptions.FromConfiguration(configuration);
var diagnosticsCollector = new DiagnosticsCollector(logger, diagnosticOptions); var diagnosticsCollector = new DiagnosticsCollector(logger, diagnosticOptions);
@ -257,9 +258,9 @@ namespace Microsoft.Tye.Hosting
{ {
new EventPipeDiagnosticsRunner(logger, diagnosticsCollector), new EventPipeDiagnosticsRunner(logger, diagnosticsCollector),
new ProxyService(logger), new ProxyService(logger),
new IngressService(logger), new HttpProxyService(logger),
new DockerRunner(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 // If the docker command is specified then transform the ProjectRunInfo into DockerRunInfo

22
src/tye/ApplicationBuilderExtensions.cs

@ -10,9 +10,9 @@ namespace Microsoft.Tye.ConfigModel
{ {
public static class ApplicationBuilderExtensions 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<string, Tye.Hosting.Model.Service>(); var services = new Dictionary<string, Service>();
foreach (var service in application.Services) foreach (var service in application.Services)
{ {
RunInfo? runInfo; RunInfo? runInfo;
@ -82,7 +82,7 @@ namespace Microsoft.Tye.ConfigModel
throw new InvalidOperationException($"Cannot figure out how to run service '{service.Name}'."); 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, Replicas = replicas,
}; };
@ -90,7 +90,7 @@ namespace Microsoft.Tye.ConfigModel
foreach (var binding in service.Bindings) foreach (var binding in service.Bindings)
{ {
description.Bindings.Add(new Tye.Hosting.Model.ServiceBinding() description.Bindings.Add(new Hosting.Model.ServiceBinding()
{ {
ConnectionString = binding.ConnectionString, ConnectionString = binding.ConnectionString,
Host = binding.Host, 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 // Ingress get turned into services for hosting
foreach (var ingress in application.Ingress) foreach (var ingress in application.Ingress)
{ {
var rules = new List<Tye.Hosting.Model.IngressRule>(); var rules = new List<IngressRule>();
foreach (var rule in ingress.Rules) 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 runInfo = new IngressRunInfo(rules);
var description = new Tye.Hosting.Model.ServiceDescription(ingress.Name, runInfo) var description = new ServiceDescription(ingress.Name, runInfo)
{ {
Replicas = ingress.Replicas, Replicas = ingress.Replicas,
}; };
foreach (var binding in ingress.Bindings) foreach (var binding in ingress.Bindings)
{ {
description.Bindings.Add(new Tye.Hosting.Model.ServiceBinding() description.Bindings.Add(new Hosting.Model.ServiceBinding()
{ {
AutoAssignPort = binding.AutoAssignPort, AutoAssignPort = binding.AutoAssignPort,
Name = binding.Name, 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);
} }
} }
} }

Loading…
Cancel
Save