Browse Source

Add test for container -> host communication. (#290)

* Add test for container -> host communication.

* Small tweaks
- Modify frontend-backend app to print backend url
- Fix log in docker runner
- Rename test to use docker instead of container

* More clean up
- Don't set container port if the service isn't a container

* Bind to all interfaces on linux only
pull/293/head
David Fowler 6 years ago
committed by GitHub
parent
commit
8ac8f93098
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      samples/frontend-backend/frontend/Startup.cs
  2. 2
      src/Microsoft.Tye.Hosting/DockerRunner.cs
  3. 24
      src/Microsoft.Tye.Hosting/PortAssigner.cs
  4. 7
      src/Microsoft.Tye.Hosting/ProcessRunner.cs
  5. 44
      test/E2ETest/TyeRunTests.cs

9
samples/frontend-backend/frontend/Startup.cs

@ -14,6 +14,7 @@ using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace Frontend
{
@ -37,7 +38,7 @@ namespace Frontend
services.AddHealthChecks();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger<Startup> logger)
{
if (env.IsDevelopment())
{
@ -48,9 +49,13 @@ namespace Frontend
app.UseEndpoints(endpoints =>
{
var uri = Configuration.GetServiceUri("backend");
logger.LogInformation("Backend URL: {BackendUrl}", uri);
var httpClient = new HttpClient()
{
BaseAddress = Configuration.GetServiceUri("backend"),
BaseAddress = uri
};
endpoints.MapGet("/", async context =>

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

@ -214,7 +214,7 @@ namespace Microsoft.Tye.Hosting
var command = $"run -d {workingDirectory} {volumes} {environmentArguments} {portString} --name {replica} --restart=unless-stopped {docker.Image} {docker.Args ?? ""}";
_logger.LogInformation("Running command image {Image} for {Replica}", docker.Image, replica);
_logger.LogInformation("Running image {Image} for {Replica}", docker.Image, replica);
service.Logs.OnNext($"[{replica}]: docker {command}");

24
src/Microsoft.Tye.Hosting/PortAssigner.cs

@ -78,18 +78,22 @@ namespace Microsoft.Tye.Hosting
binding.Name ?? binding.Protocol);
}
var httpBinding = service.Description.Bindings.FirstOrDefault(b => b.Protocol == "http");
var httpsBinding = service.Description.Bindings.FirstOrDefault(b => b.Protocol == "https");
// Default the first http and https port to 80 and 443
if (httpBinding != null)
// Only set the container port if we're running in a container
if (service.Description.RunInfo is DockerRunInfo)
{
httpBinding.ContainerPort ??= 80;
}
var httpBinding = service.Description.Bindings.FirstOrDefault(b => b.Protocol == "http");
var httpsBinding = service.Description.Bindings.FirstOrDefault(b => b.Protocol == "https");
if (httpsBinding != null)
{
httpsBinding.ContainerPort ??= 443;
// Default the first http and https port to 80 and 443
if (httpBinding != null)
{
httpBinding.ContainerPort ??= 80;
}
if (httpsBinding != null)
{
httpsBinding.ContainerPort ??= 443;
}
}
}

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

@ -153,10 +153,15 @@ namespace Microsoft.Tye.Hosting
if (hasPorts)
{
// We need to bind to all interfaces on linux since the container -> host communication won't work
// if we use the IP address to reach out of the host. This works fine on osx and windows
// but doesn't work on linux.
var host = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "*" : "localhost";
// These are the ports that the application should use for binding
// 1. Configure ASP.NET Core to bind to those same ports
environment["ASPNETCORE_URLS"] = string.Join(";", ports.Select(p => $"{p.Protocol ?? "http"}://localhost:{p.Port}"));
environment["ASPNETCORE_URLS"] = string.Join(";", ports.Select(p => $"{p.Protocol ?? "http"}://{host}:{p.Port}"));
// Set the HTTPS port for the redirect middleware
foreach (var p in ports)

44
test/E2ETest/TyeRunTests.cs

@ -177,6 +177,50 @@ namespace E2ETest
});
}
[ConditionalFact]
[SkipIfDockerNotRunning]
public async Task FrontendDockerBackendProject()
{
using var projectDirectory = CopySampleProjectDirectory("frontend-backend");
var projectFile = new FileInfo(Path.Combine(projectDirectory.DirectoryPath, "tye.yaml"));
var outputContext = new OutputContext(_sink, Verbosity.Debug);
var application = await ApplicationFactory.CreateAsync(outputContext, projectFile);
// Transform the backend into a docker image for testing
var project = (ProjectServiceBuilder)application.Services.First(s => s.Name == "frontend");
application.Services.Remove(project);
var outputFileName = project.AssemblyName + ".dll";
var container = new ContainerServiceBuilder(project.Name, $"mcr.microsoft.com/dotnet/core/sdk:{project.TargetFrameworkVersion}");
container.Volumes.Add(new VolumeBuilder(project.PublishDir, name: null, target: "/app"));
container.Args = $"dotnet /app/{outputFileName} {project.Args}";
container.Bindings.AddRange(project.Bindings);
await ProcessUtil.RunAsync("dotnet", $"publish \"{project.ProjectFile.FullName}\" /nologo", outputDataReceived: _sink.WriteLine, errorDataReceived: _sink.WriteLine);
application.Services.Add(container);
var handler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (a, b, c, d) => true,
AllowAutoRedirect = false
};
var client = new HttpClient(new RetryHandler(handler));
await RunHostingApplication(application, Array.Empty<string>(), async (app, uri) =>
{
var frontendUri = await GetServiceUrl(client, uri, "frontend");
var backendUri = await GetServiceUrl(client, uri, "backend");
var backendResponse = await client.GetAsync(backendUri);
var frontendResponse = await client.GetAsync(frontendUri);
Assert.True(backendResponse.IsSuccessStatusCode);
Assert.True(frontendResponse.IsSuccessStatusCode);
});
}
[ConditionalFact]
[SkipIfDockerNotRunning]
public async Task DockerNamedVolumeTest()

Loading…
Cancel
Save