Skip to content

AIR CLI Integration: Scaffold experimental AIR CLI command package#5564

Open
riddhibhagwat-db wants to merge 2 commits into
mainfrom
air-integration-m0
Open

AIR CLI Integration: Scaffold experimental AIR CLI command package#5564
riddhibhagwat-db wants to merge 2 commits into
mainfrom
air-integration-m0

Conversation

@riddhibhagwat-db

Copy link
Copy Markdown

Changes

  • New cmd/experimental/air/ package containing an air parent command plus 7 stub subcommands: run, status, list, logs, cancel, register-image
  • currently, all subcommands return an air is not implemented yet error with representative flags mapped from the Python CLI. Registered under the hidden experimental group.
  • tools/list_embeds.py: text=True was changed to universal_newlines=True so the acceptance harness runs on Python 3.6. General tooling fix.

Why

The AI runtime CLI ships today as a separately installed Python wheel with its own auth, output, and packaging. Folding it into the main Go CLI gives users one databricks install with consistent profiles, authentication, and -o json output, and removes a parallel toolchain to maintain. Landing the package scaffold first lets the individual commands be ported in small, reviewable PRs (status is next) instead of one large drop. Every stub is wired and navigable, so the command tree and registration are reviewable now without functional code.

Tests

  • Unit (cmd/experimental/air/): New() registers all six subcommands; each stub returns the not-implemented error.
  • Acceptance (acceptance/experimental/air/unimplemented/): runs every stub end-to-end and asserts the message + non-zero exit.

test with:
go test ./cmd/experimental/air/...
go test ./acceptance -run 'TestAccept/experimental/air'

subprocess's text= keyword was added in 3.7; universal_newlines is the exact
equivalent and also works on older interpreters. Unblocks running the acceptance
suite on a Python 3.6 host.

Co-authored-by: Isaac
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
@github-actions

Copy link
Copy Markdown
Contributor

Waiting for approval

Based on git history, these people are best suited to review:

  • @simonfaltum -- recent work in cmd/experimental/

Eligible reviewers: @andrewnester, @anton-107, @denik, @pietern, @renaudhartert-db, @shreyas-goenka

Suggestions based on git history. See OWNERS for ownership rules.

@eng-dev-ecosystem-bot

Copy link
Copy Markdown
Collaborator

Commit: 0474207

Run: 27378673078

Env 🟨​KNOWN 💚​RECOVERED 🙈​SKIP ✅​pass 🙈​skip Time
🟨​ aws linux 7 15 264 972 7:34
🟨​ aws windows 7 15 266 970 17:06
💚​ aws-ucws linux 7 15 360 886 10:15
💚​ aws-ucws windows 7 15 362 884 12:33
💚​ azure linux 1 17 267 970 7:01
💚​ azure windows 1 17 269 968 11:23
💚​ azure-ucws linux 1 17 365 882 7:44
💚​ azure-ucws windows 1 17 367 880 12:43
💚​ gcp linux 1 17 263 973 8:51
💚​ gcp windows 1 17 265 971 11:46
22 interesting tests: 15 SKIP, 7 KNOWN
Test Name aws linux aws windows aws-ucws linux aws-ucws windows azure linux azure windows azure-ucws linux azure-ucws windows gcp linux gcp windows
🟨​ TestAccept 🟨​K 🟨​K 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
🙈​ TestAccept/bundle/invariant/no_drift 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/permissions 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions 🟨​K 🟨​K 💚​R 💚​R 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions/DATABRICKS_BUNDLE_ENGINE=direct 🟨​K 🟨​K 💚​R 💚​R
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions/DATABRICKS_BUNDLE_ENGINE=terraform 🟨​K 🟨​K 💚​R 💚​R
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions 🟨​K 🟨​K 💚​R 💚​R 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions/DATABRICKS_BUNDLE_ENGINE=direct 🟨​K 🟨​K 💚​R 💚​R
🟨​ TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions/DATABRICKS_BUNDLE_ENGINE=terraform 🟨​K 🟨​K 💚​R 💚​R
🙈​ TestAccept/bundle/resources/postgres_branches/basic 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/recreate 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/replace_existing 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/update_protected 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_branches/without_branch_id 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_endpoints/basic 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_endpoints/recreate 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/postgres_projects/update_display_name 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/synced_database_tables/basic 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/vector_search_endpoints/drift/recreated_same_name 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/vector_search_indexes/basic 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/vector_search_indexes/grants/select 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/ssh/connection 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
Top 28 slowest tests (at least 2 minutes):
duration env testname
6:21 gcp windows TestAccept
6:14 aws-ucws windows TestAccept
6:04 azure-ucws windows TestAccept
6:00 azure windows TestAccept
5:23 gcp linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
5:05 gcp windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
4:35 aws-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
4:12 gcp linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
4:05 gcp windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:37 aws-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:25 azure-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:25 azure linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:20 aws-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:20 aws-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:08 azure windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:06 azure windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:03 aws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:03 azure-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:57 gcp linux TestAccept
2:54 azure linux TestAccept
2:51 azure-ucws linux TestAccept
2:51 azure linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:50 aws-ucws linux TestAccept
2:48 aws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:41 aws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
2:37 azure-ucws windows TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:35 aws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
2:32 azure-ucws linux TestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct

