Skip to content
Merged
36 changes: 36 additions & 0 deletions src/Aspire.Hosting/ApplicationModel/EndpointAnnotation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ public EndpointAnnotation(
IsExternal = isExternal ?? false;
IsProxied = isProxied;
_networkID = networkID ?? KnownNetworkIdentifiers.LocalhostNetwork;
Comment thread
karolz-ms marked this conversation as resolved.
#pragma warning disable CS0618 // Type or member is obsolete
AllAllocatedEndpoints.TryAdd(_networkID, AllocatedEndpointSnapshot);
#pragma warning restore CS0618 // Type or member is obsolete
}

/// <summary>
Expand Down Expand Up @@ -271,6 +273,7 @@ IEnumerator IEnumerable.GetEnumerator()
/// <summary>
/// Adds an AllocatedEndpoint snapshot for a specific network if one does not already exist.
/// </summary>
[Obsolete("This method is for internal use only and will be marked internal in a future Aspire release. Use AddOrUpdateAllocatedEndpoint instead.")]
public bool TryAdd(NetworkIdentifier networkID, ValueSnapshot<AllocatedEndpoint> snapshot)
{
lock (_snapshots)
Expand All @@ -283,4 +286,37 @@ public bool TryAdd(NetworkIdentifier networkID, ValueSnapshot<AllocatedEndpoint>
return true;
}
}

/// <summary>
/// Adds and AllocatedEndpoint value associated with a specific network to the snapshot list.
Comment thread
karolz-ms marked this conversation as resolved.
Outdated
/// </summary>
public void AddOrUpdateAllocatedEndpoint(NetworkIdentifier networkID, AllocatedEndpoint endpoint)
{
var nes = GetSnapshotFor(networkID);
nes.Snapshot.SetValue(endpoint);
}

/// <summary>
/// Gets an AllocatedEndpoint for a given network ID, waiting for it to appear if it is not already present.
/// </summary>
public Task<AllocatedEndpoint> GetAllocatedEndpointAsync(NetworkIdentifier networkID, CancellationToken cancellationToken = default)
{
var nes = GetSnapshotFor(networkID);
return nes.Snapshot.GetValueAsync(cancellationToken);
}
Comment thread
karolz-ms marked this conversation as resolved.

