diff --git a/playground/ParameterEndToEnd/ParameterEndToEnd.AppHost/AppHost.cs b/playground/ParameterEndToEnd/ParameterEndToEnd.AppHost/AppHost.cs
index aa4d24e3cb4..5dad5acddcf 100644
--- a/playground/ParameterEndToEnd/ParameterEndToEnd.AppHost/AppHost.cs
+++ b/playground/ParameterEndToEnd/ParameterEndToEnd.AppHost/AppHost.cs
@@ -22,7 +22,7 @@
var insertionrows = builder.AddParameter("insertionrows")
.WithDescription("The number of rows to insert into the database.");
-var cs = builder.AddConnectionString("cs", ReferenceExpression.Create($"sql={db};rows={insertionrows}"));
+var cs = builder.AddConnectionString("cs", ReferenceExpression.Create($"sql={db.Resource.Parent.PrimaryEndpoint};rows={insertionrows}"));
var parameterFromConnectionStringConfig = builder.AddConnectionString("parameterFromConnectionStringConfig");
var throwing = builder.AddParameter("throwing", () => throw new InvalidOperationException("This is a test exception."));
diff --git a/src/Aspire.Hosting/ApplicationModel/ParameterResource.cs b/src/Aspire.Hosting/ApplicationModel/ParameterResource.cs
index 76083d8b3b0..6d6ca8ffc04 100644
--- a/src/Aspire.Hosting/ApplicationModel/ParameterResource.cs
+++ b/src/Aspire.Hosting/ApplicationModel/ParameterResource.cs
@@ -9,7 +9,7 @@ namespace Aspire.Hosting.ApplicationModel;
///
/// Represents a parameter resource.
///
-public class ParameterResource : Resource, IResourceWithoutLifetime, IManifestExpressionProvider, IValueProvider
+public class ParameterResource : Resource, IManifestExpressionProvider, IValueProvider
{
private readonly Lazy _lazyValue;
private readonly Func _valueGetter;
diff --git a/src/Aspire.Hosting/CompatibilitySuppressions.xml b/src/Aspire.Hosting/CompatibilitySuppressions.xml
index c9df370dcd3..16770fc94f1 100644
--- a/src/Aspire.Hosting/CompatibilitySuppressions.xml
+++ b/src/Aspire.Hosting/CompatibilitySuppressions.xml
@@ -22,4 +22,25 @@
lib/net8.0/Aspire.Hosting.dll
true
+
+ CP0008
+ T:Aspire.Hosting.ApplicationModel.ParameterResource
+ lib/net8.0/Aspire.Hosting.dll
+ lib/net8.0/Aspire.Hosting.dll
+ true
+
+
+ CP0008
+ T:Aspire.Hosting.ConnectionStringResource
+ lib/net8.0/Aspire.Hosting.dll
+ lib/net8.0/Aspire.Hosting.dll
+ true
+
+
+ CP0008
+ T:Aspire.Hosting.ExternalServiceResource
+ lib/net8.0/Aspire.Hosting.dll
+ lib/net8.0/Aspire.Hosting.dll
+ true
+
\ No newline at end of file
diff --git a/src/Aspire.Hosting/ConnectionStringBuilderExtensions.cs b/src/Aspire.Hosting/ConnectionStringBuilderExtensions.cs
index d6ce9a2f5d2..d3d6bd98a35 100644
--- a/src/Aspire.Hosting/ConnectionStringBuilderExtensions.cs
+++ b/src/Aspire.Hosting/ConnectionStringBuilderExtensions.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using Aspire.Dashboard.Model;
using Aspire.Hosting.ApplicationModel;
+using Microsoft.Extensions.Logging;
namespace Aspire.Hosting;
@@ -39,14 +40,79 @@ public static class ConnectionStringBuilderExtensions
public static IResourceBuilder AddConnectionString(this IDistributedApplicationBuilder builder, [ResourceName] string name, ReferenceExpression connectionStringExpression)
{
var cs = new ConnectionStringResource(name, connectionStringExpression);
- return builder.AddResource(cs)
- .WithReferenceRelationship(connectionStringExpression)
- .WithInitialState(new CustomResourceSnapshot
- {
- ResourceType = KnownResourceTypes.ConnectionString,
- State = KnownResourceStates.Waiting,
- Properties = []
- });
+
+ var rb = builder.AddResource(cs);
+
+ // Wait for any referenced resources in the connection string.
+ // We only look at top level resources with the assumption that they are transitive themselves.
+ var tasks = new List();
+ var resourceNames = new HashSet(StringComparers.ResourceName);
+
+ foreach (var value in cs.ConnectionStringExpression.ValueProviders)
+ {
+ if (value is IResourceWithoutLifetime)
+ {
+ // We cannot wait for resources without a lifetime.
+ continue;
+ }
+
+ if (value is IResource resource)
+ {
+ if (resourceNames.Add(resource.Name))
+ {
+ // Wait for the resource.
+ rb.WaitForStart(builder.CreateResourceBuilder(resource));
+ }
+ }
+ else if (value is IValueWithReferences valueWithReferences)
+ {
+ foreach (var innerRef in valueWithReferences.References.OfType())
+ {
+ if (resourceNames.Add(innerRef.Name))
+ {
+ // Wait for the inner resource.
+ rb.WaitForStart(builder.CreateResourceBuilder(innerRef));
+ }
+ }
+ }
+ }
+
+ return rb.WithReferenceRelationship(connectionStringExpression)
+ .WithInitialState(new CustomResourceSnapshot
+ {
+ ResourceType = KnownResourceTypes.ConnectionString,
+ State = KnownResourceStates.NotStarted,
+ Properties = []
+ })
+ .OnInitializeResource(async (r, @evt, ct) =>
+ {
+ try
+ {
+ // This is where waiting happens
+ await @evt.Eventing.PublishAsync(new BeforeResourceStartedEvent(r, @evt.Services), ct).ConfigureAwait(false);
+
+ // Publish the update with the connection string value and the state as running.
+ // This will allow health checks to start running.
+ await evt.Notifications.PublishUpdateAsync(r, s => s with
+ {
+ State = KnownResourceStates.Running
+ }).ConfigureAwait(false);
+
+ // Publish the connection string available event for other resources that may depend on this resource.
+ await evt.Eventing.PublishAsync(new ConnectionStringAvailableEvent(r, evt.Services), ct)
+ .ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ evt.Logger.LogError(ex, "Failed to resolve connection string for resource '{ResourceName}'", r.Name);
+
+ // If we fail to resolve the connection string, we set the state to failed.
+ await evt.Notifications.PublishUpdateAsync(r, s => s with
+ {
+ State = KnownResourceStates.FailedToStart
+ }).ConfigureAwait(false);
+ }
+ });
}
///
diff --git a/src/Aspire.Hosting/ConnectionStringResource.cs b/src/Aspire.Hosting/ConnectionStringResource.cs
index 5d710b6e16a..8b69902a158 100644
--- a/src/Aspire.Hosting/ConnectionStringResource.cs
+++ b/src/Aspire.Hosting/ConnectionStringResource.cs
@@ -10,7 +10,7 @@ namespace Aspire.Hosting;
///
/// The name of the resource.
/// The connection string expression.
-public sealed class ConnectionStringResource(string name, ReferenceExpression connectionStringExpression) : Resource(name), IResourceWithConnectionString, IResourceWithoutLifetime
+public sealed class ConnectionStringResource(string name, ReferenceExpression connectionStringExpression) : Resource(name), IResourceWithConnectionString, IResourceWithWaitSupport
{
///
/// Describes the connection string format string used for this resource.
diff --git a/src/Aspire.Hosting/ExternalServiceResource.cs b/src/Aspire.Hosting/ExternalServiceResource.cs
index be6aa1f81d6..2791ef33611 100644
--- a/src/Aspire.Hosting/ExternalServiceResource.cs
+++ b/src/Aspire.Hosting/ExternalServiceResource.cs
@@ -9,7 +9,7 @@ namespace Aspire.Hosting;
///
/// Represents an external service resource with service discovery capabilities.
///
-public sealed class ExternalServiceResource : Resource, IResourceWithoutLifetime
+public sealed class ExternalServiceResource : Resource
{
private readonly Uri? _uri;
private readonly ParameterResource? _urlParameter;
diff --git a/src/Aspire.Hosting/Orchestrator/ApplicationOrchestrator.cs b/src/Aspire.Hosting/Orchestrator/ApplicationOrchestrator.cs
index dfeb5974022..3494a0979d2 100644
--- a/src/Aspire.Hosting/Orchestrator/ApplicationOrchestrator.cs
+++ b/src/Aspire.Hosting/Orchestrator/ApplicationOrchestrator.cs
@@ -9,7 +9,6 @@
using Aspire.Hosting.Dcp;
using Aspire.Hosting.Eventing;
using Aspire.Hosting.Lifecycle;
-using Microsoft.Extensions.Logging;
namespace Aspire.Hosting.Orchestrator;
@@ -59,7 +58,6 @@ public ApplicationOrchestrator(DistributedApplicationModel model,
_eventing.Subscribe(PublishConnectionStringValue);
// Implement WaitFor functionality using BeforeResourceStartedEvent.
_eventing.Subscribe(WaitForInBeforeResourceStartedEvent);
- _eventing.Subscribe(OnResourceInitialized);
}
private async Task PublishConnectionStringValue(ConnectionStringAvailableEvent @event, CancellationToken token)
@@ -306,69 +304,6 @@ private async Task OnResourceEndpointsAllocated(ResourceEndpointsAllocatedEvent
await PublishResourceEndpointUrls(@event.Resource, cancellationToken).ConfigureAwait(false);
}
- private Task OnResourceInitialized(InitializeResourceEvent @event, CancellationToken cancellationToken)
- {
- var resource = @event.Resource;
-
- if (resource is ConnectionStringResource connectionStringResource)
- {
- InitializeConnectionString(connectionStringResource);
- }
-
- void InitializeConnectionString(ConnectionStringResource connectionStringResource)
- {
- var logger = _loggerService.GetLogger(resource);
- var waitFor = new List();
-
- var references = connectionStringResource.Annotations.OfType()
- .Where(x => x.Type == KnownRelationshipTypes.Reference)
- .Select(x => x.Resource);
-
- foreach (var reference in references)
- {
- if (reference is IResourceWithEndpoints)
- {
- var tcs = new TaskCompletionSource();
- logger.LogInformation("Waiting for endpoints to be allocated for resource {ResourceName}", reference.Name);
- _eventing.Subscribe(reference, (_, _) =>
- {
- logger.LogInformation("Endpoints allocated for resource {ResourceName}", reference.Name);
- tcs.SetResult();
- return Task.CompletedTask;
- });
-
- waitFor.Add(tcs.Task.WaitAsync(cancellationToken));
- }
-
- if (reference is IResourceWithConnectionString)
- {
- var tcs = new TaskCompletionSource();
- logger.LogInformation("Waiting for connection string to be available for resource {ResourceName}", reference.Name);
- _eventing.Subscribe(reference, (_, _) =>
- {
- logger.LogInformation("Connection string is available for resource {ResourceName}", reference.Name);
- tcs.SetResult();
- return Task.CompletedTask;
- });
-
- waitFor.Add(tcs.Task.WaitAsync(cancellationToken));
- }
- }
-
- _ = Task.Run(async () =>
- {
- await Task.WhenAll(waitFor).ConfigureAwait(false);
- await PublishConnectionStringAvailableEvent(connectionStringResource, cancellationToken).ConfigureAwait(false);
- await _notificationService.PublishUpdateAsync(connectionStringResource, s => s with
- {
- State = new(KnownResourceStates.Active, KnownResourceStateStyles.Success),
- }).ConfigureAwait(false);
- }, cancellationToken);
- }
-
- return Task.CompletedTask;
- }
-
private async Task OnResourceChanged(OnResourceChangedContext context)
{
await _notificationService.PublishUpdateAsync(context.Resource, context.DcpResourceName, context.UpdateSnapshot).ConfigureAwait(false);
diff --git a/src/Aspire.Hosting/Orchestrator/ParameterProcessor.cs b/src/Aspire.Hosting/Orchestrator/ParameterProcessor.cs
index c2cb2575790..f24031c8817 100644
--- a/src/Aspire.Hosting/Orchestrator/ParameterProcessor.cs
+++ b/src/Aspire.Hosting/Orchestrator/ParameterProcessor.cs
@@ -70,7 +70,7 @@ await notificationService.PublishUpdateAsync(parameterResource, s =>
return s with
{
Properties = s.Properties.SetResourceProperty(KnownProperties.Parameter.Value, value, parameterResource.Secret),
- State = new(KnownResourceStates.Active, KnownResourceStateStyles.Success)
+ State = KnownResourceStates.Running
};
})
.ConfigureAwait(false);
@@ -190,7 +190,7 @@ await notificationService.PublishUpdateAsync(parameter, s =>
return s with
{
Properties = s.Properties.SetResourceProperty(KnownProperties.Parameter.Value, inputValue, parameter.Secret),
- State = new(KnownResourceStates.Active, KnownResourceStateStyles.Success)
+ State = KnownResourceStates.Running
};
})
.ConfigureAwait(false);
diff --git a/src/Aspire.Hosting/ParameterResourceBuilderExtensions.cs b/src/Aspire.Hosting/ParameterResourceBuilderExtensions.cs
index a8f4e272bfd..4c39193aaa6 100644
--- a/src/Aspire.Hosting/ParameterResourceBuilderExtensions.cs
+++ b/src/Aspire.Hosting/ParameterResourceBuilderExtensions.cs
@@ -216,7 +216,6 @@ internal static IResourceBuilder AddParameter(this IDistributedApplication
{
ResourceType = KnownResourceTypes.Parameter,
Properties = [
- new("parameter.secret", resource.Secret.ToString()),
new(CustomResourceKnownProperties.Source, resource.ConfigurationKey)
],
State = KnownResourceStates.Waiting
diff --git a/src/Aspire.Hosting/ResourceBuilderExtensions.cs b/src/Aspire.Hosting/ResourceBuilderExtensions.cs
index 2b90cbac462..e64b2158427 100644
--- a/src/Aspire.Hosting/ResourceBuilderExtensions.cs
+++ b/src/Aspire.Hosting/ResourceBuilderExtensions.cs
@@ -1202,16 +1202,6 @@ private static IResourceBuilder WaitForCore(this IResourceBuilder build
builder.WaitForCore(parentBuilder, waitBehavior, addRelationship: false);
}
- // Wait for any referenced resources in the connection string.
- if (dependency.Resource is ConnectionStringResource cs)
- {
- // We only look at top level resources with the assumption that they are transitive themselves.
- foreach (var referencedResource in cs.ConnectionStringExpression.ValueProviders.OfType())
- {
- builder.WaitForCore(builder.ApplicationBuilder.CreateResourceBuilder(referencedResource), waitBehavior, addRelationship: false);
- }
- }
-
if (addRelationship)
{
builder.WithRelationship(dependency.Resource, KnownRelationshipTypes.WaitFor);
diff --git a/tests/Aspire.Hosting.Tests/AddConnectionStringTests.cs b/tests/Aspire.Hosting.Tests/AddConnectionStringTests.cs
new file mode 100644
index 00000000000..db70e04beba
--- /dev/null
+++ b/tests/Aspire.Hosting.Tests/AddConnectionStringTests.cs
@@ -0,0 +1,103 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Aspire.Dashboard.Model;
+using Aspire.Hosting.Utils;
+using Microsoft.AspNetCore.InternalTesting;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Aspire.Hosting.Tests;
+
+public class AddConnectionStringTests
+{
+ [Fact]
+ public async Task AddConnectionStringExpressionIsAValueInTheManifest()
+ {
+ var appBuilder = DistributedApplication.CreateBuilder();
+
+ var endpoint = appBuilder.AddParameter("endpoint", "http://localhost:3452");
+ var key = appBuilder.AddParameter("key", "secretKey", secret: true);
+
+ // Get the service provider.
+ appBuilder.AddConnectionString("mycs", ReferenceExpression.Create($"Endpoint={endpoint};Key={key}"));
+
+ using var app = appBuilder.Build();
+
+ var appModel = app.Services.GetRequiredService();
+ var connectionStringResource = Assert.Single(appModel.Resources.OfType());
+
+ Assert.Equal("mycs", connectionStringResource.Name);
+ var connectionStringManifest = await ManifestUtils.GetManifest(connectionStringResource).DefaultTimeout();
+
+ var expectedManifest = $$"""
+ {
+ "type": "value.v0",
+ "connectionString": "Endpoint={endpoint.value};Key={key.value}"
+ }
+ """;
+
+ var s = connectionStringManifest.ToString();
+
+ Assert.Equal(expectedManifest, s);
+ }
+
+ [Fact]
+ public void ConnectionStringsAreVisibleByDefault()
+ {
+ var appBuilder = DistributedApplication.CreateBuilder();
+ var endpoint = appBuilder.AddParameter("endpoint", "http://localhost:3452");
+ var key = appBuilder.AddParameter("key", "secretKey", secret: true);
+
+ appBuilder.AddConnectionString("testcs", ReferenceExpression.Create($"Endpoint={endpoint};Key={key}"));
+
+ using var app = appBuilder.Build();
+
+ var appModel = app.Services.GetRequiredService();
+
+ var connectionStringResource = Assert.Single(appModel.Resources.OfType());
+ var annotation = connectionStringResource.Annotations.OfType().SingleOrDefault();
+
+ Assert.NotNull(annotation);
+
+ var state = annotation.InitialSnapshot;
+
+ Assert.False(state.IsHidden);
+ Assert.Equal(KnownResourceTypes.ConnectionString, state.ResourceType);
+ Assert.Equal(KnownResourceStates.NotStarted, state.State?.Text);
+ }
+
+ [Fact]
+ public void ConnectionStringResourceAddsWaitAnnotationsForReferencedResources()
+ {
+ using var builder = TestDistributedApplicationBuilder.Create();
+
+ var redis = builder.AddContainer("c", "redis").WithEndpoint(name: "tcp");
+ var key = builder.AddParameter("key", "secretKey", secret: true);
+ var rwl = builder.AddResource(new ResourceWithoutLifetime("rwl"));
+
+ var cs = builder.AddConnectionString("mycs",
+ ReferenceExpression.Create($"Endpoint={redis.GetEndpoint("tcp")};key={key};{rwl}"));
+
+ cs.Resource.TryGetAnnotationsOfType(out var waitAnnotations);
+
+ Assert.NotNull(waitAnnotations);
+
+ Assert.Collection(waitAnnotations,
+ wa =>
+ {
+ Assert.Same(redis.Resource, wa.Resource);
+ Assert.Equal(WaitType.WaitUntilStarted, wa.WaitType);
+ },
+ wa =>
+ {
+ Assert.Same(key.Resource, wa.Resource);
+ Assert.Equal(WaitType.WaitUntilStarted, wa.WaitType);
+ });
+ }
+
+ private sealed class ResourceWithoutLifetime(string name) : Resource(name), IResourceWithConnectionString, IResourceWithoutLifetime
+ {
+ public ReferenceExpression ConnectionStringExpression =>
+ ReferenceExpression.Create($"ResourceWithoutLifetime");
+ }
+}
\ No newline at end of file
diff --git a/tests/Aspire.Hosting.Tests/AddParameterTests.cs b/tests/Aspire.Hosting.Tests/AddParameterTests.cs
index 8588277f976..214489cb6b6 100644
--- a/tests/Aspire.Hosting.Tests/AddParameterTests.cs
+++ b/tests/Aspire.Hosting.Tests/AddParameterTests.cs
@@ -1,7 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using Aspire.Dashboard.Model;
using Aspire.Hosting.Publishing;
using Aspire.Hosting.Resources;
using Aspire.Hosting.Utils;
@@ -34,11 +33,6 @@ public void ParametersAreVisibleByDefault()
Assert.False(state.IsHidden);
Assert.Collection(state.Properties,
- prop =>
- {
- Assert.Equal("parameter.secret", prop.Name);
- Assert.Equal("True", prop.Value);
- },
prop =>
{
Assert.Equal(CustomResourceKnownProperties.Source, prop.Name);
@@ -333,37 +327,6 @@ public async Task AddConnectionStringParameterIsASecretParameterInTheManifest()
Assert.Equal(expectedManifest, s);
}
- [Fact]
- public async Task AddConnectionStringExpressionIsAValueInTheManifest()
- {
- var appBuilder = DistributedApplication.CreateBuilder();
-
- var endpoint = appBuilder.AddParameter("endpoint", "http://localhost:3452");
- var key = appBuilder.AddParameter("key", "secretKey", secret: true);
-
- // Get the service provider.
- appBuilder.AddConnectionString("mycs", ReferenceExpression.Create($"Endpoint={endpoint};Key={key}"));
-
- using var app = appBuilder.Build();
-
- var appModel = app.Services.GetRequiredService();
- var connectionStringResource = Assert.Single(appModel.Resources.OfType());
-
- Assert.Equal("mycs", connectionStringResource.Name);
- var connectionStringManifest = await ManifestUtils.GetManifest(connectionStringResource).DefaultTimeout();
-
- var expectedManifest = $$"""
- {
- "type": "value.v0",
- "connectionString": "Endpoint={endpoint.value};Key={key.value}"
- }
- """;
-
- var s = connectionStringManifest.ToString();
-
- Assert.Equal(expectedManifest, s);
- }
-
private sealed class TestParameterDefault(string defaultValue) : ParameterDefault
{
public override string GetDefaultValue() => defaultValue;
@@ -374,31 +337,6 @@ public override void WriteToManifest(ManifestPublishingContext context)
}
}
- [Fact]
- public void ConnectionStringsAreVisibleByDefault()
- {
- var appBuilder = DistributedApplication.CreateBuilder();
- var endpoint = appBuilder.AddParameter("endpoint", "http://localhost:3452");
- var key = appBuilder.AddParameter("key", "secretKey", secret: true);
-
- appBuilder.AddConnectionString("testcs", ReferenceExpression.Create($"Endpoint={endpoint};Key={key}"));
-
- using var app = appBuilder.Build();
-
- var appModel = app.Services.GetRequiredService();
-
- var connectionStringResource = Assert.Single(appModel.Resources.OfType());
- var annotation = connectionStringResource.Annotations.OfType().SingleOrDefault();
-
- Assert.NotNull(annotation);
-
- var state = annotation.InitialSnapshot;
-
- Assert.False(state.IsHidden);
- Assert.Equal(KnownResourceTypes.ConnectionString, state.ResourceType);
- Assert.Equal(KnownResourceStates.Waiting, state.State?.Text);
- }
-
[Fact]
public void ParameterWithDescription_SetsDescriptionProperty()
{
diff --git a/tests/Aspire.Hosting.Tests/ExternalServiceTests.cs b/tests/Aspire.Hosting.Tests/ExternalServiceTests.cs
index aae26da9132..d121b8f8aa0 100644
--- a/tests/Aspire.Hosting.Tests/ExternalServiceTests.cs
+++ b/tests/Aspire.Hosting.Tests/ExternalServiceTests.cs
@@ -246,17 +246,6 @@ public void ExternalServiceResourceHasExpectedInitialState()
Assert.Equal("ExternalService", snapshot.InitialSnapshot.ResourceType);
}
- [Fact]
- public void ExternalServiceResourceImplementsExpectedInterfaces()
- {
- using var builder = TestDistributedApplicationBuilder.Create();
-
- var externalService = builder.AddExternalService("nuget", "https://nuget.org/");
-
- // Verify the resource implements the expected interfaces
- Assert.IsAssignableFrom(externalService.Resource);
- }
-
[Fact]
public void ExternalServiceResourceIsExcludedFromPublishingManifest()
{
diff --git a/tests/Aspire.Hosting.Tests/Orchestrator/ParameterProcessorTests.cs b/tests/Aspire.Hosting.Tests/Orchestrator/ParameterProcessorTests.cs
index e02f6282010..1bc1f1c4785 100644
--- a/tests/Aspire.Hosting.Tests/Orchestrator/ParameterProcessorTests.cs
+++ b/tests/Aspire.Hosting.Tests/Orchestrator/ParameterProcessorTests.cs
@@ -16,7 +16,7 @@ namespace Aspire.Hosting.Tests.Orchestrator;
public class ParameterProcessorTests
{
[Fact]
- public async Task InitializeParametersAsync_WithValidParameters_SetsActiveState()
+ public async Task InitializeParametersAsync_WithValidParameters_SetsRunningState()
{
// Arrange
var parameterProcessor = CreateParameterProcessor();
@@ -41,7 +41,7 @@ public async Task InitializeParametersAsync_WithValidParameters_SetsActiveState(
}
[Fact]
- public async Task InitializeParametersAsync_WithValidParametersAndDashboardEnabled_SetsActiveState()
+ public async Task InitializeParametersAsync_WithValidParametersAndDashboardEnabled_SetsRunningState()
{
// Arrange
var interactionService = CreateInteractionService(disableDashboard: false);
@@ -93,8 +93,7 @@ public async Task InitializeParametersAsync_WithSecretParameter_MarksAsSecret()
// Assert
var (resource, snapshot) = Assert.Single(updates);
Assert.Same(secretParam, resource);
- Assert.Equal(KnownResourceStates.Active, snapshot.State?.Text);
- Assert.Equal(KnownResourceStateStyles.Success, snapshot.State?.Style);
+ Assert.Equal(KnownResourceStates.Running, snapshot.State?.Text);
}
[Fact]
@@ -246,17 +245,17 @@ public async Task HandleUnresolvedParametersAsync_WithMultipleUnresolvedParamete
Assert.Equal("secretValue", await secretParam.WaitForValueTcs.Task);
// Notification service should have received updates for each parameter
- // Marking them as Active with the provided values
+ // Marking them as Running with the provided values
await updates.MoveNextAsync();
- Assert.Equal(KnownResourceStates.Active, updates.Current.Snapshot.State?.Text);
+ Assert.Equal(KnownResourceStates.Running, updates.Current.Snapshot.State?.Text);
Assert.Equal("value1", updates.Current.Snapshot.Properties.FirstOrDefault(p => p.Name == KnownProperties.Parameter.Value)?.Value);
await updates.MoveNextAsync();
- Assert.Equal(KnownResourceStates.Active, updates.Current.Snapshot.State?.Text);
+ Assert.Equal(KnownResourceStates.Running, updates.Current.Snapshot.State?.Text);
Assert.Equal("value2", updates.Current.Snapshot.Properties.FirstOrDefault(p => p.Name == KnownProperties.Parameter.Value)?.Value);
await updates.MoveNextAsync();
- Assert.Equal(KnownResourceStates.Active, updates.Current.Snapshot.State?.Text);
+ Assert.Equal(KnownResourceStates.Running, updates.Current.Snapshot.State?.Text);
Assert.Equal("secretValue", updates.Current.Snapshot.Properties.FirstOrDefault(p => p.Name == KnownProperties.Parameter.Value)?.Value);
Assert.True(updates.Current.Snapshot.Properties.FirstOrDefault(p => p.Name == KnownProperties.Parameter.Value)?.IsSensitive ?? false);
}
diff --git a/tests/Aspire.Hosting.Tests/WithReferenceTests.cs b/tests/Aspire.Hosting.Tests/WithReferenceTests.cs
index 1204d57cbd5..f704c215669 100644
--- a/tests/Aspire.Hosting.Tests/WithReferenceTests.cs
+++ b/tests/Aspire.Hosting.Tests/WithReferenceTests.cs
@@ -302,6 +302,16 @@ public async Task ConnectionStringResourceWithExpressionConnectionString()
Assert.True(resource.Resource.TryGetAnnotationsOfType(out var csRelationships));
Assert.Collection(csRelationships,
+ r =>
+ {
+ Assert.Equal("WaitFor", r.Type);
+ Assert.Same(endpoint.Resource, r.Resource);
+ },
+ r =>
+ {
+ Assert.Equal("WaitFor", r.Type);
+ Assert.Same(key.Resource, r.Resource);
+ },
r =>
{
Assert.Equal("Reference", r.Type);