This commit is contained in:
David Fowler 2021-03-08 12:29:13 -08:00
Родитель 013868d87e
Коммит eec0a71371
6 изменённых файлов: 97 добавлений и 93 удалений

Просмотреть файл

@ -17,6 +17,7 @@ using Microsoft.AspNetCore.Proxy;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Routing.Matching;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Tye.Hosting.Model;
@ -24,7 +25,7 @@ namespace Microsoft.Tye.Hosting
{
public partial class HttpProxyService : IApplicationProcessor
{
private List<WebApplication> _webApplications = new List<WebApplication>();
private List<IHost> _webApplications = new List<IHost>();
private readonly ILogger _logger;
private ConcurrentDictionary<int, bool> _readyPorts;
@ -50,11 +51,16 @@ namespace Microsoft.Tye.Hosting
if (service.Description.RunInfo is IngressRunInfo runInfo)
{
var host = Host.CreateDefaultBuilder()
.ConfigureWebHostDefaults(builder =>
{
builder.Configure(app =>
{
});
});
var builder = new WebApplicationBuilder();
builder.Services.AddSingleton<MatcherPolicy, IngressHostMatcherPolicy>();
builder.Logging.AddProvider(new ServiceLoggerProvider(service.Logs));
var addresses = new List<string>();

Просмотреть файл

@ -20,7 +20,6 @@
<ItemGroup>
<PackageReference Include="Bedrock.Framework" Version="0.1.38-alpha.gd25d5b37ad" />
<PackageReference Include="FeatherHttp" Version="0.1.42-alpha.gf06a8747e7" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="3.1.0" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="3.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />

Просмотреть файл

@ -5,13 +5,15 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting;
@ -32,6 +34,7 @@ namespace Microsoft.Tye.Hosting
private Microsoft.Extensions.Logging.ILogger? _logger;
private IHostApplicationLifetime? _lifetime;
private ICollection<string>? _addresses;
private AggregateApplicationProcessor? _processor;
private readonly Application _application;
@ -46,7 +49,11 @@ namespace Microsoft.Tye.Hosting
public Application Application => _application;
public WebApplication? DashboardWebApplication { get; set; }
public IHost? DashboardWebApplication { get; set; }
public ICollection<string>? Addresses => _addresses;
public Extensions.Logging.ILogger? Logger => _logger;
// An additional sink that output will be piped to. Useful for testing.
public ILogEventSink? Sink { get; set; }
@ -71,25 +78,24 @@ namespace Microsoft.Tye.Hosting
}
}
public async Task<WebApplication> StartAsync()
public async Task<IHost> StartAsync()
{
var app = BuildWebApplication(_application, _options, Sink);
DashboardWebApplication = app;
_logger = app.Logger;
_lifetime = app.ApplicationLifetime;
_addresses = DashboardWebApplication.Services.GetRequiredService<IServer>().Features.Get<IServerAddressesFeature>().Addresses;
_logger = DashboardWebApplication.Services.GetRequiredService<ILogger<TyeHost>>();
_lifetime = app.Services.GetRequiredService<IHostApplicationLifetime>();
_logger.LogInformation("Executing application from {Source}", _application.Source);
ConfigureApplication(app);
_replicaRegistry = new ReplicaRegistry(_application.ContextDirectory, _logger);
_processor = CreateApplicationProcessor(_replicaRegistry, _options, _logger);
await app.StartAsync();
_logger.LogInformation("Dashboard running on {Address}", app.Addresses.First());
_logger.LogInformation("Dashboard running on {Address}", _addresses.First());
try
{
@ -103,88 +109,79 @@ namespace Microsoft.Tye.Hosting
if (_options.Dashboard)
{
OpenDashboard(app.Addresses.First());
OpenDashboard(_addresses.First());
}
return app;
}
private static WebApplication BuildWebApplication(Application application, HostOptions options, ILogEventSink? sink)
private IHost BuildWebApplication(Application application, HostOptions options, ILogEventSink? sink)
{
var args = new List<string>();
if (options.Port.HasValue)
{
args.Add("--port");
args.Add(options.Port.Value.ToString(CultureInfo.InvariantCulture));
}
var builder = WebApplication.CreateBuilder(args.ToArray());
// Logging for this application
builder.Host.UseSerilog((context, configuration) =>
{
var logLevel = options.LogVerbosity switch
return Host.CreateDefaultBuilder()
.UseSerilog((context, configuration) =>
{
Verbosity.Quiet => LogEventLevel.Warning,
Verbosity.Info => LogEventLevel.Information,
Verbosity.Debug => LogEventLevel.Verbose,
_ => default
};
var logLevel = options.LogVerbosity switch
{
Verbosity.Quiet => LogEventLevel.Warning,
Verbosity.Info => LogEventLevel.Information,
Verbosity.Debug => LogEventLevel.Verbose,
_ => default
};
configuration
.MinimumLevel.Is(logLevel)
.Filter.ByExcluding(Matching.FromSource("Microsoft.AspNetCore"))
.Filter.ByExcluding(Matching.FromSource("Microsoft.Extensions"))
.Filter.ByExcluding(Matching.FromSource("Microsoft.Hosting"))
.Enrich
.FromLogContext()
.WriteTo
.Console();
configuration
.MinimumLevel.Is(logLevel)
.Filter.ByExcluding(Matching.FromSource("Microsoft.AspNetCore"))
.Filter.ByExcluding(Matching.FromSource("Microsoft.Extensions"))
.Filter.ByExcluding(Matching.FromSource("Microsoft.Hosting"))
.Enrich
.FromLogContext()
.WriteTo
.Console();
if (sink is object)
if (sink is object)
{
configuration.WriteTo.Sink(sink, logLevel);
}
})
.ConfigureServices(services =>
{
configuration.WriteTo.Sink(sink, logLevel);
}
});
services.AddRazorPages(o => o.RootDirectory = "/Dashboard/Pages");
services.AddServerSideBlazor();
services.AddOptions<StaticFileOptions>()
.PostConfigure(o =>
{
var fileProvider = new ManifestEmbeddedFileProvider(typeof(TyeHost).Assembly, "wwwroot");
builder.Services.AddRazorPages(o => o.RootDirectory = "/Dashboard/Pages");
builder.Services.AddServerSideBlazor();
builder.Services.AddOptions<StaticFileOptions>()
.PostConfigure(o =>
// Make sure we don't remove the existing file providers (blazor needs this)
o.FileProvider = new CompositeFileProvider(o.FileProvider, fileProvider);
});
services.AddCors(
options =>
{
options.AddPolicy(
"default",
policy =>
{
policy
.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
services.AddSingleton(application);
})
.ConfigureWebHostDefaults(builder =>
{
var fileProvider = new ManifestEmbeddedFileProvider(typeof(TyeHost).Assembly, "wwwroot");
var port = ComputePort(options.Port);
// Make sure we don't remove the existing file providers (blazor needs this)
o.FileProvider = new CompositeFileProvider(o.FileProvider, fileProvider);
});
builder.Services.AddCors(
options =>
{
options.AddPolicy(
"default",
policy =>
{
policy
.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
builder.Services.AddSingleton(application);
var app = builder.Build();
return app;
builder.Configure(ConfigureApplication)
.UseUrls($"http://127.0.0.1:{port}");
})
.Build();
}
private void ConfigureApplication(WebApplication app)
private void ConfigureApplication(IApplicationBuilder app)
{
var port = ComputePort(app);
app.Listen($"http://127.0.0.1:{port}");
app.UseDeveloperExceptionPage();
app.UseCors("default");
@ -195,13 +192,16 @@ namespace Microsoft.Tye.Hosting
var api = new TyeDashboardApi();
api.MapRoutes(app);
app.UseEndpoints(endpoints =>
{
api.MapRoutes(endpoints);
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
private int ComputePort(WebApplication app)
private int ComputePort(int? port)
{
// logic for computing the port:
// - we allow the user to specify the port... if they don't
@ -210,17 +210,16 @@ namespace Microsoft.Tye.Hosting
// - we don't want to cause conflicts with any of the users known bindings
// or something else running.
var port = app.Configuration["port"];
if (!string.IsNullOrEmpty(port))
if (port.HasValue)
{
// Port was passed in at the command-line, use it!
return int.Parse(port, NumberStyles.Number, CultureInfo.InvariantCulture);
return port.Value;
}
if (IsPortInUseByBinding(_application, DefaultPort))
{
// Port has been reserved for the app.
app.Logger.LogInformation("Default dashboard port {DefaultPort} has been reserved by the application, choosing random port.", DefaultPort);
// app.Logger.LogInformation("Default dashboard port {DefaultPort} has been reserved by the application, choosing random port.", DefaultPort);
return AutodetectPort;
}
@ -229,7 +228,7 @@ namespace Microsoft.Tye.Hosting
return DefaultPort;
}
// Port is in use by something already running.
app.Logger.LogInformation("Default dashboard port {DefaultPort} is in use, choosing random port.", DefaultPort);
// app.Logger.LogInformation("Default dashboard port {DefaultPort} is in use, choosing random port.", DefaultPort);
return AutodetectPort;
}

Просмотреть файл

@ -112,7 +112,7 @@ namespace E2ETest
{
await StartHostAndWaitForReplicasToStart(host);
var uri = new Uri(host.DashboardWebApplication!.Addresses.First());
var uri = new Uri(host.Addresses!.First());
await execute(host, uri!);
}
@ -120,7 +120,7 @@ namespace E2ETest
{
if (host.DashboardWebApplication != null)
{
var uri = new Uri(host.DashboardWebApplication!.Addresses.First());
var uri = new Uri(host.Addresses!.First());
using var client = new HttpClient();

Просмотреть файл

@ -1105,7 +1105,7 @@ services:
{
await StartHostAndWaitForReplicasToStart(host);
var uri = new Uri(host.DashboardWebApplication!.Addresses.First());
var uri = new Uri(host.Addresses!.First());
await execute(host.Application, uri!);
}
@ -1113,7 +1113,7 @@ services:
{
if (host.DashboardWebApplication != null)
{
var uri = new Uri(host.DashboardWebApplication!.Addresses.First());
var uri = new Uri(host.Addresses!.First());
using var client = new HttpClient();

Просмотреть файл

@ -246,7 +246,7 @@ namespace Test.Infrastructure
{
static async Task Purge(TyeHost host)
{
var logger = host.DashboardWebApplication!.Logger;
var logger = host.Logger;
var replicaRegistry = new ReplicaRegistry(host.Application.ContextDirectory, logger);
var processRunner = new ProcessRunner(logger, replicaRegistry, new ProcessRunnerOptions());
var dockerRunner = new DockerRunner(logger, replicaRegistry);