-
Notifications
You must be signed in to change notification settings - Fork 855
PublishAsDockerFile causes port mismatch in Kubernetes publish when resource endpoint is referenced by another resource #14588
Description
Is there an existing issue for this?
- I have searched the existing issues
Describe the bug
Description
When an ExecutableResource uses PublishAsDockerFile() and another resource references its endpoint via WithReference(), the Kubernetes publisher generates inconsistent ports — the referencing resource gets a different port than the one assigned to the executable's service/deployment.
Reproduction
Single file (repro.cs):
#:sdk Aspire.AppHost.Sdk@13.1.0
#:package Aspire.Hosting.AppHost@13.1.0
#:package Aspire.Hosting.Kubernetes@13.1.0-preview.1.25616.3
#:property NoWarn=ASPIRECOMPUTE003
var builder = DistributedApplication.CreateBuilder(args);
var api = builder.AddExecutable("api", "echo", ".", "hello")
.WithHttpEndpoint(env: "PORT")
.PublishAsDockerFile();
builder.AddContainer("gateway", "nginx")
.WithHttpEndpoint(targetPort: 8080)
.WithReference(api.GetEndpoint("http"));
builder.AddContainerRegistry("registry", "localhost:5001");
builder.AddKubernetesEnvironment("k8s");
builder.Build().Run();Run with:
dotnet run repro.cs -- publish --publisher kubernetes --output-path ./aspire-output
Observed behavior
The log output shows the resource being created twice:
Creating Kubernetes resource for api
Creating Kubernetes resource for api
Creating Kubernetes resource for gateway
The generated output has a port mismatch:
| Location | Port |
|---|---|
values.yaml → services__api__http__0 |
http://api-service:8001 |
templates/api/service.yaml → port |
8000 |
templates/api/deployment.yaml → containerPort |
8000 |
| The gateway will try to reach the api at port 8001, but the api service/deployment exposes port 8000. |
Expected behavior
All generated references to the api's endpoint should use the same port.
Root cause
PublishAsDockerFile (ExecutableResourceBuilderExtensions.cs#L145-L148) removes the original ExecutableResource from the model and adds a new ExecutableContainerResource in its place. The replacement shares the original's Annotations collection, but they are different object instances.
However, other resources still hold EndpointReference objects that point to the original resource (the source comment at L143-L144 acknowledges these "dangling references").
During Kubernetes publish, KubernetesEnvironmentContext.CreateKubernetesResourceAsync uses a Dictionary<IResource, KubernetesResource> cache keyed by object identity. When the gateway's environment is processed, it encounters the EndpointReference pointing to the original resource → cache miss → creates KubernetesResource #1, allocates port 8001 via PortAllocator. Then the main loop processes the replacement ExecutableContainerResource → different object, another cache miss → creates KubernetesResource #2, allocates port 8000 from the same PortAllocator.
The DeploymentTargetAnnotation (which controls YAML output) points to KubernetesResource #2 (port 8000), but the gateway's env vars were resolved using KubernetesResource #1 (port 8001).
This affects AddUvicornApp, AddPythonApp, and any ExecutableResource using PublishAsDockerFile whose endpoint is referenced by another resource.
Expected Behavior
No response
Steps To Reproduce
No response
Exceptions (if any)
No response
.NET Version info
No response
Anything else?
No response