Skip to content

[Internal] Inject workspace-id routing header per-resource for non-Go-SDK resources#5759

Merged
tanmay-db merged 4 commits into
mainfrom
header-non-go-sdk
Jun 1, 2026
Merged

[Internal] Inject workspace-id routing header per-resource for non-Go-SDK resources#5759
tanmay-db merged 4 commits into
mainfrom
header-non-go-sdk

Conversation

@tanmay-db

@tanmay-db tanmay-db commented May 28, 2026

Copy link
Copy Markdown
Contributor

Changes

Resources that don't use the Go SDK to make API calls go through common.DatabricksClient's raw HTTP path (Get/Post/Patch/Delete/Put/Scim) rather than a generated w.<Service>.<Method>(...) call. Eg: repos, pools, sharing, access, catalog, workspace/notebook, clusters, storage/dbfs, aws/instance_profile,
commands, tokens, sql/, scim/, jobs legacy 2.0, exporter, etc.

Until now, those calls sent no workspace routing header — on a unified host the gateway has no way to dispatch the request to the right workspace, so these resources either failed outright or routed to the wrong workspace.

This PR adds per-request X-Databricks-Workspace-Id injection to those callsites, gated on Config.WorkspaceID being non-empty.

Design choice: injection is per-callsite, not centralized in the helpers. A central "always inject when Config.WorkspaceID != """ hook is fragile because the same client config can carry a WorkspaceID even when the call targets an account endpoint (mws_* on a unified host, or a dual SCIM resource at api=account). Per-callsite control makes the intent explicit and auditable: workspace-only resources opt in; account-only resources never do; dual SCIM is handled inside the Scim helper based on apiLevel.

Summary of main changes

common/client.go

  • New visitor AddWorkspaceIdHeader that sets X-Databricks-Workspace-Id: <Config.WorkspaceID> when WorkspaceID is non-empty (no-op otherwise).
  • Get/Post/Patch/Delete/Put/PatchWithResponse/DeleteWithResponse made variadic on visitors. addApiPrefix still runs first.
  • Scim helper injects the header conditionally based on apiLevel: workspace-level SCIM injects; account-level SCIM does not (path is rewritten to
    /api/2.0/accounts/{aid}/scim/v2/... and must not be workspace-tagged).
  • The old centralized injection on every helper has been removed.

Per-resource classification

