Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ internal ReferenceExpression GetConnectionString(string? eventHub = null, string

if (IsEmulator)
{
builder.Append($"Endpoint=sb://{EmulatorEndpoint.Property(EndpointProperty.Host)}:{EmulatorEndpoint.Property(EndpointProperty.Port)};SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true");
builder.Append($"Endpoint=sb://{EmulatorEndpoint.Property(EndpointProperty.HostAndPort)};SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true");
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public class AzureServiceBusResource(string name, Action<AzureResourceInfrastruc
/// </summary>
public ReferenceExpression ConnectionStringExpression =>
IsEmulator
? ReferenceExpression.Create($"Endpoint=sb://{EmulatorEndpoint.Property(EndpointProperty.Host)}:{EmulatorEndpoint.Property(EndpointProperty.Port)};SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;")
? ReferenceExpression.Create($"Endpoint=sb://{EmulatorEndpoint.Property(EndpointProperty.HostAndPort)};SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;")
: ReferenceExpression.Create($"{ServiceBusEndpoint}");

void IResourceWithAzureFunctionsConfig.ApplyAzureFunctionsConfiguration(IDictionary<string, object> target, string connectionName)
Expand Down
2 changes: 1 addition & 1 deletion src/Aspire.Hosting.Elasticsearch/ElasticsearchResource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,6 @@ public ElasticsearchResource(string name, ParameterResource password) : base(nam
/// Gets the connection string expression for the Elasticsearch
/// </summary>
public ReferenceExpression ConnectionStringExpression =>
ReferenceExpression.Create($"http://{UserName}:{PasswordParameter}@{PrimaryEndpoint.Property(EndpointProperty.Host)}:{PrimaryEndpoint.Property(EndpointProperty.Port)}");
ReferenceExpression.Create($"http://{UserName}:{PasswordParameter}@{PrimaryEndpoint.Property(EndpointProperty.HostAndPort)}");
}

5 changes: 2 additions & 3 deletions src/Aspire.Hosting.Garnet/GarnetResource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@ public class GarnetResource(string name) : ContainerResource(ThrowIfNull(name)),
/// <summary>
/// Gets the connection string expression for the Garnet server.
/// </summary>
public ReferenceExpression ConnectionStringExpression =>
ReferenceExpression.Create(
$"{PrimaryEndpoint.Property(EndpointProperty.Host)}:{PrimaryEndpoint.Property(EndpointProperty.Port)}");
public ReferenceExpression ConnectionStringExpression =>
ReferenceExpression.Create($"{PrimaryEndpoint.Property(EndpointProperty.HostAndPort)}");

private static string ThrowIfNull([NotNull] string? argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null)
=> argument ?? throw new ArgumentNullException(paramName);
Expand Down
5 changes: 2 additions & 3 deletions src/Aspire.Hosting.Kafka/KafkaBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ static void ConfigureKafkaUIContainer(EnvironmentCallbackContext context, Endpoi
// In run mode, Kafka UI assumes Kafka is being accessed over a default Aspire container network and hardcodes the host as the Kafka resource name
// This will need to be refactored once updated service discovery APIs are available
? ReferenceExpression.Create($"{endpoint.Resource.Name}:{endpoint.Property(EndpointProperty.TargetPort)}")
: ReferenceExpression.Create($"{endpoint.Property(EndpointProperty.Host)}:{endpoint.Property(EndpointProperty.Port)}");
: ReferenceExpression.Create($"{endpoint.Property(EndpointProperty.HostAndPort)}");

context.EnvironmentVariables.Add($"KAFKA_CLUSTERS_{index}_NAME", endpoint.Resource.Name);
context.EnvironmentVariables.Add($"KAFKA_CLUSTERS_{index}_BOOTSTRAPSERVERS", bootstrapServers);
Expand Down Expand Up @@ -218,8 +218,7 @@ private static void ConfigureKafkaContainer(EnvironmentCallbackContext context,
// In run mode, PLAINTEXT_INTERNAL assumes kafka is being accessed over a default Aspire container network and hardcodes the resource address
// This will need to be refactored once updated service discovery APIs are available
? ReferenceExpression.Create($"PLAINTEXT://localhost:29092,PLAINTEXT_HOST://localhost:{primaryEndpoint.Property(EndpointProperty.Port)},PLAINTEXT_INTERNAL://{resource.Name}:{internalEndpoint.Property(EndpointProperty.TargetPort)}")
: ReferenceExpression.Create(
$"PLAINTEXT://{primaryEndpoint.Property(EndpointProperty.Host)}:29092,PLAINTEXT_HOST://{primaryEndpoint.Property(EndpointProperty.Host)}:{primaryEndpoint.Property(EndpointProperty.Port)},PLAINTEXT_INTERNAL://{internalEndpoint.Property(EndpointProperty.Host)}:{internalEndpoint.Property(EndpointProperty.Port)}");
: ReferenceExpression.Create($"PLAINTEXT://{primaryEndpoint.Property(EndpointProperty.Host)}:29092,PLAINTEXT_HOST://{primaryEndpoint.Property(EndpointProperty.HostAndPort)},PLAINTEXT_INTERNAL://{internalEndpoint.Property(EndpointProperty.HostAndPort)}");

context.EnvironmentVariables["KAFKA_ADVERTISED_LISTENERS"] = advertisedListeners;
}
Expand Down
3 changes: 1 addition & 2 deletions src/Aspire.Hosting.Kafka/KafkaServerResource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,5 @@ public class KafkaServerResource(string name) : ContainerResource(name), IResour
/// Gets the connection string expression for the Kafka broker.
/// </summary>
public ReferenceExpression ConnectionStringExpression =>
ReferenceExpression.Create(
$"{PrimaryEndpoint.Property(EndpointProperty.Host)}:{PrimaryEndpoint.Property(EndpointProperty.Port)}");
ReferenceExpression.Create($"{PrimaryEndpoint.Property(EndpointProperty.HostAndPort)}");
}
2 changes: 1 addition & 1 deletion src/Aspire.Hosting.MongoDB/MongoDBServerResource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ internal ReferenceExpression BuildConnectionString(string? databaseName = null)
builder.Append($"{UserNameReference}:{PasswordParameter}@");
}

builder.Append($"{PrimaryEndpoint.Property(EndpointProperty.Host)}:{PrimaryEndpoint.Property(EndpointProperty.Port)}");
builder.Append($"{PrimaryEndpoint.Property(EndpointProperty.HostAndPort)}");

if (databaseName is not null)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Aspire.Hosting.Nats/NatsServerResource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ internal ReferenceExpression BuildConnectionString()
builder.Append($"{UserNameReference}:{PasswordParameter}@");
}

builder.Append($"{PrimaryEndpoint.Property(EndpointProperty.Host)}:{PrimaryEndpoint.Property(EndpointProperty.Port)}");
builder.Append($"{PrimaryEndpoint.Property(EndpointProperty.HostAndPort)}");

return builder.Build();
}
Expand Down
2 changes: 1 addition & 1 deletion src/Aspire.Hosting.Oracle/OracleDatabaseServerResource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public OracleDatabaseServerResource(string name, ParameterResource password) : b
/// </summary>
public ReferenceExpression ConnectionStringExpression =>
ReferenceExpression.Create(
$"user id=system;password={PasswordParameter};data source={PrimaryEndpoint.Property(EndpointProperty.Host)}:{PrimaryEndpoint.Property(EndpointProperty.Port)}");
$"user id=system;password={PasswordParameter};data source={PrimaryEndpoint.Property(EndpointProperty.HostAndPort)}");

