From ca6d1398922426768300bafc8d5be53461c25d39 Mon Sep 17 00:00:00 2001 From: Alireza Baloochi Date: Tue, 13 May 2025 14:12:29 +0330 Subject: [PATCH 1/9] Accept null value in Redis WithPassword to ensure password dosen't in redis-server --- .../RedisBuilderExtensions.cs | 5 +- src/Aspire.Hosting.Redis/RedisResource.cs | 4 +- .../AddRedisTests.cs | 81 +++++++++++++++++-- .../RedisFunctionalTests.cs | 7 ++ 4 files changed, 83 insertions(+), 14 deletions(-) diff --git a/src/Aspire.Hosting.Redis/RedisBuilderExtensions.cs b/src/Aspire.Hosting.Redis/RedisBuilderExtensions.cs index c98e403e3a5..1030649468d 100644 --- a/src/Aspire.Hosting.Redis/RedisBuilderExtensions.cs +++ b/src/Aspire.Hosting.Redis/RedisBuilderExtensions.cs @@ -419,12 +419,11 @@ public static IResourceBuilder WithDataBindMount(this IRes /// The resource builder. /// The parameter used to provide the password for the Redis resource. /// 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..da5913db8de 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},password={redis-password.value}", + "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("myredis2").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(redis2.Resource.Name, item.Value); + }, + (item) => + { + Assert.Equal("RI_REDIS_PORT3", item.Key); + Assert.Equal($"{redis2.Resource.PrimaryEndpoint.TargetPort!.Value}", item.Value); + }, + (item) => + { + Assert.Equal("RI_REDIS_ALIAS3", item.Key); + Assert.Equal(redis2.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..30d288c9b70 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(); @@ -165,6 +166,12 @@ public async Task VerifyWithRedisInsightImportDatabases() Assert.Equal(redis1.Resource.PrimaryEndpoint.TargetPort, db.Port); }, db => + { + 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(redis2.Resource.Name, db.Name); Assert.Equal(redis2.Resource.Name, db.Host); From 9ff939f430cb74abcfd300058c576259e8f5bbaa Mon Sep 17 00:00:00 2001 From: Alireza Baloochi Date: Tue, 13 May 2025 14:17:06 +0330 Subject: [PATCH 2/9] Update tests/Aspire.Hosting.Redis.Tests/AddRedisTests.cs --- tests/Aspire.Hosting.Redis.Tests/AddRedisTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Aspire.Hosting.Redis.Tests/AddRedisTests.cs b/tests/Aspire.Hosting.Redis.Tests/AddRedisTests.cs index da5913db8de..96bc3149970 100644 --- a/tests/Aspire.Hosting.Redis.Tests/AddRedisTests.cs +++ b/tests/Aspire.Hosting.Redis.Tests/AddRedisTests.cs @@ -291,7 +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("myredis2").WithRedisInsight().WithPassword(null); + var redis3 = builder.AddRedis("myredis3").WithRedisInsight().WithPassword(null); using var app = builder.Build(); // Add fake allocated endpoints. From 6d8189f99d2550fd0a9cf8e238ec657d39bbba21 Mon Sep 17 00:00:00 2001 From: Alireza Baloochi Date: Tue, 13 May 2025 14:18:19 +0330 Subject: [PATCH 3/9] Apply suggestions from code review --- tests/Aspire.Hosting.Redis.Tests/AddRedisTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Aspire.Hosting.Redis.Tests/AddRedisTests.cs b/tests/Aspire.Hosting.Redis.Tests/AddRedisTests.cs index 96bc3149970..31ce07ed879 100644 --- a/tests/Aspire.Hosting.Redis.Tests/AddRedisTests.cs +++ b/tests/Aspire.Hosting.Redis.Tests/AddRedisTests.cs @@ -347,17 +347,17 @@ public async Task WithRedisInsightProducesCorrectEnvironmentVariables() (item) => { Assert.Equal("RI_REDIS_HOST3", item.Key); - Assert.Equal(redis2.Resource.Name, item.Value); + Assert.Equal(redis3.Resource.Name, item.Value); }, (item) => { Assert.Equal("RI_REDIS_PORT3", item.Key); - Assert.Equal($"{redis2.Resource.PrimaryEndpoint.TargetPort!.Value}", item.Value); + Assert.Equal($"{redis3.Resource.PrimaryEndpoint.TargetPort!.Value}", item.Value); }, (item) => { Assert.Equal("RI_REDIS_ALIAS3", item.Key); - Assert.Equal(redis2.Resource.Name, item.Value); + Assert.Equal(redis3.Resource.Name, item.Value); }); } From 7d11149014a2bfb49e07d094837ea412f5505d6b Mon Sep 17 00:00:00 2001 From: Alireza Baloochi Date: Tue, 13 May 2025 14:48:07 +0330 Subject: [PATCH 4/9] Fix manifest --- playground/Redis/Redis.AppHost/Program.cs | 1 + tests/Aspire.Hosting.Redis.Tests/AddRedisTests.cs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/playground/Redis/Redis.AppHost/Program.cs b/playground/Redis/Redis.AppHost/Program.cs index caa7d08b6fb..a91af3b64fe 100644 --- a/playground/Redis/Redis.AppHost/Program.cs +++ b/playground/Redis/Redis.AppHost/Program.cs @@ -1,6 +1,7 @@ var builder = DistributedApplication.CreateBuilder(args); var redis = builder.AddRedis("redis"); +var redis2 = builder.AddRedis("redis2").WithPassword(null); redis.WithDataVolume() .WithRedisCommander(c => c.WithHostPort(33803).WithParentRelationship(redis)) .WithRedisInsight(c => c.WithHostPort(41567).WithParentRelationship(redis)); diff --git a/tests/Aspire.Hosting.Redis.Tests/AddRedisTests.cs b/tests/Aspire.Hosting.Redis.Tests/AddRedisTests.cs index da5913db8de..ffbd6c53350 100644 --- a/tests/Aspire.Hosting.Redis.Tests/AddRedisTests.cs +++ b/tests/Aspire.Hosting.Redis.Tests/AddRedisTests.cs @@ -172,12 +172,12 @@ public async Task VerifyWithoutPasswordManifest() var expectedManifest = $$""" { "type": "container.v0", - "connectionString": "{redis.bindings.tcp.host}:{redis.bindings.tcp.port},password={redis-password.value}", + "connectionString": "{redis.bindings.tcp.host}:{redis.bindings.tcp.port}", "image": "{{RedisContainerImageTags.Registry}}/{{RedisContainerImageTags.Image}}:{{RedisContainerImageTags.Tag}}", "entrypoint": "/bin/sh", "args": [ "-c", - "redis-server + "redis-server" ], "bindings": { "tcp": { From 6fd26c0bcec92ae290f7f47b56e459ac540ced9d Mon Sep 17 00:00:00 2001 From: Alireza Baloochi Date: Tue, 13 May 2025 14:54:48 +0330 Subject: [PATCH 5/9] fix redis-insight test --- .../Aspire.Hosting.Redis.Tests/RedisFunctionalTests.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/Aspire.Hosting.Redis.Tests/RedisFunctionalTests.cs b/tests/Aspire.Hosting.Redis.Tests/RedisFunctionalTests.cs index 30d288c9b70..beb3616c2d5 100644 --- a/tests/Aspire.Hosting.Redis.Tests/RedisFunctionalTests.cs +++ b/tests/Aspire.Hosting.Redis.Tests/RedisFunctionalTests.cs @@ -173,16 +173,16 @@ public async Task VerifyWithRedisInsightImportDatabases() }, db => { - Assert.Equal(redis2.Resource.Name, db.Name); - Assert.Equal(redis2.Resource.Name, db.Host); - Assert.Equal(redis2.Resource.PrimaryEndpoint.TargetPort, db.Port); + 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(); } } From 5cd6d29b72fb818b6d99d5673d16859ca228e9f2 Mon Sep 17 00:00:00 2001 From: Alireza Baloochi Date: Tue, 13 May 2025 14:55:20 +0330 Subject: [PATCH 6/9] Update playground app manifest --- .../Redis/Redis.AppHost/aspire-manifest.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/playground/Redis/Redis.AppHost/aspire-manifest.json b/playground/Redis/Redis.AppHost/aspire-manifest.json index c90e1593b07..33d609c7fad 100644 --- a/playground/Redis/Redis.AppHost/aspire-manifest.json +++ b/playground/Redis/Redis.AppHost/aspire-manifest.json @@ -29,6 +29,24 @@ } } }, + "redis2": { + "type": "container.v0", + "connectionString": "{redis2.bindings.tcp.host}:{redis2.bindings.tcp.port}", + "image": "docker.io/library/redis:7.4", + "entrypoint": "/bin/sh", + "args": [ + "-c", + "redis-server" + ], + "bindings": { + "tcp": { + "scheme": "tcp", + "protocol": "tcp", + "transport": "tcp", + "targetPort": 6379 + } + } + }, "garnet": { "type": "container.v0", "connectionString": "{garnet.bindings.tcp.host}:{garnet.bindings.tcp.port},password={garnet-password.value}", From ad44a2a72063809502732a40e7eff757848dcfb9 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Tue, 13 May 2025 07:10:55 -0700 Subject: [PATCH 7/9] Update playground/Redis/Redis.AppHost/Program.cs Co-authored-by: Eric Erhardt --- playground/Redis/Redis.AppHost/Program.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/playground/Redis/Redis.AppHost/Program.cs b/playground/Redis/Redis.AppHost/Program.cs index a91af3b64fe..caa7d08b6fb 100644 --- a/playground/Redis/Redis.AppHost/Program.cs +++ b/playground/Redis/Redis.AppHost/Program.cs @@ -1,7 +1,6 @@ var builder = DistributedApplication.CreateBuilder(args); var redis = builder.AddRedis("redis"); -var redis2 = builder.AddRedis("redis2").WithPassword(null); redis.WithDataVolume() .WithRedisCommander(c => c.WithHostPort(33803).WithParentRelationship(redis)) .WithRedisInsight(c => c.WithHostPort(41567).WithParentRelationship(redis)); From b60ccc2e57a9b47fef0e93027a0df5a607dc2a07 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Tue, 13 May 2025 07:11:29 -0700 Subject: [PATCH 8/9] Update src/Aspire.Hosting.Redis/RedisBuilderExtensions.cs Co-authored-by: Eric Erhardt --- src/Aspire.Hosting.Redis/RedisBuilderExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Aspire.Hosting.Redis/RedisBuilderExtensions.cs b/src/Aspire.Hosting.Redis/RedisBuilderExtensions.cs index 1030649468d..60e1d65fe98 100644 --- a/src/Aspire.Hosting.Redis/RedisBuilderExtensions.cs +++ b/src/Aspire.Hosting.Redis/RedisBuilderExtensions.cs @@ -417,7 +417,7 @@ 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) { From 4ef74de4d418310f28970ea659f6b6c4cdce8b13 Mon Sep 17 00:00:00 2001 From: Alireza Baloochi Date: Tue, 13 May 2025 17:46:10 +0330 Subject: [PATCH 9/9] Revert manifest changes --- .../Redis/Redis.AppHost/aspire-manifest.json | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/playground/Redis/Redis.AppHost/aspire-manifest.json b/playground/Redis/Redis.AppHost/aspire-manifest.json index 33d609c7fad..c90e1593b07 100644 --- a/playground/Redis/Redis.AppHost/aspire-manifest.json +++ b/playground/Redis/Redis.AppHost/aspire-manifest.json @@ -29,24 +29,6 @@ } } }, - "redis2": { - "type": "container.v0", - "connectionString": "{redis2.bindings.tcp.host}:{redis2.bindings.tcp.port}", - "image": "docker.io/library/redis:7.4", - "entrypoint": "/bin/sh", - "args": [ - "-c", - "redis-server" - ], - "bindings": { - "tcp": { - "scheme": "tcp", - "protocol": "tcp", - "transport": "tcp", - "targetPort": 6379 - } - } - }, "garnet": { "type": "container.v0", "connectionString": "{garnet.bindings.tcp.host}:{garnet.bindings.tcp.port},password={garnet-password.value}",