private NetworkEndpointSnapshot GetSnapshotFor(NetworkIdentifier networkID)
{
lock (_snapshots)
{
var nes = _snapshots.FirstOrDefault(s => s.NetworkID.Equals(networkID));
if (nes is null)
{
nes = new NetworkEndpointSnapshot(new ValueSnapshot<AllocatedEndpoint>(), networkID);
_snapshots.Add(nes);
}
return nes;
}
}

}
15 changes: 1 addition & 14 deletions src/Aspire.Hosting/ApplicationModel/EndpointReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -307,21 +307,8 @@ public class EndpointReferenceExpression(EndpointReference endpointReference, En

async ValueTask<string?> ResolveValueWithAllocatedAddress()
{
// We are going to take the first snapshot that matches the context network ID. In general there might be multiple endpoints for a single service,
// and in future we might need some sort of policy to choose between them, but for now we just take the first one.
var endpointSnapshots = Endpoint.EndpointAnnotation.AllAllocatedEndpoints;
var nes = endpointSnapshots.Where(nes => nes.NetworkID == networkContext).FirstOrDefault();
if (nes is null)
{
nes = new NetworkEndpointSnapshot(new ValueSnapshot<AllocatedEndpoint>(), networkContext);
if (!endpointSnapshots.TryAdd(networkContext, nes.Snapshot))
{
// Someone else added it first, use theirs.
nes = endpointSnapshots.Where(nes => nes.NetworkID == networkContext).First();
}
}

var allocatedEndpoint = await nes.Snapshot.GetValueAsync(cancellationToken).ConfigureAwait(false);
var allocatedEndpoint = await endpointSnapshots.GetAllocatedEndpointAsync(networkContext, cancellationToken).ConfigureAwait(false);

return Property switch
{
Expand Down
8 changes: 2 additions & 6 deletions src/Aspire.Hosting/Dcp/DcpExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -994,9 +994,7 @@ private void AddAllocatedEndpointInfo(IEnumerable<RenderedModelResource> resourc
targetPortExpression: $$$"""{{- portForServing "{{{svc.Metadata.Name}}}" -}}""",
KnownNetworkIdentifiers.DefaultAspireContainerNetwork
);
var snapshot = new ValueSnapshot<AllocatedEndpoint>();
snapshot.SetValue(allocatedEndpoint);
sp.EndpointAnnotation.AllAllocatedEndpoints.TryAdd(allocatedEndpoint.NetworkID, snapshot);
sp.EndpointAnnotation.AllAllocatedEndpoints.AddOrUpdateAllocatedEndpoint(allocatedEndpoint.NetworkID, allocatedEndpoint);
}
}
}
Expand Down Expand Up @@ -1056,9 +1054,7 @@ ts.Service is not null &&
targetPortExpression: $$$"""{{- portForServing "{{{ts.Service.Name}}}" -}}""",
networkID
);
var snapshot = new ValueSnapshot<AllocatedEndpoint>();
snapshot.SetValue(tunnelAllocatedEndpoint);
endpoint.AllAllocatedEndpoints.TryAdd(networkID, snapshot);
endpoint.AllAllocatedEndpoints.AddOrUpdateAllocatedEndpoint(networkID, tunnelAllocatedEndpoint);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -371,9 +371,7 @@ public async Task WithPostgresMcpOnAzureDatabaseRunAsContainerAddsMcpResource()
c.WithEndpoint("tcp", e =>
{
e.AllocatedEndpoint = new AllocatedEndpoint(e, "localhost", 5432);
var snapshot = new ValueSnapshot<AllocatedEndpoint>();
snapshot.SetValue(new AllocatedEndpoint(e, "postgres.dev.internal", 5432, EndpointBindingMode.SingleAddress, targetPortExpression: null, networkID: KnownNetworkIdentifiers.DefaultAspireContainerNetwork));
e.AllAllocatedEndpoints.TryAdd(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, snapshot);
e.AllAllocatedEndpoints.AddOrUpdateAllocatedEndpoint(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, new AllocatedEndpoint(e, "postgres.dev.internal", 5432, EndpointBindingMode.SingleAddress, targetPortExpression: null, networkID: KnownNetworkIdentifiers.DefaultAspireContainerNetwork));
});
});

Expand Down
10 changes: 2 additions & 8 deletions tests/Aspire.Hosting.Containers.Tests/ContainerResourceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,21 +102,15 @@ public async Task AddContainerWithArgs()
e.AllocatedEndpoint = new(e, "localhost", 1234, targetPortExpression: "1234");

// For container-container lookup we need to add an AllocatedEndpoint on the container network side
var ccae = new AllocatedEndpoint(e, "c1.dev.internal", 2234, EndpointBindingMode.SingleAddress, targetPortExpression: "2234", KnownNetworkIdentifiers.DefaultAspireContainerNetwork);
var snapshot = new ValueSnapshot<AllocatedEndpoint>();
snapshot.SetValue(ccae);
e.AllAllocatedEndpoints.TryAdd(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, snapshot);
e.AllAllocatedEndpoints.AddOrUpdateAllocatedEndpoint(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, new AllocatedEndpoint(e, "c1.dev.internal", 2234, EndpointBindingMode.SingleAddress, targetPortExpression: "2234", KnownNetworkIdentifiers.DefaultAspireContainerNetwork));
});

