diff --git a/src/Aspire.Hosting.Redis/RedisBuilderExtensions.cs b/src/Aspire.Hosting.Redis/RedisBuilderExtensions.cs index c98e403e3a5..60e1d65fe98 100644 --- a/src/Aspire.Hosting.Redis/RedisBuilderExtensions.cs +++ b/src/Aspire.Hosting.Redis/RedisBuilderExtensions.cs @@ -417,14 +417,13 @@ public static IResourceBuilder WithDataBindMount(this IRes /// Configures the password that the Redis resource is used. /// /// The resource builder. - /// The parameter used to provide the password for the Redis resource. + /// The parameter used to provide the password for the Redis resource. If , no password will be configured. /// The . - public static IResourceBuilder WithPassword(this IResourceBuilder builder, IResourceBuilder password) + public static IResourceBuilder WithPassword(this IResourceBuilder builder, IResourceBuilder? password) { ArgumentNullException.ThrowIfNull(builder); - ArgumentNullException.ThrowIfNull(password); - builder.Resource.SetPassword(password.Resource); + builder.Resource.SetPassword(password?.Resource); return builder; } diff --git a/src/Aspire.Hosting.Redis/RedisResource.cs b/src/Aspire.Hosting.Redis/RedisResource.cs index 2d3769de7ba..e2cc9df9ac8 100644 --- a/src/Aspire.Hosting.Redis/RedisResource.cs +++ b/src/Aspire.Hosting.Redis/RedisResource.cs @@ -77,10 +77,8 @@ public ReferenceExpression ConnectionStringExpression return BuildConnectionString().GetValueAsync(cancellationToken); } - internal void SetPassword(ParameterResource password) + internal void SetPassword(ParameterResource? password) { - ArgumentNullException.ThrowIfNull(password); - PasswordParameter = password; } } diff --git a/tests/Aspire.Hosting.Redis.Tests/AddRedisTests.cs b/tests/Aspire.Hosting.Redis.Tests/AddRedisTests.cs index 53c539abff0..302434bc4e2 100644 --- a/tests/Aspire.Hosting.Redis.Tests/AddRedisTests.cs +++ b/tests/Aspire.Hosting.Redis.Tests/AddRedisTests.cs @@ -128,7 +128,7 @@ public async Task RedisCreatesConnectionStringWithDefaultPassword() } [Fact] - public async Task VerifyWithoutPasswordManifest() + public async Task VerifyDefaultManifest() { using var builder = TestDistributedApplicationBuilder.Create(); var redis = builder.AddRedis("redis"); @@ -161,6 +161,37 @@ public async Task VerifyWithoutPasswordManifest() Assert.Equal(expectedManifest, manifest.ToString()); } + [Fact] + public async Task VerifyWithoutPasswordManifest() + { + using var builder = TestDistributedApplicationBuilder.Create(); + var redis = builder.AddRedis("redis").WithPassword(null); + + var manifest = await ManifestUtils.GetManifest(redis.Resource); + + var expectedManifest = $$""" + { + "type": "container.v0", + "connectionString": "{redis.bindings.tcp.host}:{redis.bindings.tcp.port}", + "image": "{{RedisContainerImageTags.Registry}}/{{RedisContainerImageTags.Image}}:{{RedisContainerImageTags.Tag}}", + "entrypoint": "/bin/sh", + "args": [ + "-c", + "redis-server" + ], + "bindings": { + "tcp": { + "scheme": "tcp", + "protocol": "tcp", + "transport": "tcp", + "targetPort": 6379 + } + } + } + """; + Assert.Equal(expectedManifest, manifest.ToString()); + } + [Fact] public async Task VerifyWithPasswordManifest() { @@ -260,6 +291,7 @@ public async Task WithRedisInsightProducesCorrectEnvironmentVariables() var builder = DistributedApplication.CreateBuilder(); var redis1 = builder.AddRedis("myredis1").WithRedisInsight(); var redis2 = builder.AddRedis("myredis2").WithRedisInsight(); + var redis3 = builder.AddRedis("myredis3").WithRedisInsight().WithPassword(null); using var app = builder.Build(); // Add fake allocated endpoints. @@ -311,6 +343,21 @@ public async Task WithRedisInsightProducesCorrectEnvironmentVariables() { Assert.Equal("RI_REDIS_PASSWORD2", item.Key); Assert.Equal(redis2.Resource.PasswordParameter!.Value, item.Value); + }, + (item) => + { + Assert.Equal("RI_REDIS_HOST3", item.Key); + Assert.Equal(redis3.Resource.Name, item.Value); + }, + (item) => + { + Assert.Equal("RI_REDIS_PORT3", item.Key); + Assert.Equal($"{redis3.Resource.PrimaryEndpoint.TargetPort!.Value}", item.Value); + }, + (item) => + { + Assert.Equal("RI_REDIS_ALIAS3", item.Key); + Assert.Equal(redis3.Resource.Name, item.Value); }); } @@ -391,26 +438,44 @@ public void VerifyRedisResourceWithHostPort() Assert.Equal(1000, endpoint.Port); } - [Fact] - public async Task VerifyRedisResourceWithPassword() + [Theory] + [InlineData(false)] + [InlineData(true)] + public async Task VerifyRedisResourceWithPassword(bool withPassword) { using var builder = TestDistributedApplicationBuilder.Create(); - var password = "p@ssw0rd1"; - var pass = builder.AddParameter("pass", password); var redis = builder .AddRedis("myRedis") - .WithPassword(pass) .WithEndpoint("tcp", e => e.AllocatedEndpoint = new AllocatedEndpoint(e, "localhost", 5001)); + var password = "p@ssw0rd1"; + if (withPassword) + { + var pass = builder.AddParameter("pass", password); + redis.WithPassword(pass); + } + else + { + redis.WithPassword(null); + } + using var app = builder.Build(); var appModel = app.Services.GetRequiredService(); var containerResource = Assert.Single(appModel.Resources.OfType()); var connectionStringResource = Assert.Single(appModel.Resources.OfType()); var connectionString = await connectionStringResource.GetConnectionStringAsync(default); - Assert.Equal("{myRedis.bindings.tcp.host}:{myRedis.bindings.tcp.port},password={pass.value}", connectionStringResource.ConnectionStringExpression.ValueExpression); - Assert.StartsWith($"localhost:5001,password={password}", connectionString); + if (withPassword) + { + Assert.Equal("{myRedis.bindings.tcp.host}:{myRedis.bindings.tcp.port},password={pass.value}", connectionStringResource.ConnectionStringExpression.ValueExpression); + Assert.Equal($"localhost:5001,password={password}", connectionString); + } + else + { + Assert.Equal("{myRedis.bindings.tcp.host}:{myRedis.bindings.tcp.port}", connectionStringResource.ConnectionStringExpression.ValueExpression); + Assert.Equal($"localhost:5001", connectionString); + } } [Fact] diff --git a/tests/Aspire.Hosting.Redis.Tests/RedisFunctionalTests.cs b/tests/Aspire.Hosting.Redis.Tests/RedisFunctionalTests.cs index b7a09e3855c..beb3616c2d5 100644 --- a/tests/Aspire.Hosting.Redis.Tests/RedisFunctionalTests.cs +++ b/tests/Aspire.Hosting.Redis.Tests/RedisFunctionalTests.cs @@ -136,6 +136,7 @@ public async Task VerifyWithRedisInsightImportDatabases() IResourceBuilder? redisInsightBuilder = null; var redis2 = builder.AddRedis("redis-2").WithRedisInsight(c => redisInsightBuilder = c); Assert.NotNull(redisInsightBuilder); + var redis3 = builder.AddRedis("redis-3").WithPassword(null); using var app = builder.Build(); @@ -169,13 +170,19 @@ public async Task VerifyWithRedisInsightImportDatabases() Assert.Equal(redis2.Resource.Name, db.Name); Assert.Equal(redis2.Resource.Name, db.Host); Assert.Equal(redis2.Resource.PrimaryEndpoint.TargetPort, db.Port); + }, + db => + { + Assert.Equal(redis3.Resource.Name, db.Name); + Assert.Equal(redis3.Resource.Name, db.Host); + Assert.Equal(redis3.Resource.PrimaryEndpoint.TargetPort, db.Port); }); foreach (var db in databases) { var cts2 = new CancellationTokenSource(TimeSpan.FromSeconds(2)); - var testConnectionResponse = await client.GetAsync($"/api/databases/test/{db.Id}", cts2.Token); - response.EnsureSuccessStatusCode(); + var testConnectionResponse = await client.GetAsync($"/api/databases/{db.Id}/connect", cts2.Token); + testConnectionResponse.EnsureSuccessStatusCode(); } }