Class Files Action
Workspace-only repos, pools, sharing/provider, access/{permission_assignment,sql_permissions}, catalog/{table,sql_table,update}, workspace/notebook, clusters, storage/dbfs, aws/instance_profile, commands, tokens/{token,obo_token}, sql/{query,widget,dashboard,visualization,global_config}, jobs (legacy API 2.0 paths), exporter/util Every callsite passes c.AddWorkspaceIdHeader
Account-only mws/* — every path under /accounts/{aid}/... Untouched. grep AddWorkspaceIdHeader mws/ → empty
Dual scim/* Handled inside Scim helper based on apiLevel. No per-callsite hardcoding

Classification was based on the actual API endpoints the resources hit (paths starting with /accounts/ → account-only; everything else → workspace-only) and a sweep of the docs.

Tests

Unit (common/client_test.go)

  • TestWorkspaceIdHeader_OmittedByDefault — guard against accidental re-centralization: helpers no longer inject the header on their own.
  • TestWorkspaceIdHeader_InjectedWithVisitor — opt-in works on Get/Post/Patch/Delete/Put when AddWorkspaceIdHeader is passed.
  • TestWorkspaceIdHeader_VisitorNoOpWhenWorkspaceIDEmpty — passing the visitor is safe when Config.WorkspaceID is empty.
  • TestScim_WorkspaceLevel_InjectsHeader — dual SCIM at api=workspace carries the header and SCIM Content-Type.
  • TestScim_AccountLevel_OmitsHeader — dual SCIM at api=account omits the header and the path is rewritten to /accounts/{aid}/scim/v2/....

The tests use an httptest.Server that captures each outbound request's headers and URL.

Integration (internal/acceptance/unified_host_acc_test.go)

  • Existing TestMwsAccUnifiedHostCreateJobs / TestAccUnifiedHostWorkspaceCreateJobs — Go SDK path (jobs) on unified host. Unchanged.
  • TestMwsAccUnifiedHostCreateRepo / TestAccUnifiedHostWorkspaceCreateRepo / TestMwsAccAccountHostCreateRepo — workspace-only raw-HTTP path (databricks_repo) on unified host.
    Mirrors the jobs trio so the contrast is direct: same shape, different code path.

Verification

  • go build ./... — clean
  • go test ./... — all packages pass
  • make fmt lint ws — clean
  • grep AddWorkspaceIdHeader mws/ scim/ — empty (account-only files untouched; dual SCIM handled in helper, not per-callsite)

NO_CHANGELOG=true

@tanmay-db tanmay-db temporarily deployed to test-trigger-is May 28, 2026 18:20 — with GitHub Actions Inactive
@tanmay-db tanmay-db temporarily deployed to test-trigger-is May 28, 2026 18:21 — with GitHub Actions Inactive
Move X-Databricks-Workspace-Id injection out of common.DatabricksClient's
helpers and into each workspace-level resource. The previous central
approach fired on every raw-HTTP call gated only on Config.WorkspaceID;
this is fragile for account-only and dual resources because the same
client config can carry a WorkspaceID even when the call targets an
account endpoint.

- Get/Post/Patch/Delete/Put now take variadic visitors; workspace-only
  callsites pass c.AddWorkspaceIdHeader explicitly (~137 callsites across
  repos, pools, sharing, access, catalog, workspace, clusters, storage,
  aws, commands, tokens, sql, jobs-legacy, exporter).
- Scim helper injects the header conditionally based on apiLevel so
  dual SCIM (users/groups/service_principals) sends it at workspace
  level and skips it at account level.
- mws/* (account-only, paths under /accounts/{aid}/...) untouched.

Co-authored-by: Isaac
@tanmay-db tanmay-db temporarily deployed to test-trigger-is May 29, 2026 07:58 — with GitHub Actions Inactive
@tanmay-db tanmay-db temporarily deployed to test-trigger-is May 29, 2026 07:59 — with GitHub Actions Inactive
@tanmay-db tanmay-db changed the title [Internal] Header in resources direclty calling the API without Go SDK [Internal] Inject workspace-id routing header per-resource for non-Go-SDK resources May 29, 2026
@tanmay-db tanmay-db temporarily deployed to test-trigger-is May 29, 2026 08:36 — with GitHub Actions Inactive
@tanmay-db tanmay-db marked this pull request as ready for review May 29, 2026 08:36
@tanmay-db tanmay-db requested review from a team as code owners May 29, 2026 08:36
@tanmay-db tanmay-db requested review from Divyansh-db and hectorcast-db and removed request for a team May 29, 2026 08:36
@tanmay-db tanmay-db temporarily deployed to test-trigger-is May 29, 2026 08:38 — with GitHub Actions Inactive
databricks_repo.path requires /Repos/<directory>/<repo> (3 components
after the leading slash) per validatePath in repos/resource_repo.go.
The test fixture used /Repos/tf-acc-<rand> (2 components), causing
ValidateResourceConfig to fail before any API call:

  Error: should have 3 components (/Repos/<directory>/<repo>), got 2

Failure surfaced in eng-dev-ecosystem run 26627275255 on the *-acct-*
matrix legs (TestMwsAccUnifiedHostCreateRepo, TestMwsAccAccountHostCreateRepo).

Co-authored-by: Isaac
@tanmay-db tanmay-db temporarily deployed to test-trigger-is May 29, 2026 09:14 — with GitHub Actions Inactive
@tanmay-db tanmay-db temporarily deployed to test-trigger-is May 29, 2026 09:14 — with GitHub Actions Inactive
@github-actions

Copy link
Copy Markdown
Contributor

If integration tests don't run automatically, an authorized user can run them manually by following the instructions below:

Trigger:
go/deco-tests-run/terraform

Inputs:

  • PR number: 5759
  • Commit SHA: cbb2a4a50ab8ac470fee09dd36fa30c6cd5dbaba

Checks will be approved automatically on success.

@tanmay-db tanmay-db added this pull request to the merge queue Jun 1, 2026
Merged via the queue into main with commit 11cf4c6 Jun 1, 2026
14 checks passed
@tanmay-db tanmay-db deleted the header-non-go-sdk branch June 1, 2026 14:35
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.

3 participants