@simonfaltum simonfaltum left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the scaffold. The Go code itself is in good shape and the acceptance setup follows the existing patterns (the EnvMatrix override and the committed out.test.toml are exactly right). Requesting changes for three things:

  1. The tools/list_embeds.py change needs to come out, see the inline comment. It's unrelated to this PR and the stated rationale doesn't match the repo.
  2. Package location should follow the established experimental layout (experimental/air/cmd), see the inline comment.
  3. The description needs fixing: it says 7 stub subcommands but lists and implements 6 (your own Tests section says six). Also drop the list_embeds.py bullet together with that change.

Two questions:

  • Which Python air CLI source/version were the flags mapped from? Please link it in the description; flag parity isn't verifiable from this repo.
  • Was a seventh subcommand intentionally dropped, or is "7" a typo?

The remaining inline comments (test assertion, help case, --retry help text, cancel args, test.toml defaults) are all quick fixes.

Comment thread tools/list_embeds.py
out = subprocess.check_output(
["git", "grep", "--no-color", "-E", "^" + EMBED, "--", "*.go"],
text=True,
universal_newlines=True,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change doesn't belong in this PR and the rationale doesn't hold up. This script isn't part of the acceptance harness, it's invoked by the Taskfile (EMBED_SOURCES var). The repo's Python floor is also way above 3.6: the tools/ scripts declare requires-python = ">=3.12", CI runs 3.13, and tools/check_deadcode.py plus several acceptance/bin/ scripts still use text=True, so this change alone wouldn't buy 3.6 compatibility anyway. universal_newlines is the legacy alias that text replaced in 3.7.

Please drop this file from the PR (one PR = one change). If ./task fails on your machine because of an old python3, the fix is upgrading your local Python.

package experimental

import (
"github.com/databricks/cli/cmd/experimental/air"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The established layout for experimental features is experimental/<name>/cmd: that's where aitools, genie and postgres live, and cmd/experimental/ only owns the dispatcher plus the single-file workspace_open command. AIR is going to grow real implementation code over the next milestones, so please move this package to experimental/air/cmd (imported as aircmd here). Moving later only gets more expensive as milestones stack on top.

One catch to take care of in the same PR: TEST_PACKAGES in Taskfile.yml covers ./cmd/... but not ./experimental/... (only ssh), so add ./experimental/air/... to it, otherwise the unit tests silently stop running after the move. Update the go test path in the description's Tests section too.

t.Run(name, func(t *testing.T) {
require.NotNil(t, cmd.RunE, "command should define RunE")
err := cmd.RunE(cmd, nil)
assert.ErrorContains(t, err, "not implemented")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This passes even if a stub returns the wrong name, i.e. if cancel.go copy-pasted notImplemented("list") this test wouldn't notice. You have the name as the map key, so assert the full message:

assert.EqualError(t, err, fmt.Sprintf("`air %s` is not implemented yet", name))

errcode trace $CLI experimental air cancel 123

title "register-image"
errcode trace $CLI experimental air register-image my-image:latest

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR's stated goal is making the command tree reviewable, so let's pin it in the acceptance output. Add a help case and the tree, short descriptions and flags all land in output.txt, then any future change shows up as a diff:

title "help"
trace $CLI experimental air --help


cmd.Flags().IntVar(&node, "node", 0, "Fetch logs from this node")
cmd.Flags().IntVar(&lines, "lines", 10000, "For completed runs, print the last N lines")
cmd.Flags().IntVar(&retry, "retry", -1, "View logs from a specific retry attempt (default: latest)")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pflag appends its own marker for non-zero defaults, so the help renders a double default (checked against a local build):

--retry int   View logs from a specific retry attempt (default: latest) (default -1)

Reword to fold the sentinel in, something like "View logs from a specific retry attempt; -1 means latest".


cmd := &cobra.Command{
Use: "cancel [RUN_ID...]",
Args: cobra.ArbitraryArgs,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cobra.ArbitraryArgs accepts air cancel with no IDs and no --all, and also --all combined with explicit IDs. It doesn't matter while this is a stub, but the arg contract is part of what this PR puts up for review. Either add a small Args validator now (return root.InvalidArgsError like the helpers in cmd/root/args.go, so the usage string gets printed) or leave an explicit TODO for the implementation PR.

@@ -0,0 +1,6 @@
Local = true

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Local = true and Cloud = false are already the defaults from the root acceptance/test.toml, and config is inherited (the genie test next door omits them). Keep just the [EnvMatrix] override and its comment.

"github.com/stretchr/testify/assert"
)

// TestNewRegistersAllSubcommands asserts the `ai` command wires up every

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: ai should be air.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants