diff --git a/src/CommunityToolkit.Aspire.Hosting.ActiveMQ/ActiveMQServerResourceBase.cs b/src/CommunityToolkit.Aspire.Hosting.ActiveMQ/ActiveMQServerResourceBase.cs index 992f86a4d..bd4872cf4 100644 --- a/src/CommunityToolkit.Aspire.Hosting.ActiveMQ/ActiveMQServerResourceBase.cs +++ b/src/CommunityToolkit.Aspire.Hosting.ActiveMQ/ActiveMQServerResourceBase.cs @@ -22,13 +22,23 @@ public abstract class ActiveMQServerResourceBase(string name, ParameterResource? /// public ReferenceExpression ConnectionStringExpression => ReferenceExpression.Create( - $"{scheme}://{UserNameReference}:{PasswordParameter}@{PrimaryEndpoint.Property(EndpointProperty.Host)}:{PrimaryEndpoint.Property(EndpointProperty.Port)}"); + $"{scheme}://{UserNameReference}:{PasswordParameter:uri}@{PrimaryEndpoint.Property(EndpointProperty.Host)}:{PrimaryEndpoint.Property(EndpointProperty.Port)}"); /// /// Gets the primary endpoint for the ActiveMQ server. /// public EndpointReference PrimaryEndpoint => _primaryEndpoint ??= new EndpointReference(this, PrimaryEndpointName); + /// + /// Gets the host endpoint reference for this resource. + /// + public EndpointReferenceExpression Host => PrimaryEndpoint.Property(EndpointProperty.Host); + + /// + /// Gets the port endpoint reference for this resource. + /// + public EndpointReferenceExpression Port => PrimaryEndpoint.Property(EndpointProperty.Port); + /// /// Gets the parameter that contains the ActiveMQ server username. /// @@ -49,7 +59,24 @@ public abstract class ActiveMQServerResourceBase(string name, ParameterResource? UserNameParameter is not null ? ReferenceExpression.Create($"{UserNameParameter}") : ReferenceExpression.Create($"{DefaultUserName}"); - + + /// + /// Gets the connection URI expression for the ActiveMQ server. + /// + /// + /// Format: {scheme}://{user}:{password}@{host}:{port}. + /// + public ReferenceExpression UriExpression => ConnectionStringExpression; + + IEnumerable> IResourceWithConnectionString.GetConnectionProperties() + { + yield return new("Host", ReferenceExpression.Create($"{Host}")); + yield return new("Port", ReferenceExpression.Create($"{Port}")); + yield return new("Username", UserNameReference); + yield return new("Password", ReferenceExpression.Create($"{PasswordParameter}")); + yield return new("Uri", UriExpression); + } + private static T ThrowIfNull([NotNull] T? argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null) => argument ?? throw new ArgumentNullException(paramName); } \ No newline at end of file diff --git a/src/CommunityToolkit.Aspire.Hosting.Flagd/FlagdResource.cs b/src/CommunityToolkit.Aspire.Hosting.Flagd/FlagdResource.cs index 1fcf514ba..5f51a9c48 100644 --- a/src/CommunityToolkit.Aspire.Hosting.Flagd/FlagdResource.cs +++ b/src/CommunityToolkit.Aspire.Hosting.Flagd/FlagdResource.cs @@ -24,6 +24,16 @@ public class FlagdResource(string name) : ContainerResource(name), IResourceWith /// public EndpointReference PrimaryEndpoint => _primaryEndpointReference ??= new(this, HttpEndpointName); + /// + /// Gets the host endpoint reference for this resource. + /// + public EndpointReferenceExpression Host => PrimaryEndpoint.Property(EndpointProperty.Host); + + /// + /// Gets the port endpoint reference for this resource. + /// + public EndpointReferenceExpression Port => PrimaryEndpoint.Property(EndpointProperty.Port); + /// /// Gets the health check HTTP endpoint for the flagd server. /// @@ -41,4 +51,19 @@ public class FlagdResource(string name) : ContainerResource(name), IResourceWith ReferenceExpression.Create( $"{PrimaryEndpoint.Property(EndpointProperty.Scheme)}://{PrimaryEndpoint.Property(EndpointProperty.Host)}:{PrimaryEndpoint.Property(EndpointProperty.Port)}" ); + + /// + /// Gets the connection URI expression for the flagd server. + /// + /// + /// Format: http://{host}:{port}. + /// + public ReferenceExpression UriExpression => ConnectionStringExpression; + + IEnumerable> IResourceWithConnectionString.GetConnectionProperties() + { + yield return new("Host", ReferenceExpression.Create($"{Host}")); + yield return new("Port", ReferenceExpression.Create($"{Port}")); + yield return new("Uri", UriExpression); + } } \ No newline at end of file diff --git a/src/CommunityToolkit.Aspire.Hosting.GoFeatureFlag/GoFeatureFlagResource.cs b/src/CommunityToolkit.Aspire.Hosting.GoFeatureFlag/GoFeatureFlagResource.cs index 5d994ddb0..25a7c7994 100644 --- a/src/CommunityToolkit.Aspire.Hosting.GoFeatureFlag/GoFeatureFlagResource.cs +++ b/src/CommunityToolkit.Aspire.Hosting.GoFeatureFlag/GoFeatureFlagResource.cs @@ -18,9 +18,34 @@ public class GoFeatureFlagResource(string name) : ContainerResource(name), IReso /// public EndpointReference PrimaryEndpoint => _primaryEndpoint ??= new(this, PrimaryEndpointName); + /// + /// Gets the host endpoint reference for this resource. + /// + public EndpointReferenceExpression Host => PrimaryEndpoint.Property(EndpointProperty.Host); + + /// + /// Gets the port endpoint reference for this resource. + /// + public EndpointReferenceExpression Port => PrimaryEndpoint.Property(EndpointProperty.Port); + /// /// Gets the connection string expression for the GO Feature Flag instance. /// public ReferenceExpression ConnectionStringExpression => ReferenceExpression.Create($"Endpoint=http://{PrimaryEndpoint.Property(EndpointProperty.Host)}:{PrimaryEndpoint.Property(EndpointProperty.Port)}"); + + /// + /// Gets the connection URI expression for the GO Feature Flag instance. + /// + /// + /// Format: http://{host}:{port}. + /// + public ReferenceExpression UriExpression => ReferenceExpression.Create($"http://{Host}:{Port}"); + + IEnumerable> IResourceWithConnectionString.GetConnectionProperties() + { + yield return new("Host", ReferenceExpression.Create($"{Host}")); + yield return new("Port", ReferenceExpression.Create($"{Port}")); + yield return new("Uri", UriExpression); + } } \ No newline at end of file diff --git a/src/CommunityToolkit.Aspire.Hosting.KurrentDB/KurrentDBResource.cs b/src/CommunityToolkit.Aspire.Hosting.KurrentDB/KurrentDBResource.cs index 334672003..ebd9c191d 100644 --- a/src/CommunityToolkit.Aspire.Hosting.KurrentDB/KurrentDBResource.cs +++ b/src/CommunityToolkit.Aspire.Hosting.KurrentDB/KurrentDBResource.cs @@ -19,10 +19,35 @@ public class KurrentDBResource(string name) : ContainerResource(name), IResource /// public EndpointReference PrimaryEndpoint => _primaryEndpoint ??= new(this, HttpEndpointName); + /// + /// Gets the host endpoint reference for this resource. + /// + public EndpointReferenceExpression Host => PrimaryEndpoint.Property(EndpointProperty.Host); + + /// + /// Gets the port endpoint reference for this resource. + /// + public EndpointReferenceExpression Port => PrimaryEndpoint.Property(EndpointProperty.Port); + /// /// Gets the connection string for the KurrentDB server. /// public ReferenceExpression ConnectionStringExpression => ReferenceExpression.Create( $"kurrentdb://{PrimaryEndpoint.Property(EndpointProperty.Host)}:{PrimaryEndpoint.Property(EndpointProperty.Port)}?tls=false"); + + /// + /// Gets the connection URI expression for the KurrentDB server. + /// + /// + /// Format: kurrentdb://{host}:{port}?tls=false. + /// + public ReferenceExpression UriExpression => ConnectionStringExpression; + + IEnumerable> IResourceWithConnectionString.GetConnectionProperties() + { + yield return new("Host", ReferenceExpression.Create($"{Host}")); + yield return new("Port", ReferenceExpression.Create($"{Port}")); + yield return new("Uri", UriExpression); + } } diff --git a/src/CommunityToolkit.Aspire.Hosting.LavinMQ/LavinMQContainerResource.cs b/src/CommunityToolkit.Aspire.Hosting.LavinMQ/LavinMQContainerResource.cs index dda14f63e..2b3d983c7 100644 --- a/src/CommunityToolkit.Aspire.Hosting.LavinMQ/LavinMQContainerResource.cs +++ b/src/CommunityToolkit.Aspire.Hosting.LavinMQ/LavinMQContainerResource.cs @@ -20,6 +20,16 @@ public class LavinMQContainerResource(string name) private EndpointReference? _primaryEndpoint; private EndpointReference PrimaryEndpoint => _primaryEndpoint ??= new EndpointReference(this, PrimaryEndpointName); + /// + /// Gets the host endpoint reference for this resource. + /// + public EndpointReferenceExpression Host => PrimaryEndpoint.Property(EndpointProperty.Host); + + /// + /// Gets the port endpoint reference for this resource. + /// + public EndpointReferenceExpression Port => PrimaryEndpoint.Property(EndpointProperty.Port); + private static ReferenceExpression UserNameReference => ReferenceExpression.Create($"{DefaultUserName}"); private static ReferenceExpression PasswordReference => ReferenceExpression.Create($"{DefaultPassword}"); @@ -29,4 +39,21 @@ public class LavinMQContainerResource(string name) /// public ReferenceExpression ConnectionStringExpression => ReferenceExpression.Create($"amqp://{UserNameReference}:{PasswordReference}@{PrimaryEndpoint.Property(EndpointProperty.Host)}:{PrimaryEndpoint.Property(EndpointProperty.Port)}/"); + + /// + /// Gets the connection URI expression for the LavinMQ server. + /// + /// + /// Format: amqp://{user}:{password}@{host}:{port}/. + /// + public ReferenceExpression UriExpression => ConnectionStringExpression; + + IEnumerable> IResourceWithConnectionString.GetConnectionProperties() + { + yield return new("Host", ReferenceExpression.Create($"{Host}")); + yield return new("Port", ReferenceExpression.Create($"{Port}")); + yield return new("Username", UserNameReference); + yield return new("Password", PasswordReference); + yield return new("Uri", UriExpression); + } } \ No newline at end of file diff --git a/src/CommunityToolkit.Aspire.Hosting.MailPit/MailPitContainerResource.cs b/src/CommunityToolkit.Aspire.Hosting.MailPit/MailPitContainerResource.cs index 63534cf42..cf6618dc3 100644 --- a/src/CommunityToolkit.Aspire.Hosting.MailPit/MailPitContainerResource.cs +++ b/src/CommunityToolkit.Aspire.Hosting.MailPit/MailPitContainerResource.cs @@ -15,9 +15,34 @@ public class MailPitContainerResource(string name) : ContainerResource(name), IR private EndpointReference? _smtpEndpoint; private EndpointReference SmtpEndpoint => _smtpEndpoint ??= new EndpointReference(this, SmtpEndpointName); + /// + /// Gets the host endpoint reference for the SMTP endpoint. + /// + public EndpointReferenceExpression Host => SmtpEndpoint.Property(EndpointProperty.Host); + + /// + /// Gets the port endpoint reference for the SMTP endpoint. + /// + public EndpointReferenceExpression Port => SmtpEndpoint.Property(EndpointProperty.Port); + /// /// ConnectionString for MailPit smtp endpoint in the form of smtp://host:port. /// public ReferenceExpression ConnectionStringExpression => ReferenceExpression.Create( $"Endpoint={SmtpEndpoint.Scheme}://{SmtpEndpoint.Property(EndpointProperty.Host)}:{SmtpEndpoint.Property(EndpointProperty.Port)}"); + + /// + /// Gets the connection URI expression for the MailPit SMTP endpoint. + /// + /// + /// Format: smtp://{host}:{port}. + /// + public ReferenceExpression UriExpression => ReferenceExpression.Create($"{SmtpEndpoint.Scheme}://{Host}:{Port}"); + + IEnumerable> IResourceWithConnectionString.GetConnectionProperties() + { + yield return new("Host", ReferenceExpression.Create($"{Host}")); + yield return new("Port", ReferenceExpression.Create($"{Port}")); + yield return new("Uri", UriExpression); + } } diff --git a/src/CommunityToolkit.Aspire.Hosting.Meilisearch/MeilisearchResource.cs b/src/CommunityToolkit.Aspire.Hosting.Meilisearch/MeilisearchResource.cs index b4cffb74c..832a9beea 100644 --- a/src/CommunityToolkit.Aspire.Hosting.Meilisearch/MeilisearchResource.cs +++ b/src/CommunityToolkit.Aspire.Hosting.Meilisearch/MeilisearchResource.cs @@ -22,6 +22,16 @@ public MeilisearchResource(string name, ParameterResource masterKey) : base(name /// public EndpointReference PrimaryEndpoint => _primaryEndpoint ??= new(this, PrimaryEndpointName); + /// + /// Gets the host endpoint reference for this resource. + /// + public EndpointReferenceExpression Host => PrimaryEndpoint.Property(EndpointProperty.Host); + + /// + /// Gets the port endpoint reference for this resource. + /// + public EndpointReferenceExpression Port => PrimaryEndpoint.Property(EndpointProperty.Port); + /// /// Gets the parameter that contains the Meilisearch superuser password. /// @@ -32,5 +42,21 @@ public MeilisearchResource(string name, ParameterResource masterKey) : base(name /// public ReferenceExpression ConnectionStringExpression => ReferenceExpression.Create($"Endpoint=http://{PrimaryEndpoint.Property(EndpointProperty.Host)}:{PrimaryEndpoint.Property(EndpointProperty.Port)};MasterKey={MasterKeyParameter}"); + + /// + /// Gets the connection URI expression for the Meilisearch server. + /// + /// + /// Format: http://{host}:{port}. + /// + public ReferenceExpression UriExpression => ReferenceExpression.Create($"http://{Host}:{Port}"); + + IEnumerable> IResourceWithConnectionString.GetConnectionProperties() + { + yield return new("Host", ReferenceExpression.Create($"{Host}")); + yield return new("Port", ReferenceExpression.Create($"{Port}")); + yield return new("MasterKey", ReferenceExpression.Create($"{MasterKeyParameter}")); + yield return new("Uri", UriExpression); + } } diff --git a/src/CommunityToolkit.Aspire.Hosting.Minio/MinioContainerResource.cs b/src/CommunityToolkit.Aspire.Hosting.Minio/MinioContainerResource.cs index 4a964d919..3e51cd0fd 100644 --- a/src/CommunityToolkit.Aspire.Hosting.Minio/MinioContainerResource.cs +++ b/src/CommunityToolkit.Aspire.Hosting.Minio/MinioContainerResource.cs @@ -29,12 +29,30 @@ public sealed class MinioContainerResource(string name, ParameterResource rootUs /// Gets the primary endpoint for the MinIO. This endpoint is used for all API calls over HTTP. /// public EndpointReference PrimaryEndpoint => _primaryEndpoint ??= new(this, PrimaryEndpointName); - + + /// + /// Gets the host endpoint reference for this resource. + /// + public EndpointReferenceExpression Host => PrimaryEndpoint.Property(EndpointProperty.Host); + + /// + /// Gets the port endpoint reference for this resource. + /// + public EndpointReferenceExpression Port => PrimaryEndpoint.Property(EndpointProperty.Port); + /// /// Gets the connection string expression for the Minio /// public ReferenceExpression ConnectionStringExpression => GetConnectionString(); - + + /// + /// Gets the connection URI expression for the MinIO server. + /// + /// + /// Format: http://{host}:{port}. + /// + public ReferenceExpression UriExpression => ReferenceExpression.Create($"http://{Host}:{Port}"); + /// /// Gets the connection string for the MinIO server. /// @@ -49,7 +67,7 @@ public sealed class MinioContainerResource(string name, ParameterResource rootUs return ConnectionStringExpression.GetValueAsync(cancellationToken); } - + /// /// Gets the connection string for the MinIO server. /// @@ -70,4 +88,13 @@ internal void SetPassword(ParameterResource password) { PasswordParameter = password; } + + IEnumerable> IResourceWithConnectionString.GetConnectionProperties() + { + yield return new("Host", ReferenceExpression.Create($"{Host}")); + yield return new("Port", ReferenceExpression.Create($"{Port}")); + yield return new("AccessKey", ReferenceExpression.Create($"{RootUser}")); + yield return new("SecretKey", ReferenceExpression.Create($"{PasswordParameter}")); + yield return new("Uri", UriExpression); + } } \ No newline at end of file diff --git a/src/CommunityToolkit.Aspire.Hosting.Ollama/OllamaModelResource.cs b/src/CommunityToolkit.Aspire.Hosting.Ollama/OllamaModelResource.cs index 7d4ea2dcc..a5612e658 100644 --- a/src/CommunityToolkit.Aspire.Hosting.Ollama/OllamaModelResource.cs +++ b/src/CommunityToolkit.Aspire.Hosting.Ollama/OllamaModelResource.cs @@ -26,6 +26,11 @@ public class OllamaModelResource(string name, string modelName, OllamaResource p /// public string ModelName { get; } = ThrowIfNull(modelName); + IEnumerable> IResourceWithConnectionString.GetConnectionProperties() => + Parent.CombineProperties([ + new("Model", ReferenceExpression.Create($"{ModelName}")) + ]); + private static T ThrowIfNull([NotNull] T? argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null) => argument ?? throw new ArgumentNullException(paramName); } diff --git a/src/CommunityToolkit.Aspire.Hosting.Ollama/OllamaResource.cs b/src/CommunityToolkit.Aspire.Hosting.Ollama/OllamaResource.cs index d980bda1c..73cccf2f7 100644 --- a/src/CommunityToolkit.Aspire.Hosting.Ollama/OllamaResource.cs +++ b/src/CommunityToolkit.Aspire.Hosting.Ollama/OllamaResource.cs @@ -25,6 +25,16 @@ public class OllamaResource(string name) : ContainerResource(name), IResourceWit /// public EndpointReference PrimaryEndpoint => _primaryEndpointReference ??= new(this, OllamaEndpointName); + /// + /// Gets the host endpoint reference for this resource. + /// + public EndpointReferenceExpression Host => PrimaryEndpoint.Property(EndpointProperty.Host); + + /// + /// Gets the port endpoint reference for this resource. + /// + public EndpointReferenceExpression Port => PrimaryEndpoint.Property(EndpointProperty.Port); + /// /// Gets the connection string expression for the Ollama server. /// @@ -33,6 +43,14 @@ public class OllamaResource(string name) : ContainerResource(name), IResourceWit $"Endpoint={PrimaryEndpoint.Property(EndpointProperty.Scheme)}://{PrimaryEndpoint.Property(EndpointProperty.Host)}:{PrimaryEndpoint.Property(EndpointProperty.Port)}" ); + /// + /// Gets the connection URI expression for the Ollama server. + /// + /// + /// Format: http://{host}:{port}. + /// + public ReferenceExpression UriExpression => ReferenceExpression.Create($"{PrimaryEndpoint.Property(EndpointProperty.Scheme)}://{Host}:{Port}"); + /// /// Adds a model to the list of models to download on initial startup. /// @@ -45,4 +63,11 @@ public void AddModel(string modelName) _models.Add(modelName); } } + + IEnumerable> IResourceWithConnectionString.GetConnectionProperties() + { + yield return new("Host", ReferenceExpression.Create($"{Host}")); + yield return new("Port", ReferenceExpression.Create($"{Port}")); + yield return new("Uri", UriExpression); + } } \ No newline at end of file diff --git a/src/CommunityToolkit.Aspire.Hosting.Ollama/OpenWebUIResource.cs b/src/CommunityToolkit.Aspire.Hosting.Ollama/OpenWebUIResource.cs index e62747c08..c010fa859 100644 --- a/src/CommunityToolkit.Aspire.Hosting.Ollama/OpenWebUIResource.cs +++ b/src/CommunityToolkit.Aspire.Hosting.Ollama/OpenWebUIResource.cs @@ -14,6 +14,16 @@ public class OpenWebUIResource(string name) : ContainerResource(name), IResource /// public EndpointReference PrimaryEndpoint => _primaryEndpoint ??= new(this, PrimaryEndpointName); + /// + /// Gets the host endpoint reference for this resource. + /// + public EndpointReferenceExpression Host => PrimaryEndpoint.Property(EndpointProperty.Host); + + /// + /// Gets the port endpoint reference for this resource. + /// + public EndpointReferenceExpression Port => PrimaryEndpoint.Property(EndpointProperty.Port); + /// /// Gets the connection string expression for the Open WebUI endpoint. /// @@ -21,6 +31,14 @@ public class OpenWebUIResource(string name) : ContainerResource(name), IResource ReferenceExpression.Create( $"{PrimaryEndpoint.Property(EndpointProperty.Url)}"); + /// + /// Gets the connection URI expression for the Open WebUI endpoint. + /// + /// + /// Format: http://{host}:{port}. The scheme reflects the endpoint configuration and may be https when TLS is enabled. + /// + public ReferenceExpression UriExpression => ConnectionStringExpression; + private readonly List ollamaResources = []; /// @@ -42,4 +60,11 @@ internal void AddOllamaResource(OllamaResource ollamaResource) ollamaResources.Add(ollamaResource); } + + IEnumerable> IResourceWithConnectionString.GetConnectionProperties() + { + yield return new("Host", ReferenceExpression.Create($"{Host}")); + yield return new("Port", ReferenceExpression.Create($"{Port}")); + yield return new("Uri", UriExpression); + } } \ No newline at end of file diff --git a/src/CommunityToolkit.Aspire.Hosting.PapercutSmtp/PapercutSmtpContainerResource.cs b/src/CommunityToolkit.Aspire.Hosting.PapercutSmtp/PapercutSmtpContainerResource.cs index 398254ebd..8687a0044 100644 --- a/src/CommunityToolkit.Aspire.Hosting.PapercutSmtp/PapercutSmtpContainerResource.cs +++ b/src/CommunityToolkit.Aspire.Hosting.PapercutSmtp/PapercutSmtpContainerResource.cs @@ -13,9 +13,34 @@ public class PapercutSmtpContainerResource(string name) : ContainerResource(name private EndpointReference? _smtpEndpoint; private EndpointReference SmtpEndpoint => _smtpEndpoint ??= new EndpointReference(this, SmtpEndpointName); + /// + /// Gets the host endpoint reference for the SMTP endpoint. + /// + public EndpointReferenceExpression Host => SmtpEndpoint.Property(EndpointProperty.Host); + + /// + /// Gets the port endpoint reference for the SMTP endpoint. + /// + public EndpointReferenceExpression Port => SmtpEndpoint.Property(EndpointProperty.Port); + /// /// ConnectionString for the Papercut SMTP server in the form of smtp://host:port. /// public ReferenceExpression ConnectionStringExpression => ReferenceExpression.Create( $"Endpoint={SmtpEndpoint.Scheme}://{SmtpEndpoint.Property(EndpointProperty.Host)}:{SmtpEndpoint.Property(EndpointProperty.Port)}"); + + /// + /// Gets the connection URI expression for the Papercut SMTP endpoint. + /// + /// + /// Format: smtp://{host}:{port}. + /// + public ReferenceExpression UriExpression => ReferenceExpression.Create($"{SmtpEndpoint.Scheme}://{Host}:{Port}"); + + IEnumerable> IResourceWithConnectionString.GetConnectionProperties() + { + yield return new("Host", ReferenceExpression.Create($"{Host}")); + yield return new("Port", ReferenceExpression.Create($"{Port}")); + yield return new("Uri", UriExpression); + } } diff --git a/src/CommunityToolkit.Aspire.Hosting.RavenDB/RavenDBDatabaseResource.cs b/src/CommunityToolkit.Aspire.Hosting.RavenDB/RavenDBDatabaseResource.cs index fd45acec5..45321b2ee 100644 --- a/src/CommunityToolkit.Aspire.Hosting.RavenDB/RavenDBDatabaseResource.cs +++ b/src/CommunityToolkit.Aspire.Hosting.RavenDB/RavenDBDatabaseResource.cs @@ -24,6 +24,11 @@ public class RavenDBDatabaseResource(string name, string databaseName, RavenDBSe public ReferenceExpression ConnectionStringExpression => ReferenceExpression.Create($"{Parent};Database={DatabaseName}"); + IEnumerable> IResourceWithConnectionString.GetConnectionProperties() => + Parent.CombineProperties([ + new("Database", ReferenceExpression.Create($"{DatabaseName}")) + ]); + private static T ThrowIfNull([NotNull] T? argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null) => argument ?? throw new ArgumentNullException(paramName); } diff --git a/src/CommunityToolkit.Aspire.Hosting.RavenDB/RavenDBServerResource.cs b/src/CommunityToolkit.Aspire.Hosting.RavenDB/RavenDBServerResource.cs index ce4a4e783..bf2da7974 100644 --- a/src/CommunityToolkit.Aspire.Hosting.RavenDB/RavenDBServerResource.cs +++ b/src/CommunityToolkit.Aspire.Hosting.RavenDB/RavenDBServerResource.cs @@ -27,6 +27,16 @@ public class RavenDBServerResource(string name, bool isSecured) : ContainerResou /// public EndpointReference PrimaryEndpoint => _primaryEndpoint ??= new(this, PrimaryEndpointName); + /// + /// Gets the host endpoint reference for this resource. + /// + public EndpointReferenceExpression Host => PrimaryEndpoint.Property(EndpointProperty.Host); + + /// + /// Gets the port endpoint reference for this resource. + /// + public EndpointReferenceExpression Port => PrimaryEndpoint.Property(EndpointProperty.Port); + /// /// Gets the TCP endpoint for the RavenDB server. /// @@ -39,6 +49,14 @@ public class RavenDBServerResource(string name, bool isSecured) : ContainerResou public ReferenceExpression ConnectionStringExpression => ReferenceExpression.Create( $"URL={(IsSecured ? "https://" : "http://")}{PrimaryEndpoint.Property(EndpointProperty.Host)}:{PrimaryEndpoint.Property(EndpointProperty.Port)}"); + /// + /// Gets the connection URI expression for the RavenDB server. + /// + /// + /// Format: http://{host}:{port} or https://{host}:{port} depending on security settings. + /// + public ReferenceExpression UriExpression => ReferenceExpression.Create($"{(IsSecured ? "https://" : "http://")}{Host}:{Port}"); + private readonly Dictionary _databases = new(); /// @@ -56,4 +74,11 @@ internal void AddDatabase(string name, string databaseName) { _databases.TryAdd(name, databaseName); } + + IEnumerable> IResourceWithConnectionString.GetConnectionProperties() + { + yield return new("Host", ReferenceExpression.Create($"{Host}")); + yield return new("Port", ReferenceExpression.Create($"{Port}")); + yield return new("Uri", UriExpression); + } } diff --git a/src/CommunityToolkit.Aspire.Hosting.Solr/SolrResource.cs b/src/CommunityToolkit.Aspire.Hosting.Solr/SolrResource.cs index 714663a0c..7a124852b 100644 --- a/src/CommunityToolkit.Aspire.Hosting.Solr/SolrResource.cs +++ b/src/CommunityToolkit.Aspire.Hosting.Solr/SolrResource.cs @@ -23,10 +23,36 @@ public class SolrResource(string name, string coreName) : ContainerResource(name /// public EndpointReference PrimaryEndpoint => _primaryEndpoint ??= new(this, PrimaryEndpointName); + /// + /// Gets the host endpoint reference for this resource. + /// + public EndpointReferenceExpression Host => PrimaryEndpoint.Property(EndpointProperty.Host); + + /// + /// Gets the port endpoint reference for this resource. + /// + public EndpointReferenceExpression Port => PrimaryEndpoint.Property(EndpointProperty.Port); + /// /// Gets the connection string expression for the Solr server. /// public ReferenceExpression ConnectionStringExpression => ReferenceExpression.Create( $"http://{PrimaryEndpoint.Property(EndpointProperty.Host)}:{PrimaryEndpoint.Property(EndpointProperty.Port)}/solr/{CoreName}"); + /// + /// Gets the connection URI expression for the Solr server. + /// + /// + /// Format: http://{host}:{port}/solr/{coreName}. + /// + public ReferenceExpression UriExpression => ConnectionStringExpression; + + IEnumerable> IResourceWithConnectionString.GetConnectionProperties() + { + yield return new("Host", ReferenceExpression.Create($"{Host}")); + yield return new("Port", ReferenceExpression.Create($"{Port}")); + yield return new("CoreName", ReferenceExpression.Create($"{CoreName}")); + yield return new("Uri", UriExpression); + } + } \ No newline at end of file diff --git a/src/CommunityToolkit.Aspire.Hosting.Sqlite/SqliteResource.cs b/src/CommunityToolkit.Aspire.Hosting.Sqlite/SqliteResource.cs index 5da7586db..2f55fac21 100644 --- a/src/CommunityToolkit.Aspire.Hosting.Sqlite/SqliteResource.cs +++ b/src/CommunityToolkit.Aspire.Hosting.Sqlite/SqliteResource.cs @@ -16,5 +16,10 @@ public class SqliteResource(string name, string databasePath, string databaseFil /// public ReferenceExpression ConnectionStringExpression => ReferenceExpression.Create($"Data Source={DatabaseFilePath};Cache=Shared;Mode=ReadWriteCreate"); + + IEnumerable> IResourceWithConnectionString.GetConnectionProperties() + { + yield return new("DataSource", ReferenceExpression.Create($"{DatabaseFilePath}")); + } } diff --git a/src/CommunityToolkit.Aspire.Hosting.Sqlite/SqliteWebResource.cs b/src/CommunityToolkit.Aspire.Hosting.Sqlite/SqliteWebResource.cs index 2d14a2a12..140e0256b 100644 --- a/src/CommunityToolkit.Aspire.Hosting.Sqlite/SqliteWebResource.cs +++ b/src/CommunityToolkit.Aspire.Hosting.Sqlite/SqliteWebResource.cs @@ -15,10 +15,35 @@ public class SqliteWebResource(string name) : ContainerResource(name), IResource /// public EndpointReference PrimaryEndpoint => _primaryEndpoint ??= new(this, PrimaryEndpointName); + /// + /// Gets the host endpoint reference for this resource. + /// + public EndpointReferenceExpression Host => PrimaryEndpoint.Property(EndpointProperty.Host); + + /// + /// Gets the port endpoint reference for this resource. + /// + public EndpointReferenceExpression Port => PrimaryEndpoint.Property(EndpointProperty.Port); + /// /// Gets the connection string expression for the Open WebUI endpoint. /// public ReferenceExpression ConnectionStringExpression => ReferenceExpression.Create( $"{PrimaryEndpoint.Property(EndpointProperty.Url)}"); + + /// + /// Gets the connection URI expression for the Sqlite Web endpoint. + /// + /// + /// Format: http://{host}:{port}. The scheme reflects the endpoint configuration and may be https when TLS is enabled. + /// + public ReferenceExpression UriExpression => ConnectionStringExpression; + + IEnumerable> IResourceWithConnectionString.GetConnectionProperties() + { + yield return new("Host", ReferenceExpression.Create($"{Host}")); + yield return new("Port", ReferenceExpression.Create($"{Port}")); + yield return new("Uri", UriExpression); + } } \ No newline at end of file diff --git a/src/CommunityToolkit.Aspire.Hosting.SurrealDb/SurrealDbDatabaseResource.cs b/src/CommunityToolkit.Aspire.Hosting.SurrealDb/SurrealDbDatabaseResource.cs index 247a714bd..aa3946f77 100644 --- a/src/CommunityToolkit.Aspire.Hosting.SurrealDb/SurrealDbDatabaseResource.cs +++ b/src/CommunityToolkit.Aspire.Hosting.SurrealDb/SurrealDbDatabaseResource.cs @@ -42,4 +42,9 @@ SurrealDbNamespaceResource parent DatabaseName = databaseName; Parent = parent; } + + IEnumerable> IResourceWithConnectionString.GetConnectionProperties() => + Parent.CombineProperties([ + new("Database", ReferenceExpression.Create($"{DatabaseName}")) + ]); } \ No newline at end of file diff --git a/src/CommunityToolkit.Aspire.Hosting.SurrealDb/SurrealDbNamespaceResource.cs b/src/CommunityToolkit.Aspire.Hosting.SurrealDb/SurrealDbNamespaceResource.cs index 223053471..d35dc21f4 100644 --- a/src/CommunityToolkit.Aspire.Hosting.SurrealDb/SurrealDbNamespaceResource.cs +++ b/src/CommunityToolkit.Aspire.Hosting.SurrealDb/SurrealDbNamespaceResource.cs @@ -54,4 +54,9 @@ internal void AddDatabase(string name, string databaseName) { _databases.TryAdd(name, databaseName); } + + IEnumerable> IResourceWithConnectionString.GetConnectionProperties() => + Parent.CombineProperties([ + new("Namespace", ReferenceExpression.Create($"{NamespaceName}")) + ]); } \ No newline at end of file diff --git a/src/CommunityToolkit.Aspire.Hosting.SurrealDb/SurrealDbServerResource.cs b/src/CommunityToolkit.Aspire.Hosting.SurrealDb/SurrealDbServerResource.cs index 98b5da2c8..0c2e1e41a 100644 --- a/src/CommunityToolkit.Aspire.Hosting.SurrealDb/SurrealDbServerResource.cs +++ b/src/CommunityToolkit.Aspire.Hosting.SurrealDb/SurrealDbServerResource.cs @@ -20,8 +20,8 @@ public class SurrealDbServerResource : ContainerResource, IResourceWithConnectio /// A parameter that contains the SurrealDB username. /// A parameter that contains the SurrealDB password. public SurrealDbServerResource( - [ResourceName] string name, - ParameterResource? userName, + [ResourceName] string name, + ParameterResource? userName, ParameterResource password ) : base(name) { @@ -37,6 +37,16 @@ ParameterResource password /// public EndpointReference PrimaryEndpoint { get; } + /// + /// Gets the host endpoint reference for this resource. + /// + public EndpointReferenceExpression Host => PrimaryEndpoint.Property(EndpointProperty.Host); + + /// + /// Gets the port endpoint reference for this resource. + /// + public EndpointReferenceExpression Port => PrimaryEndpoint.Property(EndpointProperty.Port); + /// /// Gets the parameter that contains the SurrealDB username. /// @@ -54,7 +64,7 @@ UserNameParameter is not null ? private ReferenceExpression ConnectionString => ReferenceExpression.Create( - $"Server={SchemeUri}://{PrimaryEndpoint.Property(EndpointProperty.Host)}:{PrimaryEndpoint.Property(EndpointProperty.Port)}/rpc;User={UserNameReference};Password='{PasswordParameter}'"); + $"Server={SchemeUri}://{PrimaryEndpoint.Property(EndpointProperty.Host)}:{PrimaryEndpoint.Property(EndpointProperty.Port)}/rpc;User={UserNameReference};Password={PasswordParameter}"); /// /// Gets the connection string expression for the SurrealDB instance. @@ -72,6 +82,14 @@ public ReferenceExpression ConnectionStringExpression } } + /// + /// Gets the connection URI expression for the SurrealDB instance. + /// + /// + /// Format: ws://{host}:{port}/rpc. + /// + public ReferenceExpression UriExpression => ReferenceExpression.Create($"{SchemeUri}://{Host}:{Port}/rpc"); + /// /// Gets the connection string for the SurrealDB instance. /// @@ -98,4 +116,13 @@ internal void AddNamespace(string name, string namespaceName) { _namespaces.TryAdd(name, namespaceName); } + + IEnumerable> IResourceWithConnectionString.GetConnectionProperties() + { + yield return new("Host", ReferenceExpression.Create($"{Host}")); + yield return new("Port", ReferenceExpression.Create($"{Port}")); + yield return new("Username", UserNameReference); + yield return new("Password", ReferenceExpression.Create($"{PasswordParameter:uri}")); + yield return new("Uri", UriExpression); + } } \ No newline at end of file diff --git a/tests/CommunityToolkit.Aspire.Hosting.Minio.Tests/MinioPublicApiTests.cs b/tests/CommunityToolkit.Aspire.Hosting.Minio.Tests/MinioPublicApiTests.cs index ff4ebc97e..ec8899ee5 100644 --- a/tests/CommunityToolkit.Aspire.Hosting.Minio.Tests/MinioPublicApiTests.cs +++ b/tests/CommunityToolkit.Aspire.Hosting.Minio.Tests/MinioPublicApiTests.cs @@ -12,25 +12,25 @@ public void AddMinioContainerShouldThrowWhenBuilderIsNull() { IDistributedApplicationBuilder builder = null!; const string name = "Minio"; - + var action = () => builder.AddMinioContainer(name); - + var exception = Assert.Throws(action); Assert.Equal(nameof(builder), exception.ParamName); } - + [Fact] public void AddMinioContainerShouldThrowWhenNameIsNull() { IDistributedApplicationBuilder builder = new DistributedApplicationBuilder([]); string name = null!; - + var action = () => builder.AddMinioContainer(name); - + var exception = Assert.Throws(action); Assert.Equal(nameof(name), exception.ParamName); } - + [Theory] [InlineData(false)] [InlineData(true)] @@ -68,7 +68,7 @@ public void WithDataBindMountShouldThrowWhenSourceIsNull() var exception = Assert.Throws(action); Assert.Equal(nameof(source), exception.ParamName); } - + [Fact] public void VerifyMinioContainerResourceWithHostPort() { @@ -92,7 +92,7 @@ public async Task VerifyMinioContainerResourceWithPassword() .WithEndpoint("http", e => e.AllocatedEndpoint = new AllocatedEndpoint(e, "localhost", 2000)); var connectionString = await minio.Resource.GetConnectionStringAsync(); - Assert.Equal("Endpoint=http://localhost:2000;AccessKey=minioadmin;SecretKey=p@ssw0rd1", connectionString); + Assert.Equal(await ReferenceExpression.Create($"Endpoint=http://localhost:2000;AccessKey=minioadmin;SecretKey={password}").GetValueAsync(CancellationToken.None), connectionString); } [Fact] diff --git a/tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests/AddSurrealServerTests.cs b/tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests/AddSurrealServerTests.cs index f4486872f..c2f2f901f 100644 --- a/tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests/AddSurrealServerTests.cs +++ b/tests/CommunityToolkit.Aspire.Hosting.SurrealDb.Tests/AddSurrealServerTests.cs @@ -34,16 +34,16 @@ public void AddSurrealServerDoesNotAddGeneratedPasswordParameterWithUserSecretsP public async Task AddSurrealServerContainerWithDefaultsAddsAnnotationMetadata() { var appBuilder = DistributedApplication.CreateBuilder(); - + var surrealServer = appBuilder.AddSurrealServer("surreal"); - + using var app = appBuilder.Build(); - + var appModel = app.Services.GetRequiredService(); - + var containerResource = Assert.Single(appModel.Resources.OfType()); Assert.Equal("surreal", containerResource.Name); - + var endpoint = Assert.Single(containerResource.Annotations.OfType()); Assert.Equal(8000, endpoint.TargetPort); Assert.False(endpoint.IsExternal); @@ -52,12 +52,12 @@ public async Task AddSurrealServerContainerWithDefaultsAddsAnnotationMetadata() Assert.Equal(ProtocolType.Tcp, endpoint.Protocol); Assert.Equal("tcp", endpoint.Transport); Assert.Equal("tcp", endpoint.UriScheme); - + var containerAnnotation = Assert.Single(containerResource.Annotations.OfType()); Assert.Equal(SurrealDbContainerImageTags.Tag + "-dev", containerAnnotation.Tag); Assert.Equal(SurrealDbContainerImageTags.Image, containerAnnotation.Image); Assert.Equal(SurrealDbContainerImageTags.Registry, containerAnnotation.Registry); - + var config = await surrealServer.Resource.GetEnvironmentVariableValuesAsync(); Assert.Collection(config, @@ -78,7 +78,8 @@ public async Task AddSurrealServerContainerWithDefaultsAddsAnnotationMetadata() public async Task SurrealServerCreatesConnectionString() { var appBuilder = DistributedApplication.CreateBuilder(); - appBuilder.Configuration["Parameters:pass"] = "p@ssw0rd1"; + var password = "p@ssw0rd1"; + appBuilder.Configuration["Parameters:pass"] = password; var pass = appBuilder.AddParameter("pass"); appBuilder @@ -92,15 +93,16 @@ public async Task SurrealServerCreatesConnectionString() var connectionStringResource = Assert.Single(appModel.Resources.OfType()); var connectionString = await connectionStringResource.GetConnectionStringAsync(default); - Assert.Equal("Server=ws://localhost:8000/rpc;User=root;Password='p@ssw0rd1'", connectionString); - Assert.Equal("Server=ws://{surreal.bindings.tcp.host}:{surreal.bindings.tcp.port}/rpc;User=root;Password='{pass.value}'", connectionStringResource.ConnectionStringExpression.ValueExpression); + Assert.Equal(await ReferenceExpression.Create($"Server=ws://localhost:8000/rpc;User=root;Password={password}").GetValueAsync(CancellationToken.None), connectionString); + Assert.Equal("Server=ws://{surreal.bindings.tcp.host}:{surreal.bindings.tcp.port}/rpc;User=root;Password={pass.value}", connectionStringResource.ConnectionStringExpression.ValueExpression); } [Fact] public async Task SurrealServerDatabaseCreatesConnectionString() { var appBuilder = DistributedApplication.CreateBuilder(); - appBuilder.Configuration["Parameters:pass"] = "p@ssw0rd1"; + var password = "p@ssw0rd1"; + appBuilder.Configuration["Parameters:pass"] = password; var pass = appBuilder.AddParameter("pass"); appBuilder @@ -117,7 +119,7 @@ public async Task SurrealServerDatabaseCreatesConnectionString() var connectionStringResource = (IResourceWithConnectionString)surrealResource; var connectionString = await connectionStringResource.GetConnectionStringAsync(); - Assert.Equal("Server=ws://localhost:8000/rpc;User=root;Password='p@ssw0rd1';Namespace=myns;Database=mydb", connectionString); + Assert.Equal(await ReferenceExpression.Create($"Server=ws://localhost:8000/rpc;User=root;Password={password};Namespace=myns;Database=mydb").GetValueAsync(CancellationToken.None), connectionString); Assert.Equal("{ns.connectionString};Database=mydb", connectionStringResource.ConnectionStringExpression.ValueExpression); } @@ -181,7 +183,7 @@ public void CanAddDatabasesWithTheSameNameOnMultipleServers() Assert.Equal("{ns1.connectionString};Database=imports", db1.Resource.ConnectionStringExpression.ValueExpression); Assert.Equal("{ns2.connectionString};Database=imports", db2.Resource.ConnectionStringExpression.ValueExpression); } - + [Theory] [InlineData(LogLevel.Trace, "trace")] [InlineData(LogLevel.Debug, "debug")] @@ -193,17 +195,17 @@ public void CanAddDatabasesWithTheSameNameOnMultipleServers() public async Task AddSurrealServerContainerWithLogLevel(LogLevel logLevel, string expected) { var appBuilder = DistributedApplication.CreateBuilder(); - + var surrealServer = appBuilder .AddSurrealServer("surreal") .WithLogLevel(logLevel); - + using var app = appBuilder.Build(); - + var config = await surrealServer.Resource.GetEnvironmentVariableValuesAsync(); bool hasValue = config.TryGetValue("SURREAL_LOG", out var value); - + Assert.True(hasValue); Assert.Equal(expected, value); }