| File: ContainerTunnelTests.cs | Web Access |
| Project: src\tests\Aspire.Hosting.Tests\Aspire.Hosting.Tests.csproj (Aspire.Hosting.Tests) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Aspire.Hosting.Testing; using Aspire.Hosting.Tests.Utils; using Aspire.Hosting.Utils; using Aspire.Hosting.Yarp.Transforms; using Aspire.TestUtilities; using Microsoft.AspNetCore.InternalTesting; namespace Aspire.Hosting.Tests; [Trait("Partition", "2")] public class ContainerTunnelTests(ITestOutputHelper testOutputHelper) { [Fact] [RequiresFeature(TestFeature.ContainerRuntime | TestFeature.ContainerImageBuild)] public async Task ContainerTunnelWorksWithYarp() { const string testName = "container-tunnel-works-with-yarp"; using var builder = TestDistributedApplicationBuilder.Create(testOutputHelper); builder.Configuration[KnownConfigNames.EnableContainerTunnel] = "true"; var servicea = builder.AddProject<Projects.ServiceA>($"{testName}-servicea"); var yarp = builder.AddYarp($"{testName}-yarp").WithConfiguration(conf => { conf.AddRoute("/servicea/{**catch-all}", servicea).WithTransformPathRemovePrefix("/servicea"); }); using var app = builder.Build(); // Use extra long timeout because if this is first time the tunnel is being used, // getting the base images and building the tunnel (client) proxy image may take a while. await app.StartAsync().DefaultTimeout(TestConstants.ExtraLongTimeoutDuration); await app.WaitForTextAsync("Application started.").DefaultTimeout(TestConstants.DefaultOrchestratorTestLongTimeout); using var clientA = app.CreateHttpClient(yarp.Resource.Name, "http"); var response = await clientA.GetAsync("/servicea/").DefaultTimeout(TestConstants.DefaultOrchestratorTestTimeout); Assert.True(response.IsSuccessStatusCode); var body = await response.Content.ReadAsStringAsync().DefaultTimeout(TestConstants.DefaultOrchestratorTestTimeout); Assert.Equal("Hello World!", body); await app.StopAsync().DefaultTimeout(TestConstants.DefaultOrchestratorTestLongTimeout); } [Fact] [RequiresFeature(TestFeature.ContainerRuntime | TestFeature.ContainerImageBuild)] public async Task ProxylessEndpointWorksWithContainerTunnel() { var port = await Helpers.Network.GetAvailablePortAsync(); const string testName = "proxyless-endpoint-container-tunnel"; using var builder = TestDistributedApplicationBuilder.Create(testOutputHelper); builder.Configuration[KnownConfigNames.EnableContainerTunnel] = "true"; var servicea = builder.AddProject<Projects.ServiceA>($"{testName}-servicea") .WithEndpoint("http", e => { e.Port = port; e.TargetPort = port; e.IsProxied = false; }); var yarp = builder.AddYarp($"{testName}-yarp").WithConfiguration(conf => { conf.AddRoute("/servicea/{**catch-all}", servicea).WithTransformPathRemovePrefix("/servicea"); }); await using var app = builder.Build(); // Use extra long timeout because if this is first time the tunnel is being used, // getting the base images and building the tunnel (client) proxy image may take a while. await app.StartAsync().DefaultTimeout(TestConstants.ExtraLongTimeoutDuration); await app.WaitForTextAsync("Application started.").DefaultTimeout(TestConstants.DefaultOrchestratorTestLongTimeout); using var clientA = app.CreateHttpClient(yarp.Resource.Name, "http"); var response = await clientA.GetAsync("/servicea/").DefaultTimeout(TestConstants.DefaultOrchestratorTestTimeout); Assert.True(response.IsSuccessStatusCode); var body = await response.Content.ReadAsStringAsync().DefaultTimeout(TestConstants.DefaultOrchestratorTestTimeout); Assert.Equal("Hello World!", body); await app.StopAsync().DefaultTimeout(TestConstants.DefaultOrchestratorTestLongTimeout); } [Fact] [RequiresFeature(TestFeature.ContainerRuntime | TestFeature.ContainerImageBuild)] public async Task WaitingContainersCanUseTunnel() { const string testName = "waiting-containers-can-use-tunnel"; using var builder = TestDistributedApplicationBuilder.Create(testOutputHelper); builder.Configuration[KnownConfigNames.EnableContainerTunnel] = "true"; var servicea = builder.AddProject<Projects.ServiceA>($"{testName}-servicea", launchProfileName: null) .WithHttpEndpoint(); var container = builder.AddContainer($"{testName}-container", "mcr.microsoft.com/cbl-mariner/base/nginx", "1.22") .WithEnvironment("SERVICEA_URL", servicea.GetEndpoint("http")); var waitingContainer = builder.AddContainer($"{testName}-waiting", "mcr.microsoft.com/cbl-mariner/base/nginx", "1.22") .WaitFor(container); var waitingContainerConsumingEndpoint = builder.AddContainer($"{testName}-waiting-consuming", "mcr.microsoft.com/cbl-mariner/base/nginx", "1.22") .WithEnvironment("SERVICEA_URL", servicea.GetEndpoint("http")) .WaitFor(container); await using var app = builder.Build(); // Use extra long timeout because if this is first time the tunnel is being used, // getting the base images and building the tunnel (client) proxy image may take a while. await app.StartAsync().DefaultTimeout(TestConstants.ExtraLongTimeoutDuration); foreach (var c in new[] { container, waitingContainer, waitingContainerConsumingEndpoint }) { await app.ResourceNotifications.WaitForResourceAsync(c.Resource.Name, KnownResourceStates.Running) .DefaultTimeout(TestConstants.DefaultOrchestratorTestLongTimeout); } await app.StopAsync().DefaultTimeout(TestConstants.DefaultOrchestratorTestLongTimeout); } [Fact] [RequiresFeature(TestFeature.ContainerRuntime | TestFeature.ContainerImageBuild)] public async Task HostResourceCanWaitForTunnelDependentContainers() { const string testName = "host-resource-waits-for-tunnel-container"; using var builder = TestDistributedApplicationBuilder.Create(testOutputHelper); builder.Configuration[KnownConfigNames.EnableContainerTunnel] = "true"; var upstreamService = builder.AddProject<Projects.ServiceA>($"{testName}-upstream", launchProfileName: null) .WithHttpEndpoint(); var tunnelDependentContainer = builder.AddContainer($"{testName}-container", "mcr.microsoft.com/cbl-mariner/base/nginx", "1.22") .WithEnvironment("UPSTREAM_SERVICE_URL", upstreamService.GetEndpoint("http")) .WaitFor(upstreamService); var downstreamService = builder.AddProject<Projects.ServiceB>($"{testName}-downstream", launchProfileName: null) .WithHttpEndpoint() .WaitFor(tunnelDependentContainer); await using var app = builder.Build(); // Use extra long timeout because if this is first time the tunnel is being used, // getting the base images and building the tunnel (client) proxy image may take a while. await app.StartAsync().DefaultTimeout(TestConstants.ExtraLongTimeoutDuration); foreach (var resourceName in new[] { upstreamService.Resource.Name, tunnelDependentContainer.Resource.Name, downstreamService.Resource.Name }) { await app.ResourceNotifications.WaitForResourceAsync(resourceName, KnownResourceStates.Running) .DefaultTimeout(TestConstants.DefaultOrchestratorTestLongTimeout); } await app.StopAsync().DefaultTimeout(TestConstants.DefaultOrchestratorTestLongTimeout); } }