Project resource waits on itself when referencing its own container-to-host endpoint
- Dominant language
- C#
- Stars
- 6.3k
- Forks
- 991
- Avg merge
- 2d 12h
- Merged PRs (30d)
- 201
Description
### Is there an existing issue for this?
- [x] I have searched the existing issues
### Is your feature request related to a problem? Please describe the problem.
I have a peculiar use case. We have used Consul for service discovery and now continue using it with Aspire.
I have built a sample repo to illustrate the use case - https://github.com/Niksson/AspireProjectContainerEndpointSelfReferenceSample
There are 3 services in the host model:
1. Consul itself as `ContainerResource`
2. A `gateway` that uses Consul to forward the request to another downstream service
3. An actual `weather` service that serves the request
If you start the AppHost project, the `weather` service will hang in `Starting` state, with the following message:
```
Waiting for endpoint 'http' on resource 'weather' for the 'aspire-container-network' network
```
### Describe the solution you'd like
In this case I want to inject a project's own container-to-host endpoint as environment variable. Otherwise I need to inject a hardcoded `host.docker.internal`, see explanation below.
### Additional context
Suppose we register service in consul like this:
```csharp
string serviceHost = app.Configuration["Consul:ServiceHost"];
int servicePort = app.Configuration.GetSection("Consul:ServicePort").Get();
string healthCheckScheme = app.Configuration["Consul:HealthCheckScheme"];
string healthCheckHost = app.Configuration["Consul:HealthCheckHost"];
int healthCheckPort = app.Configuration.GetSection("Consul:HealthCheckPort").Get();
string healthCheckUri = $"{healthCheckScheme}://{healthCheckHost}:{healthCheckPort}/health";
IConsulClient consulClient = app.Services.GetRequiredService();
var registration = new AgentServiceRegistration()
{
ID = "gateway-1",
Name = "gateway",
Address = serviceHost,
Port = servicePort,
Tags = [],
Checks =
[
new AgentCheckRegistration()
{
HTTP = healthCheckUri,
// ...
}
]
};
```
Initially I injected the variables as follows, and it works as expected - host will be `localhost` and port will be whatever Aspire assigns:
```csharp
var weatherEndpoint= weather.GetEndpoint("http");
weather
.WithEnvironment("Consul:ServiceHost", weatherEndpoint.Property(EndpointProperty.Host))
.WithEnvironment("Consul:ServicePort", weatherEndpoint.Property(EndpointProperty.Port))
.WithEnvironment("Consul:HealthCheckScheme", "http")
.WithEnvironment("Consul:HealthCheckHost", "host.docker.internal")
.WithEnvironment("Consul:HealthCheckPort", weatherEndpoint.Property(EndpointProperty.Port));
```
What I tried to do to get rid of hardcoded `host.docker.internal` is to get the endpoint references with explicit network IDs:
```csharp
var weather = builder.AddProject("weather")
.WithHttpHealthCheck("/health")
.WithReference(consul);
// Inject host-to-host endpoint
var weatherLocalhostEndpoint = weather.GetEndpoint("http", KnownNetworkIdentifiers.LocalhostNetwork);
weather
.WithEnvironment("Consul:ServiceHost", weatherLocalhostEndpoint.Property(EndpointProperty.Host))
.WithEnvironment("Consul:ServicePort", weatherLocalhostEndpoint.Property(EndpointProperty.Port));
// Inject container-to-host endpoint
var weatherContainerEndpoint = weather.GetEndpoint("http", KnownNetworkIdentifiers.DefaultAspireContainerNetwork);
weather
.WithEnvironment("Consul:HealthCheckScheme", weatherContainerEndpoint.Property(EndpointProperty.Scheme))
.WithEnvironment("Consul:HealthCheckHost", weatherContainerEndpoint.Property(EndpointProperty.Host))
.WithEnvironment("Consul:HealthCheckPort", weatherContainerEndpoint.Property(EndpointProperty.Port));
```
And this doesn't work as I hoped it would, unfortunately
Contributor guide
Research direction
Start by running the linked sample repository's AppHost project and inspect the resource definitions using GetEndpoint, KnownNetworkIdentifiers, and WithEnvironment. Trace why the weather resource waits on its own container-to-host endpoint. Done means the self-reference resolves without leaving weather in Starting, while preserving the intended Consul health-check host and port behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- infrastructure, networking
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100