var c2 = appBuilder.AddContainer("container", "none")
.WithEndpoint("ep", e =>
{
e.UriScheme = "http";
// We only care about the container-side endpoint for this test
var snapshot = new ValueSnapshot<AllocatedEndpoint>();
var ae = new AllocatedEndpoint(e, "container.dev.internal", 5678, EndpointBindingMode.SingleAddress, targetPortExpression: "5678", KnownNetworkIdentifiers.DefaultAspireContainerNetwork);
snapshot.SetValue(ae);
e.AllAllocatedEndpoints.TryAdd(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, snapshot);
e.AllAllocatedEndpoints.AddOrUpdateAllocatedEndpoint(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, new AllocatedEndpoint(e, "container.dev.internal", 5678, EndpointBindingMode.SingleAddress, targetPortExpression: "5678", KnownNetworkIdentifiers.DefaultAspireContainerNetwork));
})
.WithArgs(context =>
{
Expand Down
4 changes: 1 addition & 3 deletions tests/Aspire.Hosting.Milvus.Tests/AddMilvusTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,7 @@ public async Task MilvusClientAppWithReferenceContainsConnectionStrings()
.WithEndpoint("grpc", e =>
{
e.AllocatedEndpoint = new AllocatedEndpoint(e, "localhost", MilvusPortGrpc);
var snapshot = new ValueSnapshot<AllocatedEndpoint>();
snapshot.SetValue(new AllocatedEndpoint(e, "my-milvus.dev.internal", MilvusPortGrpc, EndpointBindingMode.SingleAddress, targetPortExpression: null, networkID: KnownNetworkIdentifiers.DefaultAspireContainerNetwork));
e.AllAllocatedEndpoints.TryAdd(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, snapshot);
e.AllAllocatedEndpoints.AddOrUpdateAllocatedEndpoint(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, new AllocatedEndpoint(e, "my-milvus.dev.internal", MilvusPortGrpc, EndpointBindingMode.SingleAddress, targetPortExpression: null, networkID: KnownNetworkIdentifiers.DefaultAspireContainerNetwork));
});

var projectA = appBuilder.AddProject<ProjectA>("projecta", o => o.ExcludeLaunchProfile = true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,7 @@ public async Task WithPostgresMcpOnDatabaseSetsDatabaseUriEnvironmentVariable()
.WithEndpoint("tcp", e =>
{
e.AllocatedEndpoint = new AllocatedEndpoint(e, "localhost", 5432);
var snapshot = new ValueSnapshot<AllocatedEndpoint>();
snapshot.SetValue(new AllocatedEndpoint(e, "postgres.dev.internal", 5432, EndpointBindingMode.SingleAddress, targetPortExpression: null, networkID: KnownNetworkIdentifiers.DefaultAspireContainerNetwork));
e.AllAllocatedEndpoints.TryAdd(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, snapshot);
e.AllAllocatedEndpoints.AddOrUpdateAllocatedEndpoint(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, new AllocatedEndpoint(e, "postgres.dev.internal", 5432, EndpointBindingMode.SingleAddress, targetPortExpression: null, networkID: KnownNetworkIdentifiers.DefaultAspireContainerNetwork));
})
.AddDatabase("db")
.WithPostgresMcp();
Expand Down
8 changes: 2 additions & 6 deletions tests/Aspire.Hosting.Qdrant.Tests/AddQdrantTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -172,16 +172,12 @@ public async Task QdrantClientAppWithReferenceContainsConnectionStrings()
.WithEndpoint("grpc", e =>
{
e.AllocatedEndpoint = new AllocatedEndpoint(e, "localhost", 6334);
var snapshot = new ValueSnapshot<AllocatedEndpoint>();
snapshot.SetValue(new AllocatedEndpoint(e, "my-qdrant.dev.internal", 6334, EndpointBindingMode.SingleAddress, targetPortExpression: null, networkID: KnownNetworkIdentifiers.DefaultAspireContainerNetwork));
e.AllAllocatedEndpoints.TryAdd(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, snapshot);
e.AllAllocatedEndpoints.AddOrUpdateAllocatedEndpoint(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, new AllocatedEndpoint(e, "my-qdrant.dev.internal", 6334, EndpointBindingMode.SingleAddress, targetPortExpression: null, networkID: KnownNetworkIdentifiers.DefaultAspireContainerNetwork));
})
.WithEndpoint("http", e =>
{
e.AllocatedEndpoint = new AllocatedEndpoint(e, "localhost", 6333);
var snapshot = new ValueSnapshot<AllocatedEndpoint>();
snapshot.SetValue(new AllocatedEndpoint(e, "my-qdrant.dev.internal", 6333, EndpointBindingMode.SingleAddress, targetPortExpression: null, networkID: KnownNetworkIdentifiers.DefaultAspireContainerNetwork));
e.AllAllocatedEndpoints.TryAdd(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, snapshot);
e.AllAllocatedEndpoints.AddOrUpdateAllocatedEndpoint(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, new AllocatedEndpoint(e, "my-qdrant.dev.internal", 6333, EndpointBindingMode.SingleAddress, targetPortExpression: null, networkID: KnownNetworkIdentifiers.DefaultAspireContainerNetwork));
});

var projectA = appBuilder.AddProject<ProjectA>("projecta", o => o.ExcludeLaunchProfile = true)
Expand Down
16 changes: 4 additions & 12 deletions tests/Aspire.Hosting.Redis.Tests/AddRedisTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -304,23 +304,17 @@ public async Task WithRedisInsightProducesCorrectEnvironmentVariables()
redis1.WithEndpoint("tcp", e =>
{
e.AllocatedEndpoint = new AllocatedEndpoint(e, "localhost", 5001);
var snapshot = new ValueSnapshot<AllocatedEndpoint>();
snapshot.SetValue(new AllocatedEndpoint(e, "myredis1.dev.internal", 5001, EndpointBindingMode.SingleAddress, targetPortExpression: null, networkID: KnownNetworkIdentifiers.DefaultAspireContainerNetwork));
e.AllAllocatedEndpoints.TryAdd(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, snapshot);
e.AllAllocatedEndpoints.AddOrUpdateAllocatedEndpoint(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, new AllocatedEndpoint(e, "myredis1.dev.internal", 5001, EndpointBindingMode.SingleAddress, targetPortExpression: null, networkID: KnownNetworkIdentifiers.DefaultAspireContainerNetwork));
});
redis2.WithEndpoint("tcp", e =>
{
e.AllocatedEndpoint = new AllocatedEndpoint(e, "localhost", 5002);
var snapshot = new ValueSnapshot<AllocatedEndpoint>();
snapshot.SetValue(new AllocatedEndpoint(e, "myredis2.dev.internal", 5002, EndpointBindingMode.SingleAddress, targetPortExpression: null, networkID: KnownNetworkIdentifiers.DefaultAspireContainerNetwork));
e.AllAllocatedEndpoints.TryAdd(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, snapshot);
e.AllAllocatedEndpoints.AddOrUpdateAllocatedEndpoint(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, new AllocatedEndpoint(e, "myredis2.dev.internal", 5002, EndpointBindingMode.SingleAddress, targetPortExpression: null, networkID: KnownNetworkIdentifiers.DefaultAspireContainerNetwork));
});
redis3.WithEndpoint("tcp", e =>
{
e.AllocatedEndpoint = new AllocatedEndpoint(e, "localhost", 5003);
var snapshot = new ValueSnapshot<AllocatedEndpoint>();
snapshot.SetValue(new AllocatedEndpoint(e, "myredis3.dev.internal", 5003, EndpointBindingMode.SingleAddress, targetPortExpression: null, networkID: KnownNetworkIdentifiers.DefaultAspireContainerNetwork));
e.AllAllocatedEndpoints.TryAdd(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, snapshot);
e.AllAllocatedEndpoints.AddOrUpdateAllocatedEndpoint(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, new AllocatedEndpoint(e, "myredis3.dev.internal", 5003, EndpointBindingMode.SingleAddress, targetPortExpression: null, networkID: KnownNetworkIdentifiers.DefaultAspireContainerNetwork));
});

var redisInsight = Assert.Single(builder.Resources.OfType<RedisInsightResource>());
Expand Down Expand Up @@ -734,9 +728,7 @@ public async Task RedisInsightEnvironmentCallbackIsIdempotent()
.WithEndpoint("tcp", e =>
{
e.AllocatedEndpoint = new AllocatedEndpoint(e, "localhost", 6379);
var snapshot = new ValueSnapshot<AllocatedEndpoint>();
snapshot.SetValue(new AllocatedEndpoint(e, "redis.dev.internal", 6379, EndpointBindingMode.SingleAddress, targetPortExpression: null, networkID: KnownNetworkIdentifiers.DefaultAspireContainerNetwork));
e.AllAllocatedEndpoints.TryAdd(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, snapshot);
e.AllAllocatedEndpoints.AddOrUpdateAllocatedEndpoint(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, new AllocatedEndpoint(e, "redis.dev.internal", 6379, EndpointBindingMode.SingleAddress, targetPortExpression: null, networkID: KnownNetworkIdentifiers.DefaultAspireContainerNetwork));
})
.WithRedisInsight();

Expand Down
4 changes: 1 addition & 3 deletions tests/Aspire.Hosting.Tests/EndpointReferenceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -330,9 +330,7 @@ public async Task PropertyResolutionTest(EndpointProperty property, ResourceKind
: ("host.docker.internal", port);

var containerEndpoint = new AllocatedEndpoint(annotation, containerHost, containerPort, EndpointBindingMode.SingleAddress, targetPortExpression: targetPort.ToString(), KnownNetworkIdentifiers.DefaultAspireContainerNetwork);
var snapshot = new ValueSnapshot<AllocatedEndpoint>();
snapshot.SetValue(containerEndpoint);
annotation.AllAllocatedEndpoints.TryAdd(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, snapshot);
annotation.AllAllocatedEndpoints.AddOrUpdateAllocatedEndpoint(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, containerEndpoint);

var expression = destination.GetEndpoint(annotation.Name).Property(property);

Expand Down
15 changes: 3 additions & 12 deletions tests/Aspire.Hosting.Tests/ExpressionResolverTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,7 @@ public async Task ExpressionResolverGeneratesCorrectEndpointStrings(string exprN
if (sourceIsContainer)
{
// Note: on the container network side the port and target port are always the same for AllocatedEndpoint.
var ae = new AllocatedEndpoint(e, containerHost, 22345, EndpointBindingMode.SingleAddress, targetPortExpression: "22345", KnownNetworkIdentifiers.DefaultAspireContainerNetwork);
var snapshot = new ValueSnapshot<AllocatedEndpoint>();
snapshot.SetValue(ae);
e.AllAllocatedEndpoints.TryAdd(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, snapshot);
e.AllAllocatedEndpoints.AddOrUpdateAllocatedEndpoint(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, new AllocatedEndpoint(e, containerHost, 22345, EndpointBindingMode.SingleAddress, targetPortExpression: "22345", KnownNetworkIdentifiers.DefaultAspireContainerNetwork));
}
})
.WithEndpoint("endpoint2", e =>
Expand All @@ -108,10 +105,7 @@ public async Task ExpressionResolverGeneratesCorrectEndpointStrings(string exprN
e.AllocatedEndpoint = new(e, "localhost", 12346, targetPortExpression: "10001");
if (sourceIsContainer)
{
var ae = new AllocatedEndpoint(e, containerHost, 22346, EndpointBindingMode.SingleAddress, targetPortExpression: "22346", KnownNetworkIdentifiers.DefaultAspireContainerNetwork);
var snapshot = new ValueSnapshot<AllocatedEndpoint>();
snapshot.SetValue(ae);
e.AllAllocatedEndpoints.TryAdd(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, snapshot);
e.AllAllocatedEndpoints.AddOrUpdateAllocatedEndpoint(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, new AllocatedEndpoint(e, containerHost, 22346, EndpointBindingMode.SingleAddress, targetPortExpression: "22346", KnownNetworkIdentifiers.DefaultAspireContainerNetwork));
}
})
.WithEndpoint("endpoint3", e =>
Expand All @@ -120,10 +114,7 @@ public async Task ExpressionResolverGeneratesCorrectEndpointStrings(string exprN
e.AllocatedEndpoint = new(e, "host with space", 12347);
if (sourceIsContainer)
{
var ae = new AllocatedEndpoint(e, containerHost, 22347, EndpointBindingMode.SingleAddress, targetPortExpression: "22346", KnownNetworkIdentifiers.DefaultAspireContainerNetwork);
var snapshot = new ValueSnapshot<AllocatedEndpoint>();
snapshot.SetValue(ae);
e.AllAllocatedEndpoints.TryAdd(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, snapshot);
e.AllAllocatedEndpoints.AddOrUpdateAllocatedEndpoint(KnownNetworkIdentifiers.DefaultAspireContainerNetwork, new AllocatedEndpoint(e, containerHost, 22347, EndpointBindingMode.SingleAddress, targetPortExpression: "22346", KnownNetworkIdentifiers.DefaultAspireContainerNetwork));
Comment thread
karolz-ms marked this conversation as resolved.
Outdated
}
});

Expand Down
Loading
Loading