Fix Redis DbGate TLS connections - #1549
Conversation
There was a problem hiding this comment.
Pull request overview
This PR fixes the Redis WithDbGate() integration to work reliably when Redis uses TLS by (1) sourcing the connection URL from Aspire’s deferred RedisResource.UriExpression and (2) configuring the DbGate container to trust Aspire’s development certificate.
Changes:
- Update
WithDbGate()to set DbGate’sURL_*env var fromRedisResource.UriExpressionand add a certificate trust configuration for DbGate. - Update resource-creation tests to validate the deferred
ReferenceExpressionrather than forcing early resolution. - Add a Docker-backed integration test that logs into DbGate and verifies Redis connectivity by issuing
PINGand assertingPONG.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/CommunityToolkit.Aspire.Hosting.Redis.Extensions/RedisBuilderExtensions.cs |
Switch DbGate Redis URL to UriExpression and add cert-trust configuration for Node/DbGate. |
tests/CommunityToolkit.Aspire.Hosting.Redis.Extensions.Tests/ResourceCreationTests.cs |
Adjust tests to inspect deferred expressions and assert cert-trust annotation exists. |
tests/CommunityToolkit.Aspire.Hosting.Redis.Extensions.Tests/AppHostTests.cs |
Add Docker integration test that exercises DbGate → Redis TLS connectivity via PING. |
Suppressed comments (2)
tests/CommunityToolkit.Aspire.Hosting.Redis.Extensions.Tests/AppHostTests.cs:60
- The refresh HTTP call should use the 5-minute linked token (cts.Token). Using TestContext.Current.CancellationToken here bypasses the CancelAfter timeout and can cause the test to hang indefinitely if DbGate stops responding.
using var refreshResponse = await httpClient.PostAsJsonAsync(
"/server-connections/refresh",
new
{
conid = "redis1",
keepOpen = true
},
cancellationToken: TestContext.Current.CancellationToken);
tests/CommunityToolkit.Aspire.Hosting.Redis.Extensions.Tests/AppHostTests.cs:72
- The Redis PING call (and response body read) should use cts.Token so it respects the 5-minute timeout you set up for this test. Right now it uses TestContext.Current.CancellationToken, so a stuck request can outlive the intended timeout.
using var pingResponse = await httpClient.PostAsJsonAsync(
"/database-connections/call-method",
new
{
conid = "redis1",
database = "db0",
method = "ping",
args = Array.Empty<object>()
},
cancellationToken: TestContext.Current.CancellationToken);
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
@dotnet-policy-service agree |
| private static async Task<Dictionary<string, object>> GetEnvironmentVariablesAsync( | ||
| IDistributedApplicationBuilder builder, | ||
| IResource resource) | ||
| { | ||
| Assert.True(resource.TryGetAnnotationsOfType<EnvironmentCallbackAnnotation>(out var annotations)); | ||
|
|
||
| var environmentVariables = new Dictionary<string, object>(); | ||
| var context = new EnvironmentCallbackContext(builder.ExecutionContext, environmentVariables); | ||
|
|
||
| foreach (var annotation in annotations) | ||
| { | ||
| await annotation.Callback(context); | ||
| } | ||
|
|
||
| return environmentVariables; | ||
| } |
There was a problem hiding this comment.
What's the need for this over the original approach to getting environment variables?
There was a problem hiding this comment.
The original approach was deadlocking when resolving the env variables that referenced the endpoint. Probably because the endpoint was not allocated yet.
May be related to microsoft/aspire#14954
**Closes #1548 **
Fixes the Redis DbGate integration by using
RedisResource.UriExpressioninstead of manually constructing the connection URL.The DbGate container is also configured to trust Aspire's development certificate through
NODE_EXTRA_CA_CERTS.Validation
ReferenceExpressionvalues directly. Resolving them withGetEnvironmentVariablesAsync()before Aspire allocates the Redis endpoint caused the tests to wait indefinitely.PING.PONG.PR Checklist
Other information
Adding certificate trust alone was not sufficient. The previous URL used the Redis resource name directly as the hostname, while Aspire’s certificate is issued for the hostname produced by its deferred endpoint expression.
The fix uses
RedisResource.UriExpression, preserving Aspire’s runtime-resolved hostname, port, credentials, and TLS scheme so the hostname matches the generated certificate.The existing tests only verified the generated environment-variable values and that the DbGate web UI responded. They did not verify that DbGate could establish and use the Redis connection. The new Docker-backed test opens the configured connection through DbGate, executes Redis
PING, and asserts that it returnsPONG.The unit tests now inspect the deferred
ReferenceExpressiondirectly. CallingGetEnvironmentVariablesAsync()before Aspire allocates the endpoint attempts to resolve it prematurely and can wait indefinitely.