From 96e0aadfeda22b7ccdb7f588afcf655ac3860aa4 Mon Sep 17 00:00:00 2001 From: Shreyas Goenka Date: Fri, 22 May 2026 11:08:01 +0000 Subject: [PATCH 1/4] bundle: surface read-only DMS commands under DAB sub-groups The SDK v0.135 added a workspace-level `bundle` (Deployment Metadata Service) whose auto-generated cobra commands live at cmd/workspace/bundle/. The previous PR (#5311) filters that workspace root out of top-level registration because `bundle` collides with the DAB command tree. This commit brings the read-side verbs back, grouped under the noun parents under `databricks bundle`: databricks bundle deployment {get, list} databricks bundle version {get, list} databricks bundle resource {get, list} databricks bundle operation {get, list} Aliases (`deployments`, `versions`, `resources`, `operations`) are attached on each group so cobra renders the noun/nouns pair in the help header and either form routes the same way. Mutating verbs (create-deployment, create-version, create-operation, delete-deployment, complete-version, heartbeat) are intentionally not surfaced -- they have no user-facing workflow yet and stay in the filtered-out workspace tree. The `deployment` group is additive: the new read-side verbs sit alongside the existing `bind`, `unbind`, `migrate` from cmd/bundle/deployment/. Help output renders both sets together with the alias header on top. Implementation lives in cmd/bundle/metadata_service.go: a small helper calls `workspacebundle.New()` once, detaches each subcommand from the (discarded) workspace root, and exposes them via a map keyed by their original cobra Name. cmd/bundle/bundle.go pulls only the four read-side entries from the map and renames each from `-` to `` via `renameTo`, which preserves the trailing positional-arg syntax that cobra renders in usage strings. Co-authored-by: Isaac --- cmd/bundle/bundle.go | 49 +++++++++++++++++++++++++++++++++- cmd/bundle/metadata_service.go | 42 +++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 cmd/bundle/metadata_service.go diff --git a/cmd/bundle/bundle.go b/cmd/bundle/bundle.go index 3f4985c2480..b6bf83012f6 100644 --- a/cmd/bundle/bundle.go +++ b/cmd/bundle/bundle.go @@ -36,9 +36,56 @@ Online documentation: https://docs.databricks.com/en/dev-tools/bundles/index.htm cmd.AddCommand(newSummaryCommand()) cmd.AddCommand(newGenerateCommand()) cmd.AddCommand(newDebugCommand()) - cmd.AddCommand(deployment.NewDeploymentCommand()) cmd.AddCommand(newOpenCommand()) cmd.AddCommand(newPlanCommand()) cmd.AddCommand(newConfigRemoteSyncCommand()) + + // Bundle Metadata Service (DMS) read-only command groups. Only `get` + // and `list` are surfaced here; mutating verbs (create/delete/heartbeat/ + // complete) are not user-facing yet and stay in the auto-generated + // `cmd/workspace/bundle` tree (which is filtered out of top-level + // registration in cmd/cmd.go). + // + // Each group uses the singular noun as the primary `Use` and aliases the + // plural for discoverability; cobra renders the alias pair in the help + // header so callers see both forms. + dms := metadataServiceCommands() + + // The DAB `deployment` group already exists for bind/unbind/migrate. + // Augment it additively with the DMS read-side verbs and add the + // `deployments` alias. + deploymentCmd := deployment.NewDeploymentCommand() + deploymentCmd.Aliases = append(deploymentCmd.Aliases, "deployments") + deploymentCmd.AddCommand(renameTo(dms["get-deployment"], "get")) + deploymentCmd.AddCommand(renameTo(dms["list-deployments"], "list")) + cmd.AddCommand(deploymentCmd) + + versionCmd := &cobra.Command{ + Use: "version", + Aliases: []string{"versions"}, + Short: "Read version records in the bundle metadata service.", + } + versionCmd.AddCommand(renameTo(dms["get-version"], "get")) + versionCmd.AddCommand(renameTo(dms["list-versions"], "list")) + cmd.AddCommand(versionCmd) + + resourceCmd := &cobra.Command{ + Use: "resource", + Aliases: []string{"resources"}, + Short: "Read resource records from the bundle metadata service.", + } + resourceCmd.AddCommand(renameTo(dms["get-resource"], "get")) + resourceCmd.AddCommand(renameTo(dms["list-resources"], "list")) + cmd.AddCommand(resourceCmd) + + operationCmd := &cobra.Command{ + Use: "operation", + Aliases: []string{"operations"}, + Short: "Read operation records in the bundle metadata service.", + } + operationCmd.AddCommand(renameTo(dms["get-operation"], "get")) + operationCmd.AddCommand(renameTo(dms["list-operations"], "list")) + cmd.AddCommand(operationCmd) + return cmd } diff --git a/cmd/bundle/metadata_service.go b/cmd/bundle/metadata_service.go new file mode 100644 index 00000000000..80836e7cf3c --- /dev/null +++ b/cmd/bundle/metadata_service.go @@ -0,0 +1,42 @@ +package bundle + +import ( + "strings" + + workspacebundle "github.com/databricks/cli/cmd/workspace/bundle" + "github.com/spf13/cobra" +) + +// metadataServiceCommands returns the auto-generated workspace bundle service +// commands keyed by their original cobra Name (e.g. "get-deployment"). +// +// The auto-generated `databricks bundle ` namespace collides with the +// DAB `bundle` command tree; cmd/cmd.go filters the workspace bundle root out +// of top-level registration. Here we call into the workspace package once, +// detach each subcommand from its (discarded) parent, and let the DAB bundle +// re-attach them under proper sub-groups with shorter names. +func metadataServiceCommands() map[string]*cobra.Command { + ws := workspacebundle.New() + subs := ws.Commands() + out := make(map[string]*cobra.Command, len(subs)) + for _, sub := range subs { + ws.RemoveCommand(sub) + // These ride under the DAB bundle now, which is visible. + sub.Hidden = false + out[sub.Name()] = sub + } + return out +} + +// renameTo replaces the first whitespace-separated token of cobra's Use field +// with newName, preserving the trailing positional-arg syntax that cobra renders +// in usage strings (e.g. "get-deployment NAME" -> "get NAME"). Returns the +// command for inline chaining. +func renameTo(c *cobra.Command, newName string) *cobra.Command { + rest := "" + if i := strings.IndexByte(c.Use, ' '); i >= 0 { + rest = c.Use[i:] + } + c.Use = newName + rest + return c +} From 7f3f62d2eba98edd5dffd231acabb27cc1289755 Mon Sep 17 00:00:00 2001 From: Shreyas Goenka Date: Fri, 22 May 2026 11:29:53 +0000 Subject: [PATCH 2/4] acc: refresh bundle/help goldens for new DMS sub-groups The previous commit adds `operation`, `resource`, `version` as new top-level rows in `databricks bundle --help`, and `get`/`list` as new verbs under `bundle deployment`. Update the two `bundle/help` golden outputs to match (test was passing under -update; verified with a re-run without -update). Co-authored-by: Isaac --- acceptance/bundle/help/bundle-deployment/output.txt | 5 +++++ acceptance/bundle/help/bundle/output.txt | 3 +++ 2 files changed, 8 insertions(+) diff --git a/acceptance/bundle/help/bundle-deployment/output.txt b/acceptance/bundle/help/bundle-deployment/output.txt index a135735cd44..34c99d7db85 100644 --- a/acceptance/bundle/help/bundle-deployment/output.txt +++ b/acceptance/bundle/help/bundle-deployment/output.txt @@ -19,8 +19,13 @@ After binding, the existing workspace resource will be managed by your bundle. Usage: databricks bundle deployment [command] +Aliases: + deployment, deployments + Available Commands: bind Bind bundle-defined resources to existing resources + get Get a deployment. + list List deployments. migrate Migrate from Terraform to Direct deployment engine unbind Unbind bundle-defined resources from its managed remote resource diff --git a/acceptance/bundle/help/bundle/output.txt b/acceptance/bundle/help/bundle/output.txt index 624e18db9ca..715c7a6045e 100644 --- a/acceptance/bundle/help/bundle/output.txt +++ b/acceptance/bundle/help/bundle/output.txt @@ -24,12 +24,15 @@ Available Commands: generate Generate bundle configuration init Initialize using a bundle template open Open a resource in the browser + operation Read operation records in the bundle metadata service. plan Show deployment plan + resource Read resource records from the bundle metadata service. run Run a job, pipeline update or app schema Generate JSON Schema for bundle configuration summary Summarize resources deployed by this bundle sync Synchronize bundle tree to the workspace validate Validate configuration + version Read version records in the bundle metadata service. Flags: -h, --help help for bundle From dcb1b3064cb5e758e0a85ea09afa2eec41d73ba0 Mon Sep 17 00:00:00 2001 From: Shreyas Goenka Date: Fri, 22 May 2026 13:28:54 +0000 Subject: [PATCH 3/4] bundle: drop plural aliases from DMS sub-groups for now Removes the `deployments`/`versions`/`resources`/`operations` plural aliases from the four sub-groups. Cobra still routes the singular form (matching the SDK / API convention); we can revisit aliasing once the read-only surface lands and we see what users prefer. `bundle-deployment` help golden refreshed -- the `Aliases:` header in the help output is what changes. Co-authored-by: Isaac --- .../bundle/help/bundle-deployment/output.txt | 3 --- cmd/bundle/bundle.go | 23 ++++++------------- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/acceptance/bundle/help/bundle-deployment/output.txt b/acceptance/bundle/help/bundle-deployment/output.txt index 34c99d7db85..558d10850e4 100644 --- a/acceptance/bundle/help/bundle-deployment/output.txt +++ b/acceptance/bundle/help/bundle-deployment/output.txt @@ -19,9 +19,6 @@ After binding, the existing workspace resource will be managed by your bundle. Usage: databricks bundle deployment [command] -Aliases: - deployment, deployments - Available Commands: bind Bind bundle-defined resources to existing resources get Get a deployment. diff --git a/cmd/bundle/bundle.go b/cmd/bundle/bundle.go index b6bf83012f6..5ed4e6dc8e1 100644 --- a/cmd/bundle/bundle.go +++ b/cmd/bundle/bundle.go @@ -45,43 +45,34 @@ Online documentation: https://docs.databricks.com/en/dev-tools/bundles/index.htm // complete) are not user-facing yet and stay in the auto-generated // `cmd/workspace/bundle` tree (which is filtered out of top-level // registration in cmd/cmd.go). - // - // Each group uses the singular noun as the primary `Use` and aliases the - // plural for discoverability; cobra renders the alias pair in the help - // header so callers see both forms. dms := metadataServiceCommands() // The DAB `deployment` group already exists for bind/unbind/migrate. - // Augment it additively with the DMS read-side verbs and add the - // `deployments` alias. + // Augment it additively with the DMS read-side verbs. deploymentCmd := deployment.NewDeploymentCommand() - deploymentCmd.Aliases = append(deploymentCmd.Aliases, "deployments") deploymentCmd.AddCommand(renameTo(dms["get-deployment"], "get")) deploymentCmd.AddCommand(renameTo(dms["list-deployments"], "list")) cmd.AddCommand(deploymentCmd) versionCmd := &cobra.Command{ - Use: "version", - Aliases: []string{"versions"}, - Short: "Read version records in the bundle metadata service.", + Use: "version", + Short: "Read version records in the bundle metadata service.", } versionCmd.AddCommand(renameTo(dms["get-version"], "get")) versionCmd.AddCommand(renameTo(dms["list-versions"], "list")) cmd.AddCommand(versionCmd) resourceCmd := &cobra.Command{ - Use: "resource", - Aliases: []string{"resources"}, - Short: "Read resource records from the bundle metadata service.", + Use: "resource", + Short: "Read resource records from the bundle metadata service.", } resourceCmd.AddCommand(renameTo(dms["get-resource"], "get")) resourceCmd.AddCommand(renameTo(dms["list-resources"], "list")) cmd.AddCommand(resourceCmd) operationCmd := &cobra.Command{ - Use: "operation", - Aliases: []string{"operations"}, - Short: "Read operation records in the bundle metadata service.", + Use: "operation", + Short: "Read operation records in the bundle metadata service.", } operationCmd.AddCommand(renameTo(dms["get-operation"], "get")) operationCmd.AddCommand(renameTo(dms["list-operations"], "list")) From 5f4b668b868f5b3b889770abfec6e61e50d6b91a Mon Sep 17 00:00:00 2001 From: Shreyas Goenka Date: Fri, 22 May 2026 13:33:14 +0000 Subject: [PATCH 4/4] acc: add local-only acceptance test for read-only DMS bundle commands Eight stubbed REST endpoints and one consolidated script exercise the new `bundle {deployment,version,resource,operation} {get,list}` commands end to end against the local testserver. The DMS APIs aren't on test workspaces yet, so this test is `Cloud = false` -- it only runs in the in-process matrix. Stubbed response shapes match the SDK v0.136 `bundle` service models; the golden captures the rendered output for each command in order: list-then-get for each of the four nouns. Co-authored-by: Isaac --- .../cmd/bundle/dms-read-only/out.test.toml | 3 + .../cmd/bundle/dms-read-only/output.txt | 81 ++++++++++++ acceptance/cmd/bundle/dms-read-only/script | 8 ++ acceptance/cmd/bundle/dms-read-only/test.toml | 117 ++++++++++++++++++ 4 files changed, 209 insertions(+) create mode 100644 acceptance/cmd/bundle/dms-read-only/out.test.toml create mode 100644 acceptance/cmd/bundle/dms-read-only/output.txt create mode 100644 acceptance/cmd/bundle/dms-read-only/script create mode 100644 acceptance/cmd/bundle/dms-read-only/test.toml diff --git a/acceptance/cmd/bundle/dms-read-only/out.test.toml b/acceptance/cmd/bundle/dms-read-only/out.test.toml new file mode 100644 index 00000000000..f784a183258 --- /dev/null +++ b/acceptance/cmd/bundle/dms-read-only/out.test.toml @@ -0,0 +1,3 @@ +Local = true +Cloud = false +EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["terraform", "direct"] diff --git a/acceptance/cmd/bundle/dms-read-only/output.txt b/acceptance/cmd/bundle/dms-read-only/output.txt new file mode 100644 index 00000000000..6b702e746e3 --- /dev/null +++ b/acceptance/cmd/bundle/dms-read-only/output.txt @@ -0,0 +1,81 @@ + +>>> [CLI] bundle deployment list +[ + { + "display_name": "first deployment", + "name": "deployments/abc", + "status": "DEPLOYMENT_STATUS_ACTIVE", + "target_name": "dev" + }, + { + "display_name": "second deployment", + "name": "deployments/def", + "status": "DEPLOYMENT_STATUS_ACTIVE", + "target_name": "prod" + } +] + +>>> [CLI] bundle deployment get deployments/abc +{ + "display_name": "first deployment", + "last_version_id": "v1", + "name": "deployments/abc", + "status": "DEPLOYMENT_STATUS_ACTIVE", + "target_name": "dev" +} + +>>> [CLI] bundle version list deployments/abc +[ + { + "cli_version": "[DEV_VERSION]", + "name": "deployments/abc/versions/v1", + "status": "VERSION_STATUS_COMPLETED", + "version_type": "" + } +] + +>>> [CLI] bundle version get deployments/abc/versions/v1 +{ + "cli_version": "[DEV_VERSION]", + "name": "deployments/abc/versions/v1", + "status": "VERSION_STATUS_COMPLETED", + "version_type": "" +} + +>>> [CLI] bundle resource list deployments/abc +[ + { + "last_action_type": "OPERATION_ACTION_TYPE_CREATE", + "last_version_id": "v1", + "name": "deployments/abc/resources/my_job", + "resource_id": "12345", + "resource_type": "DEPLOYMENT_RESOURCE_TYPE_JOB" + } +] + +>>> [CLI] bundle resource get deployments/abc/resources/my_job +{ + "last_action_type": "OPERATION_ACTION_TYPE_CREATE", + "last_version_id": "v1", + "name": "deployments/abc/resources/my_job", + "resource_id": "12345", + "resource_type": "DEPLOYMENT_RESOURCE_TYPE_JOB" +} + +>>> [CLI] bundle operation list deployments/abc/versions/v1 +[ + { + "action_type": "OPERATION_ACTION_TYPE_CREATE", + "name": "deployments/abc/versions/v1/operations/my_job", + "resource_id": "12345", + "status": "OPERATION_STATUS_SUCCEEDED" + } +] + +>>> [CLI] bundle operation get deployments/abc/versions/v1/operations/my_job +{ + "action_type": "OPERATION_ACTION_TYPE_CREATE", + "name": "deployments/abc/versions/v1/operations/my_job", + "resource_id": "12345", + "status": "OPERATION_STATUS_SUCCEEDED" +} diff --git a/acceptance/cmd/bundle/dms-read-only/script b/acceptance/cmd/bundle/dms-read-only/script new file mode 100644 index 00000000000..1a39de6a77d --- /dev/null +++ b/acceptance/cmd/bundle/dms-read-only/script @@ -0,0 +1,8 @@ +trace $CLI bundle deployment list +trace $CLI bundle deployment get deployments/abc +trace $CLI bundle version list deployments/abc +trace $CLI bundle version get deployments/abc/versions/v1 +trace $CLI bundle resource list deployments/abc +trace $CLI bundle resource get deployments/abc/resources/my_job +trace $CLI bundle operation list deployments/abc/versions/v1 +trace $CLI bundle operation get deployments/abc/versions/v1/operations/my_job diff --git a/acceptance/cmd/bundle/dms-read-only/test.toml b/acceptance/cmd/bundle/dms-read-only/test.toml new file mode 100644 index 00000000000..b7a8cbd5901 --- /dev/null +++ b/acceptance/cmd/bundle/dms-read-only/test.toml @@ -0,0 +1,117 @@ +# Local-only acceptance test for the read-only DMS commands under +# `databricks bundle {deployment,version,resource,operation}`. The DMS APIs +# aren't on test workspaces yet, so we stub the eight read endpoints with +# fixed response bodies and assert the CLI renders them as expected. +Local = true +Cloud = false + +[[Server]] +Pattern = "GET /api/2.0/bundle/deployments" +Response.Body = ''' +{ + "deployments": [ + { + "name": "deployments/abc", + "display_name": "first deployment", + "target_name": "dev", + "status": "DEPLOYMENT_STATUS_ACTIVE" + }, + { + "name": "deployments/def", + "display_name": "second deployment", + "target_name": "prod", + "status": "DEPLOYMENT_STATUS_ACTIVE" + } + ] +} +''' + +[[Server]] +Pattern = "GET /api/2.0/bundle/deployments/abc" +Response.Body = ''' +{ + "name": "deployments/abc", + "display_name": "first deployment", + "target_name": "dev", + "status": "DEPLOYMENT_STATUS_ACTIVE", + "last_version_id": "v1" +} +''' + +[[Server]] +Pattern = "GET /api/2.0/bundle/deployments/abc/versions" +Response.Body = ''' +{ + "versions": [ + { + "name": "deployments/abc/versions/v1", + "cli_version": "0.0.0-dev", + "status": "VERSION_STATUS_COMPLETED" + } + ] +} +''' + +[[Server]] +Pattern = "GET /api/2.0/bundle/deployments/abc/versions/v1" +Response.Body = ''' +{ + "name": "deployments/abc/versions/v1", + "cli_version": "0.0.0-dev", + "status": "VERSION_STATUS_COMPLETED" +} +''' + +[[Server]] +Pattern = "GET /api/2.0/bundle/deployments/abc/resources" +Response.Body = ''' +{ + "resources": [ + { + "name": "deployments/abc/resources/my_job", + "resource_id": "12345", + "resource_type": "DEPLOYMENT_RESOURCE_TYPE_JOB", + "last_version_id": "v1", + "last_action_type": "OPERATION_ACTION_TYPE_CREATE" + } + ] +} +''' + +[[Server]] +Pattern = "GET /api/2.0/bundle/deployments/abc/resources/my_job" +Response.Body = ''' +{ + "name": "deployments/abc/resources/my_job", + "resource_id": "12345", + "resource_type": "DEPLOYMENT_RESOURCE_TYPE_JOB", + "last_version_id": "v1", + "last_action_type": "OPERATION_ACTION_TYPE_CREATE" +} +''' + +[[Server]] +Pattern = "GET /api/2.0/bundle/deployments/abc/versions/v1/operations" +Response.Body = ''' +{ + "operations": [ + { + "name": "deployments/abc/versions/v1/operations/my_job", + "action_type": "OPERATION_ACTION_TYPE_CREATE", + "resource_id": "12345", + "status": "OPERATION_STATUS_SUCCEEDED" + } + ] +} +''' + +[[Server]] +Pattern = "GET /api/2.0/bundle/deployments/abc/versions/v1/operations/my_job" +Response.Body = ''' +{ + "name": "deployments/abc/versions/v1/operations/my_job", + "action_type": "OPERATION_ACTION_TYPE_CREATE", + "resource_id": "12345", + "status": "OPERATION_STATUS_SUCCEEDED" +} +'''