Skip to content

Commit 3ff5a77

Browse files
cmd/experimental/air: scaffold AI runtime CLI command package
Add the experimental `air` command group as the Go port surface for the Python `air` CLI. Every subcommand (run, status, list, logs, cancel, register-image) is registered as a stub that returns a not-implemented error; the real implementations land in later milestones. Includes unit tests for the command-tree wiring and the not-implemented stubs, plus an acceptance test exercising the stubs end-to-end. Co-authored-by: Isaac
1 parent d66b99e commit 3ff5a77

14 files changed

Lines changed: 334 additions & 0 deletions

File tree

acceptance/experimental/air/unimplemented/out.test.toml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
=== run
3+
>>> [CLI] experimental air run
4+
Error: `air run` is not implemented yet
5+
6+
Exit code: 1
7+
8+
=== status
9+
>>> [CLI] experimental air status 123
10+
Error: `air status` is not implemented yet
11+
12+
Exit code: 1
13+
14+
=== list
15+
>>> [CLI] experimental air list
16+
Error: `air list` is not implemented yet
17+
18+
Exit code: 1
19+
20+
=== logs
21+
>>> [CLI] experimental air logs 123
22+
Error: `air logs` is not implemented yet
23+
24+
Exit code: 1
25+
26+
=== cancel
27+
>>> [CLI] experimental air cancel 123
28+
Error: `air cancel` is not implemented yet
29+
30+
Exit code: 1
31+
32+
=== register-image
33+
>>> [CLI] experimental air register-image my-image:latest
34+
Error: `air register-image` is not implemented yet
35+
36+
Exit code: 1
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Each stub must fail with "not implemented"; errcode records the exit code.
2+
3+
title "run"
4+
errcode trace $CLI experimental air run
5+
6+
title "status"
7+
errcode trace $CLI experimental air status 123
8+
9+
title "list"
10+
errcode trace $CLI experimental air list
11+
12+
title "logs"
13+
errcode trace $CLI experimental air logs 123
14+
15+
title "cancel"
16+
errcode trace $CLI experimental air cancel 123
17+
18+
title "register-image"
19+
errcode trace $CLI experimental air register-image my-image:latest
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Local = true
2+
Cloud = false
3+
4+
# Stubs fail locally before any API call, so no server stubs needed.
5+
[EnvMatrix]
6+
DATABRICKS_BUNDLE_ENGINE = []

cmd/experimental/air/air.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package air
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/spf13/cobra"
7+
)
8+
9+
// New returns the root command for the experimental AI runtime CLI.
10+
//
11+
// Milestone 0: scaffolds the command group with every subcommand registered as a
12+
// stub (not yet implemented), pending the port from the Python `air` CLI.
13+
func New() *cobra.Command {
14+
cmd := &cobra.Command{
15+
Use: "air",
16+
Short: "Run and manage AI runtime training workloads",
17+
Long: `Run and manage AI runtime training workloads on Databricks serverless GPU compute.
18+
19+
This command set is the Go port of the standalone Python "air" CLI. It is
20+
experimental and may change in future versions.`,
21+
}
22+
23+
cmd.AddCommand(newRunCommand())
24+
cmd.AddCommand(newStatusCommand())
25+
cmd.AddCommand(newListCommand())
26+
cmd.AddCommand(newLogsCommand())
27+
cmd.AddCommand(newCancelCommand())
28+
cmd.AddCommand(newRegisterImageCommand())
29+
30+
return cmd
31+
}
32+
33+
// notImplemented returns the placeholder error used by milestone-0 stubs.
34+
func notImplemented(name string) error {
35+
return fmt.Errorf("`air %s` is not implemented yet", name)
36+
}

cmd/experimental/air/air_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package air
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
)
8+
9+
// TestNewRegistersAllSubcommands asserts the `ai` command wires up every
10+
// expected subcommand, so none is accidentally dropped from New.
11+
func TestNewRegistersAllSubcommands(t *testing.T) {
12+
registered := make(map[string]bool)
13+
for _, c := range New().Commands() {
14+
registered[c.Name()] = true
15+
}
16+
17+
want := []string{"run", "status", "list", "logs", "cancel", "register-image"}
18+
for _, name := range want {
19+
assert.True(t, registered[name], "subcommand %q is not registered", name)
20+
}
21+
assert.Len(t, registered, len(want), "unexpected number of subcommands")
22+
}

cmd/experimental/air/cancel.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package air
2+
3+
import (
4+
"github.com/spf13/cobra"
5+
)
6+
7+
func newCancelCommand() *cobra.Command {
8+
var (
9+
all bool
10+
yes bool
11+
)
12+
13+
cmd := &cobra.Command{
14+
Use: "cancel [RUN_ID...]",
15+
Args: cobra.ArbitraryArgs,
16+
Short: "Cancel one or more runs",
17+
Long: `Cancel one or more runs by ID, or cancel all of your active runs with --all.`,
18+
RunE: func(cmd *cobra.Command, args []string) error {
19+
return notImplemented("cancel")
20+
},
21+
}
22+
23+
cmd.Flags().BoolVar(&all, "all", false, "Cancel all of your active runs")
24+
cmd.Flags().BoolVarP(&yes, "yes", "y", false, "Skip the confirmation prompt")
25+
26+
return cmd
27+
}

cmd/experimental/air/list.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package air
2+
3+
import (
4+
"github.com/databricks/cli/cmd/root"
5+
"github.com/spf13/cobra"
6+
)
7+
8+
func newListCommand() *cobra.Command {
9+
var (
10+
limit int
11+
active bool
12+
allUsers bool
13+
filters []string
14+
)
15+
16+
cmd := &cobra.Command{
17+
Use: "list",
18+
Args: root.NoArgs,
19+
Short: "List recent runs",
20+
RunE: func(cmd *cobra.Command, args []string) error {
21+
return notImplemented("list")
22+
},
23+
}
24+
25+
cmd.Flags().IntVar(&limit, "limit", 20, "Maximum number of runs to show")
26+
cmd.Flags().BoolVar(&active, "active", false, "Show only active runs")
27+
cmd.Flags().BoolVar(&allUsers, "all-users", false, "Show runs from all users")
28+
cmd.Flags().StringArrayVar(&filters, "filter", nil, "Filter runs, e.g. experiment=foo* (repeatable)")
29+
30+
return cmd
31+
}

cmd/experimental/air/logs.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package air
2+
3+
import (
4+
"github.com/databricks/cli/cmd/root"
5+
"github.com/spf13/cobra"
6+
)
7+
8+
func newLogsCommand() *cobra.Command {
9+
var (
10+
node int
11+
lines int
12+
retry int
13+
downloadTo string
14+
review bool
15+
)
16+
17+
cmd := &cobra.Command{
18+
Use: "logs RUN_ID",
19+
Args: root.ExactArgs(1),
20+
Short: "Stream or fetch logs for a run",
21+
Long: `Stream logs from an active run, or fetch logs from a completed run.`,
22+
RunE: func(cmd *cobra.Command, args []string) error {
23+
return notImplemented("logs")
24+
},
25+
}
26+
27+
cmd.Flags().IntVar(&node, "node", 0, "Fetch logs from this node")
28+
cmd.Flags().IntVar(&lines, "lines", 10000, "For completed runs, print the last N lines")
29+
cmd.Flags().IntVar(&retry, "retry", -1, "View logs from a specific retry attempt (default: latest)")
30+
cmd.Flags().StringVar(&downloadTo, "download-to", "", "Download all logs to this directory instead of printing")
31+
cmd.Flags().BoolVar(&review, "review", false, "Download logs from all nodes and filter for error signatures")
32+
33+
return cmd
34+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package air
2+
3+
import (
4+
"github.com/databricks/cli/cmd/root"
5+
"github.com/spf13/cobra"
6+
)
7+
8+
func newRegisterImageCommand() *cobra.Command {
9+
var (
10+
scope string
11+
key string
12+
interactiveAuth bool
13+
tagPolicy string
14+
timeoutMinutes int
15+
)
16+
17+
cmd := &cobra.Command{
18+
Use: "register-image IMAGE_URL",
19+
Args: root.ExactArgs(1),
20+
Short: "Mirror a Docker image into the workspace registry",
21+
RunE: func(cmd *cobra.Command, args []string) error {
22+
return notImplemented("register-image")
23+
},
24+
}
25+
26+
cmd.Flags().StringVar(&scope, "scope", "", "Databricks secret scope holding registry credentials")
27+
cmd.Flags().StringVar(&key, "key", "", "Databricks secret key holding registry credentials")
28+
cmd.Flags().BoolVar(&interactiveAuth, "interactive-authenticate", false, "Prompt for registry credentials and store them as a secret")
29+
cmd.Flags().StringVar(&tagPolicy, "tag-policy", "auto", "Image resolution policy: auto or latest")
30+
cmd.Flags().IntVar(&timeoutMinutes, "timeout-minutes", 60, "Timeout to wait for the image to become available")
31+
32+
return cmd
33+
}

0 commit comments

Comments
 (0)