private readonly Dictionary<string, string> _databases = new(StringComparers.ResourceName);

Expand Down
2 changes: 1 addition & 1 deletion src/Aspire.Hosting.RabbitMQ/RabbitMQServerResource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,5 @@ UserNameParameter is not null ?
/// </summary>
public ReferenceExpression ConnectionStringExpression =>
ReferenceExpression.Create(
$"amqp://{UserNameReference}:{PasswordParameter}@{PrimaryEndpoint.Property(EndpointProperty.Host)}:{PrimaryEndpoint.Property(EndpointProperty.Port)}");
$"amqp://{UserNameReference}:{PasswordParameter}@{PrimaryEndpoint.Property(EndpointProperty.HostAndPort)}");
}
3 changes: 1 addition & 2 deletions src/Aspire.Hosting.Redis/RedisResource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ public class RedisResource(string name) : ContainerResource(name), IResourceWith
public EndpointReference PrimaryEndpoint => _primaryEndpoint ??= new(this, PrimaryEndpointName);

private ReferenceExpression ConnectionString =>
ReferenceExpression.Create(
$"{PrimaryEndpoint.Property(EndpointProperty.Host)}:{PrimaryEndpoint.Property(EndpointProperty.Port)}");
ReferenceExpression.Create($"{PrimaryEndpoint.Property(EndpointProperty.HostAndPort)}");

