aspire
aspire copied to clipboard
Error when trying to use DistributedApplicationTestingBuilder with resource with unproxied ports
Trying to use DistributedApplicationTestingBuilder in Aspire.Hosting.Testing with a resource that uses unproxied ports results in an exception:
System.InvalidOperationException : Service 'webfrontend_https_66317ca1' needs to specify a port for endpoint 'https' since it isn't using a proxy.
ApplicationExecutor.AddAllocatedEndpointInfo(IEnumerable`1 resources) line 867
ApplicationExecutor.CreateContainersAndExecutablesAsync(CancellationToken cancellationToken) line 836
ApplicationExecutor.RunApplicationAsync(CancellationToken cancellationToken) line 121
DcpHostService.StartAsync(CancellationToken cancellationToken) line 70
Host.<StartAsync>b__15_1(IHostedService service, CancellationToken token)
Host.ForeachService[T](IEnumerable`1 services, CancellationToken token, Boolean concurrent, Boolean abortOnFirstException, List`1 exceptions, Func`3 operation)
Host.StartAsync(CancellationToken cancellationToken)
ObservedHost.StartAsync(CancellationToken cancellationToken) line 369
DistributedApplicationFactory.StartAsync(CancellationToken cancellationToken) line 52
DelegatedHost.StartAsync(CancellationToken cancellationToken) line 158
DelegatedDistributedApplication.StartAsync(CancellationToken cancellationToken) line 133
WebTests.GetWebResourceRootReturnsOkStatusCode() line 13
WebTests.GetWebResourceRootReturnsOkStatusCode() line 20
To reproduce, create a new Aspire Starter App with a tests project and disable the endpoint proxies for the webfrontend resource:
var builder = DistributedApplication.CreateBuilder(args);
var apiService = builder.AddProject<Projects.AspireApp7_ApiService>("apiservice");
builder.AddProject<Projects.AspireApp7_Web>("webfrontend")
.WithEndpoint("http", ea => ea.IsProxied = false)
.WithEndpoint("https", ea => ea.IsProxied = false)
.WithExternalHttpEndpoints()
.WithReference(apiService);
builder.Build().Run();
Run the application and note that it works just fine.
Run the test it will fail with the exception above.
@ReubenBond perhaps something to do with the port randomization routine?
Your hypothesis sounds right. Taking a look
The relevant line is here, but it already looks correct to me: we are accounting for non-proxied ports by no-op'ing. I wonder what's going wrong in this case. My guess is that we aren't loading the launch settings, so it has no default port.
Hmm if we aren't loading launch settings how does it get endpoints at all? Or do you mean we simply ignore the ports specified in the launch settings when running under the test host?
Yep, that's it. If I specify a launch profile in the sample, it works:
var builder = DistributedApplication.CreateBuilder(args);
builder.AddRedis("redis1");
builder.AddProject<Projects.TestingAppHost1_MyWebApp>("mywebapp1", "https") // Specify "https" to make it work
.WithEndpoint("http", ea => ea.IsProxied = false)
.WithEndpoint("https", ea => ea.IsProxied = false)
.WithExternalHttpEndpoints();
builder.AddProject<Projects.TestingAppHost1_MyWorker>("myworker1")
.WithEndpoint(name: "myendpoint1");
builder.AddPostgres("postgres1");
builder.Build().Run();
Hmm if we aren't loading launch settings how does it get endpoints at all? Or do you mean we simply ignore the ports specified in the launch settings when running under the test host?
By default, for proxied ports, DCP picks ports for the app and tells the app what to bind to. When running under the test host, we aren't getting a launch profile specified, so non-proxied ports have no default values specified.
Note I found this after having issues using CreateHttpClient with a custom resource that has an unproxied endpoint named "http" with a specified port. In that case, it fails with:
System.ArgumentException : Endpoint '' for resource 'ingress' not found. (Parameter 'endpointName')
DistributedApplicationHostingTestingExtensions.GetEndpointUriStringCore(DistributedApplication app, String resourceName, String endpointName) line 99
DistributedApplicationHostingTestingExtensions.CreateHttpClient(DistributedApplication app, String resourceName, String endpointName) line 25
YarpResourceSample.GetAppsThroughYarpIngressResourceReturnsOkStatusCode() line 21
YarpResourceSample.GetAppsThroughYarpIngressResourceReturnsOkStatusCode() line 27