Skip to content

Send X-Databricks-Workspace-Id on workspace-routed API calls#5368

Open
Divyansh-db wants to merge 4 commits into
mainfrom
new-workspace-parameter
Open

Send X-Databricks-Workspace-Id on workspace-routed API calls#5368
Divyansh-db wants to merge 4 commits into
mainfrom
new-workspace-parameter

Conversation

@Divyansh-db
Copy link
Copy Markdown

Summary

On unified Databricks hosts that serve multiple workspaces, the CLI sends a routing header so the gateway can dispatch each request to the correct workspace. The platform is consolidating workspace addressing onto a single header name. This PR switches the header sent on workspace-scoped API calls from X-Databricks-Org-Id to X-Databricks-Workspace-Id. The previous header continues to be accepted by the platform, so older CLI versions keep working.

The value continues to come from the workspace_id config field or DATABRICKS_WORKSPACE_ID environment variable.

Scope

Hand-written CLI paths that issue workspace-routed API calls without going through generated SDK service methods:

  • databricks api {verb} (cmd/api/api.go)
  • Files API filer (libs/filer/files_client.go)
  • Workspace files filer (libs/filer/workspace_files_client.go)
  • Telemetry uploads (libs/telemetry/logger.go)

The matching change inside the SDK landed in databricks/databricks-sdk-go#1688 and will reach generated service methods on the next SDK bump.

Asymmetric migration

Only the request-side header flips. The SDK's CurrentWorkspaceID() still reads X-Databricks-Org-Id from the response on /api/2.0/preview/scim/v2/Me, because the server continues to echo the legacy response header. The two CLI test fakes that support that flow stay on the legacy name intentionally:

  • libs/testserver/handlers.go/Me mock response header
  • libs/testproxy/server.goincludeResponseHeaders for the proxy

Test plan

  • go test ./cmd/api/... ./libs/filer/... ./libs/telemetry/... — green
  • go test ./acceptance -run 'TestAccept/cmd/api|TestAccept/telemetry/(failure|timeout|partial)' — green (acceptance fixtures regenerated via -update)
  • ./task lint-q — 0 issues; ./task fmt — no changes
  • git grep -in 'X-Databricks-Org' -- ':!*.md' ':!*.sum' ':!bundle/' — only the two intentional response-side fakes plus a context comment in cmd/api/api.go

On unified Databricks hosts that serve multiple workspaces, the CLI sends a
routing header so the gateway can dispatch each request to the correct
workspace. The platform is consolidating workspace addressing onto a single
header name. Switch the header sent on workspace-scoped API calls from
X-Databricks-Org-Id to X-Databricks-Workspace-Id. The previous header
continues to be accepted by the platform, so older CLI versions keep working.

This change covers the hand-written paths in the CLI that issue workspace-
routed API calls without going through generated SDK service methods:

- databricks api {verb} (cmd/api/api.go)
- Files API filer (libs/filer/files_client.go)
- Workspace files filer (libs/filer/workspace_files_client.go)
- Telemetry uploads (libs/telemetry/logger.go)

The value continues to come from the workspace_id config field or
DATABRICKS_WORKSPACE_ID.

The CurrentWorkspaceID() helper in the SDK still reads X-Databricks-Org-Id
from the response on /api/2.0/preview/scim/v2/Me, so the response-side
references in libs/testserver/handlers.go and libs/testproxy/server.go
intentionally remain on the legacy header name.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 28, 2026

Approval status: pending

/bundle/ - needs approval

Files: bundle/deploy/filer.go
Suggested: @pietern
Also eligible: @denik, @shreyas-goenka, @janniklasrose, @andrewnester, @anton-107, @lennartkats-db

/cmd/api/ - approved by @hectorcast-db

Files: cmd/api/api.go

/libs/filer/ - approved by @hectorcast-db

Files: libs/filer/files_client.go, libs/filer/workspace_files_client.go, libs/filer/workspace_files_client_test.go

/libs/telemetry/ - approved by @hectorcast-db

Files: libs/telemetry/logger.go

General files (require maintainer)

19 files changed
Based on git history:

  • @simonfaltum -- recent work in libs/filer/, cmd/api/, bundle/deploy/

Any maintainer (@andrewnester, @anton-107, @denik, @pietern, @shreyas-goenka, @simonfaltum, @renaudhartert-db) can approve all areas.
See OWNERS for ownership rules.

@eng-dev-ecosystem-bot
Copy link
Copy Markdown
Collaborator

eng-dev-ecosystem-bot commented May 28, 2026

Commit: c579a1c

Run: 26639715738

The cmd_exec_id placeholder regressed from [CMD-EXEC-ID] to [UUID] when
the fixture was regenerated locally with jq 1.6. The test script uses
jq '.headers."User-Agent".[0]' syntax that only works in jq 1.7+; on the
older runtime that pipeline silently produced no replacement, leaving
the raw UUID in place which then matched the generic UUID replacement.

Re-regenerated with jq 1.7. CI was already running 1.7+ which is why the
discrepancy only showed up against the wire output, not locally.
Comment thread libs/telemetry/logger.go
func attempt(ctx context.Context, apiClient *client.DatabricksClient, protoLogs []string) (*ResponseBody, error) {
resp := &ResponseBody{}
err := apiClient.Do(ctx, http.MethodPost, "/telemetry-ext", orgIDHeaders(apiClient), nil, RequestBody{
err := apiClient.Do(ctx, http.MethodPost, "/telemetry-ext", workspaceIDHeaders(apiClient), nil, RequestBody{
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

There are a bunch of places where we call ApiClient.Do but don't set the headers like for example

cli/libs/git/info.go

Lines 64 to 78 in 6795f16

err = apiClient.Do(
ctx,
http.MethodGet,
apiEndpoint,
nil,
nil,
map[string]string{
"path": path,
"return_git_info": "true",
},
&response,
)
if err != nil {
return result, err
}

@simonfaltum any thoughts on it?

@andrewnester andrewnester requested a review from simonfaltum May 29, 2026 12:55
bundle/deploy/filer.go has its own stateFiler that fetches the bundle
deployment state from /api/2.0/workspace-files/ using client.Do() directly
(bypassing generated SDK service methods). Apply the same X-Databricks-Org-Id
→ X-Databricks-Workspace-Id swap here so bundle deploy/summary against
unified hosts uses the new routing header consistently with the rest of the
CLI.

Method renamed orgIDHeaders → workspaceIDHeaders for consistency with the
other filer helpers updated in this PR.
Copy link
Copy Markdown
Member

@simonfaltum simonfaltum left a comment

Choose a reason for hiding this comment

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

Code review note:

The PR still misses some raw workspace API callers that bypass generated SDK methods and send no workspace routing header. The PR scope says it covers hand-written workspace-routed calls, but these remain uncovered:

  • bundle/generate/downloader.go:161
  • cmd/pipelines/utils.go:185
  • libs/databrickscfg/cfgpickers/warehouses.go:140
  • libs/apps/prompt/listers.go:178
  • libs/git/info.go:64

On unified hosts with WorkspaceID, those calls can still route incorrectly or fail. I would add a shared helper for the new X-Databricks-Workspace-Id request header and use it for these raw callers, or explicitly document why each one is out of scope. This matches the existing review comment from @andrewnester, with a few more examples.

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.

5 participants