/// <summary>
/// Gets the connection string expression for the Redis server.
Expand Down
3 changes: 1 addition & 2 deletions src/Aspire.Hosting.Valkey/ValkeyResource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,5 @@ public class ValkeyResource(string name) : ContainerResource(name), IResourceWit
/// Gets the connection string expression for the Valkey server.
/// </summary>
public ReferenceExpression ConnectionStringExpression =>
ReferenceExpression.Create(
$"{PrimaryEndpoint.Property(EndpointProperty.Host)}:{PrimaryEndpoint.Property(EndpointProperty.Port)}");
ReferenceExpression.Create($"{PrimaryEndpoint.Property(EndpointProperty.HostAndPort)}");
}
21 changes: 14 additions & 7 deletions src/Aspire.Hosting/ApplicationModel/EndpointReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,18 @@ public sealed class EndpointReference : IManifestExpressionProvider, IValueProvi
/// </summary>
internal string GetExpression(EndpointProperty property = EndpointProperty.Url)
{
var prop = property switch
return property switch
{
EndpointProperty.Url => "url",
EndpointProperty.Host or EndpointProperty.IPV4Host => "host",
EndpointProperty.Port => "port",
EndpointProperty.Scheme => "scheme",
EndpointProperty.TargetPort => "targetPort",
EndpointProperty.Url => Binding("url"),
EndpointProperty.Host or EndpointProperty.IPV4Host => Binding("host"),
EndpointProperty.Port => Binding("port"),
EndpointProperty.Scheme => Binding("scheme"),
EndpointProperty.TargetPort => Binding("targetPort"),
EndpointProperty.HostAndPort => $"{Binding("host")}:{Binding("port")}",
_ => throw new InvalidOperationException($"The property '{property}' is not supported for the endpoint '{EndpointName}'.")
};

return $"{{{Resource.Name}.bindings.{EndpointName}.{prop}}}";
string Binding(string prop) => $"{{{Resource.Name}.bindings.{EndpointName}.{prop}}}";
}

/// <summary>
Expand Down Expand Up @@ -177,6 +178,7 @@ public class EndpointReferenceExpression(EndpointReference endpointReference, En
EndpointProperty.Port => new(Endpoint.Port.ToString(CultureInfo.InvariantCulture)),
EndpointProperty.Scheme => new(Endpoint.Scheme),
EndpointProperty.TargetPort => new(ComputeTargetPort()),
EndpointProperty.HostAndPort => new($"{Endpoint.Host}:{Endpoint.Port.ToString(CultureInfo.InvariantCulture)}"),
_ => throw new InvalidOperationException($"The property '{Property}' is not supported for the endpoint '{Endpoint.EndpointName}'.")
};

Expand Down Expand Up @@ -227,4 +229,9 @@ public enum EndpointProperty
/// The target port of the endpoint.
/// </summary>
TargetPort,

