Skip to content

Commit 60e716c

Browse files
committed
Add unified-host acceptance test for X-Databricks-Workspace-Id
Hooks a capturing http.RoundTripper into a workspace client built against a unified (SPOG) host and verifies what crosses the wire: 1. SDK sends X-Databricks-Workspace-Id with Config.WorkspaceID on the request and no longer sends the legacy X-Databricks-Org-Id. 2. Server still echoes the workspace ID on the legacy X-Databricks-Org-Id response header — which is why workspace_functions.go reads that name. 3. The workspace-scoped /api/2.0/preview/scim/v2/Me call succeeds against the unified host gateway. Targets the workspace test environment. Requires UNIFIED_HOST, THIS_WORKSPACE_ID, TEST_ACCOUNT_ID, DATABRICKS_CLIENT_ID, and DATABRICKS_CLIENT_SECRET, and skips if TEST_ENVIRONMENT_TYPE is set to anything other than WORKSPACE / UC_WORKSPACE. Co-authored-by: Isaac Signed-off-by: Divyansh Vijayvergia <divyansh.vijayvergia@databricks.com>
1 parent 3633c0e commit 60e716c

1 file changed

Lines changed: 100 additions & 0 deletions

File tree

internal/unified_host_test.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package internal
2+
3+
import (
4+
"context"
5+
"net/http"
6+
"testing"
7+
8+
"github.com/databricks/databricks-sdk-go"
9+
"github.com/databricks/databricks-sdk-go/config"
10+
"github.com/databricks/databricks-sdk-go/service/iam"
11+
"github.com/stretchr/testify/assert"
12+
"github.com/stretchr/testify/require"
13+
)
14+
15+
// captureHeadersTransport snapshots the request and response headers for a
16+
// single matching URL path and lets every other request through unchanged.
17+
type captureHeadersTransport struct {
18+
inner http.RoundTripper
19+
path string
20+
21+
reqHdr http.Header
22+
respHdr http.Header
23+
}
24+
25+
func (t *captureHeadersTransport) RoundTrip(req *http.Request) (*http.Response, error) {
26+
matched := req.URL.Path == t.path
27+
if matched {
28+
t.reqHdr = req.Header.Clone()
29+
}
30+
resp, err := t.inner.RoundTrip(req)
31+
if matched && resp != nil {
32+
t.respHdr = resp.Header.Clone()
33+
}
34+
return resp, err
35+
}
36+
37+
// TestAccUnifiedHostSendsWorkspaceIdHeader verifies, against a real unified
38+
// (SPOG) host, that:
39+
// 1. the SDK sends the new X-Databricks-Workspace-Id routing header on
40+
// workspace-scoped requests, and no longer sends the legacy
41+
// X-Databricks-Org-Id, and
42+
// 2. the server still echoes the workspace ID on the legacy
43+
// X-Databricks-Org-Id response header — the response-side migration has
44+
// not yet happened, which is why CurrentWorkspaceID still reads the
45+
// legacy name in workspace_functions.go.
46+
//
47+
// Uses OAuth M2M auth (ClientID/ClientSecret) and probes the SCIM Me endpoint
48+
// as the workspace-scoped call. A transport-level header capture is hooked in
49+
// to verify which routing header actually crosses the wire.
50+
//
51+
// Runs against the workspace test environment (TEST_ENVIRONMENT_TYPE in
52+
// {WORKSPACE, UC_WORKSPACE}). Requires UNIFIED_HOST, THIS_WORKSPACE_ID,
53+
// TEST_ACCOUNT_ID, DATABRICKS_CLIENT_ID, and DATABRICKS_CLIENT_SECRET in the
54+
// environment.
55+
func TestAccUnifiedHostSendsWorkspaceIdHeader(t *testing.T) {
56+
loadDebugEnvIfRunsFromIDE(t, "workspace")
57+
if envType := testEnvironmentType(); envType != "" && envType != "WORKSPACE" && envType != "UC_WORKSPACE" {
58+
skipf(t)("Skipping workspace test: TEST_ENVIRONMENT_TYPE=%s", envType)
59+
}
60+
61+
const apiPath = "/api/2.0/preview/scim/v2/Me"
62+
transport := &captureHeadersTransport{
63+
inner: http.DefaultTransport,
64+
path: apiPath,
65+
}
66+
workspaceID := GetEnvOrSkipTest(t, "THIS_WORKSPACE_ID")
67+
cfg := &config.Config{
68+
Host: GetEnvOrSkipTest(t, "UNIFIED_HOST"),
69+
AccountID: GetEnvOrSkipTest(t, "TEST_ACCOUNT_ID"),
70+
ClientID: GetEnvOrSkipTest(t, "DATABRICKS_CLIENT_ID"),
71+
ClientSecret: GetEnvOrSkipTest(t, "DATABRICKS_CLIENT_SECRET"),
72+
WorkspaceID: workspaceID,
73+
HTTPTransport: transport,
74+
HTTPTimeoutSeconds: 60,
75+
}
76+
if err := cfg.EnsureResolved(); err != nil {
77+
skipf(t)("config resolve: %s", err)
78+
}
79+
t.Parallel()
80+
81+
ctx := context.Background()
82+
w := databricks.Must(databricks.NewWorkspaceClient((*databricks.Config)(cfg)))
83+
84+
// (1) workspace-scoped probe against the unified host: must succeed.
85+
me, err := w.CurrentUser.Me(ctx, iam.MeRequest{})
86+
require.NoError(t, err, "workspace-scoped SCIM Me should pass through the unified host gateway with the new routing header")
87+
assert.NotEmpty(t, me.UserName, "Me should return a non-empty UserName")
88+
89+
// (2) On the request side, the SDK must send the new header and not the legacy one.
90+
require.NotNil(t, transport.reqHdr, "transport did not observe a request to %s", apiPath)
91+
assert.Equal(t, workspaceID, transport.reqHdr.Get("X-Databricks-Workspace-Id"),
92+
"SDK must send X-Databricks-Workspace-Id with Config.WorkspaceID")
93+
assert.Empty(t, transport.reqHdr.Get("X-Databricks-Org-Id"),
94+
"SDK must no longer send the legacy X-Databricks-Org-Id request header")
95+
96+
// (3) On the response side, the server still echoes the legacy header name during the migration.
97+
require.NotNil(t, transport.respHdr, "transport did not observe a response from %s", apiPath)
98+
assert.NotEmpty(t, transport.respHdr.Get("X-Databricks-Org-Id"),
99+
"server is expected to still echo the legacy X-Databricks-Org-Id response header during the migration")
100+
}

0 commit comments

Comments
 (0)