feat(cli): retrieve virtual machine instance description#602
feat(cli): retrieve virtual machine instance description#602skevetter merged 1 commit intoskevetter:mainfrom
Conversation
📝 WalkthroughWalkthroughAdds a new machine "describe" CLI command and corresponding client API/implementations that run provider describe commands and return their output; extends provider config with a Changes
Sequence DiagramsequenceDiagram
participant CLI as CLI
participant Config as Config Loader
participant Workspace as Workspace Client
participant Machine as Machine Client
participant Executor as Command Executor
participant Output as Stdout/Stderr
CLI->>Config: Load config
Config-->>CLI: config
CLI->>Workspace: GetMachine(config, args)
Workspace-->>CLI: machine client
CLI->>Machine: Describe(ctx)
Machine->>Executor: Run provider describe command
Executor->>Output: Capture stdout/stderr
Executor-->>Machine: result
alt success
Machine-->>CLI: Description (stdout)
else failure
Machine-->>CLI: DescriptionNotFound (combined stdout/stderr)
end
Estimated Code Review Effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
cmd/machine/describe.go (1)
28-29: Use the cobra command's context instead ofcontext.Background().Using
context.Background()ignores any context set on the cobra command, which can affect signal handling and cancellation propagation.♻️ Proposed fix
describeCmd := &cobra.Command{ Use: "describe [name]", Short: "Retrieves the description of an existing machine", - RunE: func(_ *cobra.Command, args []string) error { - return cmd.Run(context.Background(), args) + RunE: func(cobraCmd *cobra.Command, args []string) error { + return cmd.Run(cobraCmd.Context(), args) }, }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cmd/machine/describe.go` around lines 28 - 29, The RunE handler uses context.Background() which ignores the cobra command's context; change the handler signature to accept the cobra command (e.g. func(c *cobra.Command, args []string) error) and pass c.Context() into the existing cmd.Run call (replace context.Background() with c.Context()), ensuring you don't shadow the package-level cmd variable while updating the parameter name.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@cmd/machine/describe.go`:
- Around line 28-29: The RunE handler uses context.Background() which ignores
the cobra command's context; change the handler signature to accept the cobra
command (e.g. func(c *cobra.Command, args []string) error) and pass c.Context()
into the existing cmd.Run call (replace context.Background() with c.Context()),
ensuring you don't shadow the package-level cmd variable while updating the
parameter name.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 0f3771ea-ec44-454f-8950-09c5a7d88749
📒 Files selected for processing (12)
cmd/machine/delete.gocmd/machine/describe.gocmd/machine/list.gocmd/machine/machine.gocmd/machine/ssh.gocmd/machine/start.gocmd/machine/status.gocmd/machine/stop.gopkg/client/client.gopkg/client/clientimplementation/machine_client.gopkg/client/clientimplementation/workspace_client.gopkg/provider/provider.go
ca535f8 to
844152d
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
cmd/machine/describe.go (1)
26-31: Consider using cobra command's context for signal propagation.Using
context.Background()in theRunEhandler ignores any context that cobra may provide (e.g., for handling cancellation signals like SIGINT). Consider using the command's context:♻️ Suggested improvement
describeCmd := &cobra.Command{ Use: "describe [name]", Short: "Retrieves the description of an existing machine", - RunE: func(_ *cobra.Command, args []string) error { - return cmd.Run(context.Background(), args) + RunE: func(cobraCmd *cobra.Command, args []string) error { + return cmd.Run(cobraCmd.Context(), args) }, }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cmd/machine/describe.go` around lines 26 - 31, The handler currently calls cmd.Run with context.Background(), which ignores cobra's command context and signal cancellation; change the RunE signature to accept the command (e.g., func(c *cobra.Command, args []string) error) and call cmd.Run(c.Context(), args) so describeCmd uses the cobra-provided context for cancellation/propagation (also remove the now-unused context.Background() usage/import).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@cmd/machine/describe.go`:
- Around line 26-31: The handler currently calls cmd.Run with
context.Background(), which ignores cobra's command context and signal
cancellation; change the RunE signature to accept the command (e.g., func(c
*cobra.Command, args []string) error) and call cmd.Run(c.Context(), args) so
describeCmd uses the cobra-provided context for cancellation/propagation (also
remove the now-unused context.Background() usage/import).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: e86024f1-73b0-485b-b016-cb6cb0d0f1f4
📒 Files selected for processing (11)
cmd/machine/delete.gocmd/machine/describe.gocmd/machine/list.gocmd/machine/machine.gocmd/machine/ssh.gocmd/machine/start.gocmd/machine/status.gocmd/machine/stop.gopkg/client/client.gopkg/client/clientimplementation/machine_client.gopkg/client/clientimplementation/workspace_client.go
✅ Files skipped from review due to trivial changes (3)
- cmd/machine/ssh.go
- cmd/machine/list.go
- cmd/machine/start.go
🚧 Files skipped from review as they are similar to previous changes (4)
- cmd/machine/status.go
- cmd/machine/stop.go
- cmd/machine/delete.go
- pkg/client/clientimplementation/machine_client.go
844152d to
e6fd2be
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
cmd/machine/describe.go (1)
26-32: Consider adding argument validation to the command.The
Use: "describe [name]"suggests an optional single argument, but without explicitArgsvalidation, extra arguments are silently ignored (perGetMachinebehavior inpkg/workspace/machine.go:147-170). Adding validation improves CLI UX by providing clear error messages for invalid invocations.Proposed fix
describeCmd := &cobra.Command{ Use: "describe [name]", Short: "Retrieves the description of an existing machine", + Args: cobra.MaximumNArgs(1), RunE: func(_ *cobra.Command, args []string) error { return cmd.Run(context.Background(), args) }, }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cmd/machine/describe.go` around lines 26 - 32, The describe command lacks argument validation: add an Args validator on the describeCmd (the cobra.Command created in cmd/machine/describe.go) to enforce exactly one positional argument (or adjust to zero/one if intended) so extra arguments are rejected; update the command declaration near describeCmd and ensure RunE (which calls cmd.Run) only runs when the Args check passes so GetMachine is not called with unexpected extra args.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@cmd/machine/describe.go`:
- Around line 26-32: The describe command lacks argument validation: add an Args
validator on the describeCmd (the cobra.Command created in
cmd/machine/describe.go) to enforce exactly one positional argument (or adjust
to zero/one if intended) so extra arguments are rejected; update the command
declaration near describeCmd and ensure RunE (which calls cmd.Run) only runs
when the Args check passes so GetMachine is not called with unexpected extra
args.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 31ceca32-a908-4a0d-915e-ecc6ac3c2e1d
📒 Files selected for processing (12)
cmd/machine/delete.gocmd/machine/describe.gocmd/machine/list.gocmd/machine/machine.gocmd/machine/ssh.gocmd/machine/start.gocmd/machine/status.gocmd/machine/stop.gopkg/client/client.gopkg/client/clientimplementation/machine_client.gopkg/client/clientimplementation/workspace_client.gopkg/provider/provider.go
✅ Files skipped from review due to trivial changes (3)
- cmd/machine/start.go
- cmd/machine/delete.go
- cmd/machine/stop.go
🚧 Files skipped from review as they are similar to previous changes (7)
- cmd/machine/ssh.go
- cmd/machine/status.go
- cmd/machine/list.go
- pkg/provider/provider.go
- pkg/client/client.go
- pkg/client/clientimplementation/workspace_client.go
- cmd/machine/machine.go
|
@skevetter I probably shouldn't be able to merge pull requests without approval; you may want to tweak the repository settings a bit ;) |
I'm still figuring out the settings. Are you able to merge with bypass with your current permissions? |
No. Everything seems to be as it should now. Thanks! |
skevetter
left a comment
There was a problem hiding this comment.
Will review the gcloud provider changes next, merge those changes, and update the provider.
| Use: "describe [name]", | ||
| Short: "Retrieves the description of an existing machine", | ||
| RunE: func(_ *cobra.Command, args []string) error { | ||
| return cmd.Run(context.Background(), args) |
There was a problem hiding this comment.
There is inconsistency throughout the commands. Some use context.Background(); others use cobraCmd.Context(). I'll let you decide if you want to update this here; otherwise, I can follow up and update all the commands at once.
| return cmd.Run(context.Background(), args) | |
| RunE: func(cobraCmd *cobra.Command, args []string) error { | |
| return cmd.Run(cobraCmd.Context(), args) |
There was a problem hiding this comment.
Sorry, I'll leave this one to you: I do not understand the difference sufficiently...
Signed-off-by: Leonid Dubinsky <dub@podval.org>
e6fd2be to
85066db
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@pkg/client/clientimplementation/machine_client.go`:
- Around line 245-264: The Describe method must short-circuit when there is no
describe command configured: check if len(s.config.Exec.Describe) == 0 at the
start of machineClient.Describe and, if so, return client.DescriptionNotFound
(and nil error) instead of calling s.executor.execute; this avoids treating an
empty command slice as a successful no-op from RunCommand and ensures callers
get DescriptionNotFound for providers that don't support describe.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 638a6887-576e-48a0-b973-9a66976e5a94
📒 Files selected for processing (12)
cmd/machine/delete.gocmd/machine/describe.gocmd/machine/list.gocmd/machine/machine.gocmd/machine/ssh.gocmd/machine/start.gocmd/machine/status.gocmd/machine/stop.gopkg/client/client.gopkg/client/clientimplementation/machine_client.gopkg/client/clientimplementation/workspace_client.gopkg/provider/provider.go
✅ Files skipped from review due to trivial changes (2)
- cmd/machine/stop.go
- cmd/machine/start.go
🚧 Files skipped from review as they are similar to previous changes (4)
- cmd/machine/delete.go
- cmd/machine/describe.go
- pkg/provider/provider.go
- cmd/machine/machine.go
| func (s *machineClient) Describe(ctx context.Context) (string, error) { | ||
| stdout := &bytes.Buffer{} | ||
| stderr := &bytes.Buffer{} | ||
|
|
||
| err := s.executor.execute(ctx, execConfig{ | ||
| name: "describe", | ||
| command: s.config.Exec.Describe, | ||
| stdout: stdout, | ||
| stderr: io.MultiWriter(stderr, s.log.Writer(logrus.InfoLevel, true)), | ||
| }) | ||
| if err != nil { | ||
| return client.DescriptionNotFound, fmt.Errorf( | ||
| "describe: %s%s", | ||
| strings.TrimSpace(stdout.String()), | ||
| strings.TrimSpace(stderr.String()), | ||
| ) | ||
| } | ||
|
|
||
| return strings.TrimSpace(stdout.String()), nil | ||
| } |
There was a problem hiding this comment.
Handle providers with no describe command before executing.
execute() eventually reaches RunCommand, which treats an empty command slice as success. Because this method does not guard len(s.config.Exec.Describe) == 0, direct machine-client callers can get "", nil for unsupported providers and the new machine describe flow will look like a successful no-op instead of returning DescriptionNotFound or failing.
Suggested fix
func (s *machineClient) Describe(ctx context.Context) (string, error) {
+ if len(s.config.Exec.Describe) == 0 {
+ return client.DescriptionNotFound, nil
+ }
+
stdout := &bytes.Buffer{}
stderr := &bytes.Buffer{}
err := s.executor.execute(ctx, execConfig{
name: "describe",
command: s.config.Exec.Describe,
stdout: stdout,
stderr: io.MultiWriter(stderr, s.log.Writer(logrus.InfoLevel, true)),
})🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pkg/client/clientimplementation/machine_client.go` around lines 245 - 264,
The Describe method must short-circuit when there is no describe command
configured: check if len(s.config.Exec.Describe) == 0 at the start of
machineClient.Describe and, if so, return client.DescriptionNotFound (and nil
error) instead of calling s.executor.execute; this avoids treating an empty
command slice as a successful no-op from RunCommand and ensures callers get
DescriptionNotFound for providers that don't support describe.
Thank you! |
Summary by CodeRabbit
New Features
Bug Fixes
Chores