/// <summary>
/// The host and port of the endpoint in the format `{Host}:{Port}`.
/// </summary>
HostAndPort
}
7 changes: 4 additions & 3 deletions src/Aspire.Hosting/ApplicationModel/ExpressionResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,12 @@ class HostAndPortPresence
{
hostAndPortPresence.HasPort = true;
}
else if (property == EndpointProperty.Url)
else if (property is EndpointProperty.Url or EndpointProperty.HostAndPort)
{
hostAndPortPresence.HasHost = hostAndPortPresence.HasPort = true;
}

return string.Empty;
}

// We need to use the root resource, e.g. AzureStorageResource instead of AzureBlobResource
// Otherwise, we get the wrong values for IsContainer and Name
var target = endpointReference.Resource.GetRootResource();
Expand All @@ -73,6 +71,9 @@ bool HasBothHostAndPort() =>
endpointReference.Scheme,
await EvalEndpointAsync(endpointReference, EndpointProperty.Host).ConfigureAwait(false),
await EvalEndpointAsync(endpointReference, EndpointProperty.Port).ConfigureAwait(false)),
(EndpointProperty.HostAndPort, _, _) => string.Format(CultureInfo.InvariantCulture, "{0}:{1}",
await EvalEndpointAsync(endpointReference, EndpointProperty.Host).ConfigureAwait(false),
await EvalEndpointAsync(endpointReference, EndpointProperty.Port).ConfigureAwait(false)),
_ => await endpointReference.Property(property).GetValueAsync(cancellationToken).ConfigureAwait(false)
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public async Task AsProvisioningParameterTests()
.WithHttpsEndpoint();

var endpointReference = apiProject.GetEndpoint("https");
var referenceExpression = ReferenceExpression.Create($"prefix:{endpointReference.Property(EndpointProperty.Host)}:{endpointReference.Property(EndpointProperty.Port)}");
var referenceExpression = ReferenceExpression.Create($"prefix:{endpointReference.Property(EndpointProperty.HostAndPort)}");

var resource1 = builder.AddAzureInfrastructure("resource1", infrastructure =>
{
Expand Down
3 changes: 3 additions & 0 deletions tests/Aspire.Hosting.Tests/ExpressionResolverTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public class ExpressionResolverTests
[InlineData("OnlyHost", true, true, "Host=localhost;")] // host not replaced since no port
[InlineData("OnlyPort", true, false, "Port=12345;")]
[InlineData("OnlyPort", true, true, "Port=12345;")] // port not replaced since no host
[InlineData("HostAndPort", true, false, "HostPort=ContainerHostName:12345")]
[InlineData("HostAndPort", true, true, "HostPort=testresource:10000")] // host not replaced since no port
[InlineData("PortBeforeHost", true, false, "Port=12345;Host=ContainerHostName;")]
[InlineData("PortBeforeHost", true, true, "Port=10000;Host=testresource;")]
[InlineData("FullAndPartial", true, false, "Test1=http://ContainerHostName:12345/;Test2=https://localhost:12346/;")]
Expand Down Expand Up @@ -135,6 +137,7 @@ public TestExpressionResolverResource(string exprName) : base("testresource")
{ "Url2", ReferenceExpression.Create($"Url={Endpoint1};") },
{ "OnlyHost", ReferenceExpression.Create($"Host={Endpoint1.Property(EndpointProperty.Host)};") },
{ "OnlyPort", ReferenceExpression.Create($"Port={Endpoint1.Property(EndpointProperty.Port)};") },
{ "HostAndPort", ReferenceExpression.Create($"HostPort={Endpoint1.Property(EndpointProperty.HostAndPort)}") },
{ "PortBeforeHost", ReferenceExpression.Create($"Port={Endpoint1.Property(EndpointProperty.Port)};Host={Endpoint1.Property(EndpointProperty.Host)};") },
{ "FullAndPartial", ReferenceExpression.Create($"Test1={Endpoint1.Property(EndpointProperty.Scheme)}://{Endpoint1.Property(EndpointProperty.IPV4Host)}:{Endpoint1.Property(EndpointProperty.Port)}/;Test2={Endpoint2.Property(EndpointProperty.Scheme)}://localhost:{Endpoint2.Property(EndpointProperty.Port)}/;") }
};
Expand Down