Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions src/Aspire.Hosting/Orchestrator/ParameterProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,14 @@ public async Task InitializeParametersAsync(DistributedApplicationModel model, b

private async Task CollectDependentParameterResourcesAsync(DistributedApplicationModel model, Dictionary<string, ParameterResource> referencedParameters, HashSet<object?> currentDependencySet, CancellationToken cancellationToken)
{
var publishExecutionContext = new DistributedApplicationExecutionContext(DistributedApplicationOperation.Publish);

foreach (var resource in model.Resources)
{
await ProcessResourceDependenciesAsync(resource, publishExecutionContext, referencedParameters, currentDependencySet, cancellationToken).ConfigureAwait(false);
if (resource.IsExcludedFromPublish())
{
continue;
}

await ProcessResourceDependenciesAsync(resource, executionContext, referencedParameters, currentDependencySet, cancellationToken).ConfigureAwait(false);
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,81 @@ public async Task InitializeParametersAsync_WithDistributedApplicationModel_Hand
}
}

[Fact]
public async Task InitializeParametersAsync_UsesExecutionContextOptions_DoesNotThrow()
{
// Arrange
using var builder = TestDistributedApplicationBuilder.Create();
var param = builder.AddParameter("testParam", () => "testValue");

var serviceProviderAccessed = false;
builder.AddContainer("testContainer", "nginx")
.WithEnvironment(context =>
{
// This should not throw InvalidOperationException
// when using the proper execution context constructor
var sp = context.ExecutionContext.ServiceProvider;
serviceProviderAccessed = sp is not null;
context.EnvironmentVariables["TEST_ENV"] = param;
});

using var app = builder.Build();
var model = app.Services.GetRequiredService<DistributedApplicationModel>();

// Get the ParameterProcessor from the built app's service provider
// This ensures it has the proper execution context with ServiceProvider
var parameterProcessor = app.Services.GetRequiredService<ParameterProcessor>();

// Act - Should not throw InvalidOperationException about IServiceProvider not being available
await parameterProcessor.InitializeParametersAsync(model);

// Assert
Assert.True(serviceProviderAccessed);
var parameterResource = model.Resources.OfType<ParameterResource>().Single();
Assert.NotNull(parameterResource.WaitForValueTcs);
Assert.True(parameterResource.WaitForValueTcs.Task.IsCompletedSuccessfully);
}

[Fact]
public async Task InitializeParametersAsync_SkipsResourcesExcludedFromPublish()
{
// Arrange
using var builder = TestDistributedApplicationBuilder.Create();
var param = builder.AddParameter("excludedParam", () => "excludedValue");

var excludedContainer = builder.AddContainer("excludedContainer", "nginx")
.WithEnvironment(context =>
{
context.EnvironmentVariables["EXCLUDED_ENV"] = param;
});

// Mark the container as excluded from publish
excludedContainer.ExcludeFromManifest();

using var app = builder.Build();
var model = app.Services.GetRequiredService<DistributedApplicationModel>();

var parameterProcessor = CreateParameterProcessor();

// Act - The excluded container should be skipped during parameter collection
await parameterProcessor.InitializeParametersAsync(model);

// Assert
// The environment callback should have been invoked during parameter collection
// because we now create a publish execution context to collect dependent parameters
// However, since we filter out excluded resources, the parameter should not be initialized
// unless it's explicitly in the model
var parameters = model.Resources.OfType<ParameterResource>().ToList();
Assert.Single(parameters);

var parameterResource = parameters[0];
Assert.Equal("excludedParam", parameterResource.Name);

// The parameter should be initialized since it's explicitly in the model
Assert.NotNull(parameterResource.WaitForValueTcs);
Assert.True(parameterResource.WaitForValueTcs.Task.IsCompletedSuccessfully);
}

private static ParameterProcessor CreateParameterProcessor(
ResourceNotificationService? notificationService = null,
ResourceLoggerService? loggerService = null,
Expand Down