-
Notifications
You must be signed in to change notification settings - Fork 647
feat: run apphost in tool mode #9912
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
base: main
Are you sure you want to change the base?
Conversation
Problems that I see now:
|
|
||
namespace Aspire.Hosting.Tools; | ||
|
||
internal class ToolExecutionService |
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 you should just run the tool inside of dcp and use the ResourceLoggingService to extract logs and ResourceNotificationService to track the lifetime of the resource.
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.
From what Mitch has proposed, I thought that we want to run apphost, and once it has started, we would want to wait until caller explicitly invokes the tool execution, that is why I did not put the service in dcp. For example if later we would add --keep-alive
option for apphost, then all we would need to do is change CLI side to not invoke shutdown, and no dcp changes will be required. What do you think?
I will try to reuse ResourceLoggerService
for logging extraction and streaming to cli
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.
You would use:
- ResourceLoggerService (capture logs)
- ResourceNoticationService (wait for lifetime)
- ResourceCommandService (execute commands)
The last one is new and allows you to execute the "resource-start" command for a resource.
I was discussing this today with @DamianEdwards and in a slight pivot I think we said we want to explore running the tool or command with another resource's configuration. In essence, when you invoke a tool, it runs in the context of another resource (maybe as a replacement?).
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.
Right. I'm imagining we introduce something like IResourceSupportsExec
which means it can be targeted by aspire exec
. It would likely have a Prepare
method that's invoked during app host start, and an Execute
method that's invoked to perform the actual command execution. The implementation for ContainerResource
would utilize DCP's support for container exec (this can be done later), and the implementation for ExecutableResource
and ProjectResource
would execute the exec command using the configuration (i.e. working directory, environment variables, wait-for, etc.) of the resource. All the plumbing for capturing the logs and sending them back to the invocation terminal are still required. Eventually we'd want to support interactive commands too but that's not required initially.
The advantage of this approach is that nothing needs to be added to the AppHost to enable executing existing command line tools. One can simply use the aspire
CLI to execute them assuming they're already installed. The concept of supporting tools in the AppHost is still an interesting one though and something that we could revisit later.
Open questions:
- Does the
ExecutableResource
/ProjectResource
still run if it's the target of anaspire exec
, or is its config just used? In the case ofdotnet ef
you don't need the project started, you just want the config. Maybe it's an option? - We might need to support options to
IResourceSupportsExec
(see last point above) that can be passed in from the call site on the command line, to allow for different behaviors, e.g. start resource, replace resource, etc., e.g.aspire exec --resource MyApp --start-resource false dotnet ef migrations add Initial
- What happens once the command is completed? Does the AppHost just do a graceful shut down?
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 we should probably do both approaches. I think we should probably define the tool in the app model (which will support a broader range of scenarios). But aspire exec
would effectively dynamically create an AddExecutable(...)
call to the app model on startup.
Then its just about figuring out how you tell the orchestrator that you want resource X to effectively run with the same environment as resource Y. The way I would tackle that is that I would add an annotation which the orchestrator can spot and then make a call out to apply the target resources environment to the dynamically injected tool resource.
I kind of see these things as distinct but related things.
@@ -51,6 +51,10 @@ public RunCommand(IDotNetCliRunner runner, IInteractionService interactionServic | |||
watchOption.Description = RunCommandStrings.WatchArgumentDescription; | |||
Options.Add(watchOption); | |||
|
|||
var toolParseOption = new Option<string>("--tool", "-t"); | |||
toolParseOption.Description = "Runs a resource as a tool."; |
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.
Need to localize.
Description
Current PR supports running AppHost in
tool
mode. That mode is an extension of run mode, and should be invoked as:The idea is to run apphost, and then find a resource with specified name (i.e.
myTool
), run it, and then shutdown the apphost. It is the first part of supporting EntityFramework e2e scenarios, and later this foundation can be reused for EF specific commands.Implementation
If CLI detects the tool run, it invokes the
IAsyncEnumerable<CommandOutput> GetToolExecutionOutputStreamAsync(CancellationToken cancellationToken)
which streams the output of the tool to the CLI.For now apphost only supports "toolexecution" as
ExecutableResource
. It runs the process by supplying explicitly defined args in the apphost (i.e.WithArgs(...)
) and also supplies the args coming toappHost
directly (those which are passed viaaspire run --tool myTool --....
).Testing
ToolTests
does the testing - it builds the DistributedApplication, by registering a couple of dependencies and an executable resource. After that it resolves theToolExecutionService
which runs theExecutableResource
, and streams the output.cli-tool-run.mp4
Relates to #9859