-
Notifications
You must be signed in to change notification settings - Fork 684
Support prompting for unresolved parameters during deploy #11160
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds support for prompting users for unresolved parameter values during Azure deployment, addressing the need to collect missing parameter values interactively rather than failing the deployment.
- Adds parameter resolution step before Azure Bicep provisioning that prompts for unresolved parameters
- Exposes the WaitForValueTcs property on ParameterResource for testing purposes
- Updates Azure deployment context to include interaction service for parameter prompting
Reviewed Changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
File | Description |
---|---|
tests/Aspire.Hosting.Azure.Tests/AzureDeployerTests.cs | Adds tests for parameter prompting functionality during deployment |
src/Aspire.Hosting/ApplicationModel/ParameterResource.cs | Changes WaitForValueTcs visibility from internal to public |
src/Aspire.Hosting.Azure/AzureEnvironmentResource.cs | Injects interaction service into Azure deploying context |
src/Aspire.Hosting.Azure/AzureDeployingContext.cs | Implements parameter resolution logic with user prompting |
playground/deployers/Deployers.AppHost/AppHost.cs | Adds example parameters for testing deployment scenarios |
@@ -75,7 +75,7 @@ internal string ConfigurationKey | |||
/// <summary> | |||
/// A task completion source that can be used to wait for the value of the parameter to be set. | |||
/// </summary> | |||
internal TaskCompletionSource<string>? WaitForValueTcs { get; set; } | |||
public TaskCompletionSource<string>? WaitForValueTcs { get; set; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't be exposing the TaskCompletionSource
publicly. That would mean anyone would be able to complete the Task. Instead, you just want the Task
to be exposed, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should flip this instead. ParameterResource
has the ability for callers to give it a Task<string>
that it can use to pull the value from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't be exposing the TaskCompletionSource publicly. That would mean anyone would be able to complete the Task.
In this case, we do want to complete the TCS from outside the core API
Maybe we should flip this instead. ParameterResource has the ability for callers to give it a Task that it can use to pull the value from?
Is this similar to SetValue
from #11160 (comment). Something like public void SetValue(Task<string> valueProvider)
then we'd resolve the valueProvider that is passed in GetValueAsync.
Another option is to do something similar to what we did with ProvisioningContextProvider and have a common ParameterProcessor
implementation that both run-mode and publish-mode scenarios use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think a TCS should be exposed publically. Instead I would expected there to be a Task
property on the type and, if publically required, a method to complete it, e.g.
public Task ValueAvailableTask { get; }
public void SetValue(string s); // completes the task
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless you want to cancel or set an exception (now we're recreating a TCS with a new name).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed the implementation in 5d805e1 so that ParameterProcessor is public. This let's the Azure deployer and any other deployers that are implemented add support for parameter resolution.
Some notes on this:
- Users now get prompted about saving values to user secrets, which isn't something we want to support for deployment. We may need to opt this out, I can see it being valuable for super local deployment scenarios but not necessarily deployments from CI.
- We need to add a
WaitForParameterResolutionAsync
method to the processor so that we can support the dashboard's fire and forget model and the
Does every deployment system need to implement their own parameter processing and prompting? Why wouldn't this be as generic as what we have at runtime with the ParameterProcessor? |
Yep, this is a scenario where this proposal:
would come in handy. If we centralize parameter resolution as a core public API, then it wouldn't need to be rewritten in multiple places. |
🚀 Dogfood this PR with: curl -fsSL https://github.com/raw/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 11160 Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 11160" |
ResourceNotificationService notificationService, | ||
ResourceLoggerService loggerService, | ||
IInteractionService interactionService, | ||
ILogger<ParameterProcessor> logger, | ||
DistributedApplicationOptions options) | ||
{ | ||
private readonly List<ParameterResource> _unresolvedParameters = []; | ||
|
||
public async Task InitializeParametersAsync(IEnumerable<ParameterResource> parameterResources) | ||
private Task? _parameterResolutionTask; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Delete this task.
@@ -76,14 +77,16 @@ private Task DeployAsync(DeployingContext context) | |||
var activityPublisher = context.Services.GetRequiredService<IPublishingActivityReporter>(); | |||
var containerImageBuilder = context.Services.GetRequiredService<IResourceContainerImageBuilder>(); | |||
var processRunner = context.Services.GetRequiredService<IProcessRunner>(); | |||
var parameterProcessor = context.Services.GetRequiredService<ParameterProcessor>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want this concrete type as the DI service? Or do we want an interface?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interface when we figure out what to expose. This API is sketchy as is.
/// Initializes parameter resources and handles unresolved parameters if interaction service is available. | ||
/// </summary> | ||
/// <param name="parameterResources">The parameter resources to initialize.</param> | ||
/// <param name="waitForResolution">Whether to wait for all parameters to be resolved before returning.</param> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// <param name="waitForResolution">Whether to wait for all parameters to be resolved before returning.</param> | |
/// <param name="waitForResolution">Whether to wait for all parameters to be resolved before completing the returned Task.</param> |
@@ -14,16 +15,24 @@ namespace Aspire.Hosting.Orchestrator; | |||
/// <summary> | |||
/// Handles processing of parameter resources during application orchestration. | |||
/// </summary> | |||
internal sealed class ParameterProcessor( | |||
[Experimental("ASPIREINTERACTION001", UrlFormat = "https://aka.ms/aspire/diagnostics/{0}")] | |||
public sealed class ParameterProcessor( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is the first public type in the Aspire.Hosting.Orchestrator
namespace. I'm wondering if we should make an interface in a separate namespace that is already exposed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good callout -- I think we should move this to the Aspire.Hosting
namespace to match what we do for InteractionService
.
Contributes to #10448.