Skip to content

Commit 87b5224

Browse files
Add X-Databricks-Org-Id header to deprecated workspace SCIM APIs (#1614)
## Summary - Added `X-Databricks-Org-Id` header to all methods in the deprecated `groupsImpl`, `servicePrincipalsImpl`, and `usersImpl` workspace services (22 methods total in `service/iam/ext_impl.go`) - These were the only workspace-level services missing this header, which is required for SPOG (unified) host compatibility - Added integration test `TestAccUnifiedHostWorkspaceGroups` to verify Groups API works through a SPOG host ## Test plan - [X] Verify `TestAccUnifiedHostWorkspaceGroups` passes against a SPOG host with `UNIFIED_HOST` and `TEST_WORKSPACE_ID` configured - [X] Verify existing `TestAccGroups`, `TestAccWorkspaceUsers`, and `TestAccServicePrincipalsOnAWS` still pass https://github.com/databricks-eng/eng-dev-ecosystem/actions/runs/24186717484/job/70593435796 This pull request was AI-assisted by Isaac. Signed-off-by: Hector Castejon Diaz <hector.castejon@databricks.com>
1 parent 64b75cd commit 87b5224

3 files changed

Lines changed: 106 additions & 0 deletions

File tree

NEXT_CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
### Bug Fixes
1616

17+
* Add `X-Databricks-Org-Id` header to deprecated workspace SCIM APIs (Groups, ServicePrincipals, Users) for SPOG host compatibility.
1718
* Add retry logic to token acquisition for OIDC, M2M, and Azure client secret credentials ([#1398](https://github.com/databricks/databricks-sdk-go/issues/1398), [#1072](https://github.com/databricks/databricks-sdk-go/issues/1072)).
1819
* Fix double-caching of OAuth tokens in Azure client secret credentials ([#1549](https://github.com/databricks/databricks-sdk-go/issues/1549)).
1920
* Disable async token refresh for GCP credential providers to avoid wasted refresh attempts caused by double-caching with Google's internal `oauth2.ReuseTokenSource` ([#1549](https://github.com/databricks/databricks-sdk-go/issues/1549)).

internal/unifiedhost_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,23 @@ import (
99
"github.com/stretchr/testify/require"
1010
)
1111

12+
func TestAccUnifiedHostWorkspaceGroups(t *testing.T) {
13+
ctx, _, w := unifiedHostAccountTest(t)
14+
15+
group, err := w.Groups.Create(ctx, iam.Group{
16+
DisplayName: RandomName("go-sdk-"),
17+
})
18+
require.NoError(t, err)
19+
t.Cleanup(func() {
20+
err := w.Groups.DeleteById(ctx, group.Id)
21+
require.True(t, err == nil || apierr.IsMissing(err))
22+
})
23+
24+
fetch, err := w.Groups.GetById(ctx, group.Id)
25+
require.NoError(t, err)
26+
assert.Equal(t, group.DisplayName, fetch.DisplayName)
27+
}
28+
1229
func TestAccUnifiedHost(t *testing.T) {
1330
ctx, a, w := unifiedHostAccountTest(t)
1431

service/iam/ext_impl.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,10 @@ func (a *groupsImpl) Create(ctx context.Context, request Group) (*Group, error)
331331
headers := make(map[string]string)
332332
headers["Accept"] = "application/json"
333333
headers["Content-Type"] = "application/json"
334+
cfg := a.client.Config
335+
if cfg.WorkspaceID != "" {
336+
headers["X-Databricks-Org-Id"] = cfg.WorkspaceID
337+
}
334338
err := a.client.Do(ctx, http.MethodPost, path, headers, queryParams, request, &group)
335339
return &group, err
336340
}
@@ -339,6 +343,10 @@ func (a *groupsImpl) Delete(ctx context.Context, request DeleteGroupRequest) err
339343
path := fmt.Sprintf("/api/2.0/preview/scim/v2/Groups/%v", request.Id)
340344
queryParams := make(map[string]any)
341345
headers := make(map[string]string)
346+
cfg := a.client.Config
347+
if cfg.WorkspaceID != "" {
348+
headers["X-Databricks-Org-Id"] = cfg.WorkspaceID
349+
}
342350
err := a.client.Do(ctx, http.MethodDelete, path, headers, queryParams, request, nil)
343351
return err
344352
}
@@ -349,6 +357,10 @@ func (a *groupsImpl) Get(ctx context.Context, request GetGroupRequest) (*Group,
349357
queryParams := make(map[string]any)
350358
headers := make(map[string]string)
351359
headers["Accept"] = "application/json"
360+
cfg := a.client.Config
361+
if cfg.WorkspaceID != "" {
362+
headers["X-Databricks-Org-Id"] = cfg.WorkspaceID
363+
}
352364
err := a.client.Do(ctx, http.MethodGet, path, headers, queryParams, request, &group)
353365
return &group, err
354366
}
@@ -400,6 +412,10 @@ func (a *groupsImpl) internalList(ctx context.Context, request ListGroupsRequest
400412
queryParams := make(map[string]any)
401413
headers := make(map[string]string)
402414
headers["Accept"] = "application/json"
415+
cfg := a.client.Config
416+
if cfg.WorkspaceID != "" {
417+
headers["X-Databricks-Org-Id"] = cfg.WorkspaceID
418+
}
403419
err := a.client.Do(ctx, http.MethodGet, path, headers, queryParams, request, &listGroupsResponse)
404420
return &listGroupsResponse, err
405421
}
@@ -409,6 +425,10 @@ func (a *groupsImpl) Patch(ctx context.Context, request PartialUpdate) error {
409425
queryParams := make(map[string]any)
410426
headers := make(map[string]string)
411427
headers["Content-Type"] = "application/json"
428+
cfg := a.client.Config
429+
if cfg.WorkspaceID != "" {
430+
headers["X-Databricks-Org-Id"] = cfg.WorkspaceID
431+
}
412432
err := a.client.Do(ctx, http.MethodPatch, path, headers, queryParams, request, nil)
413433
return err
414434
}
@@ -418,6 +438,10 @@ func (a *groupsImpl) Update(ctx context.Context, request Group) error {
418438
queryParams := make(map[string]any)
419439
headers := make(map[string]string)
420440
headers["Content-Type"] = "application/json"
441+
cfg := a.client.Config
442+
if cfg.WorkspaceID != "" {
443+
headers["X-Databricks-Org-Id"] = cfg.WorkspaceID
444+
}
421445
err := a.client.Do(ctx, http.MethodPut, path, headers, queryParams, request, nil)
422446
return err
423447
}
@@ -434,6 +458,10 @@ func (a *servicePrincipalsImpl) Create(ctx context.Context, request ServicePrinc
434458
headers := make(map[string]string)
435459
headers["Accept"] = "application/json"
436460
headers["Content-Type"] = "application/json"
461+
cfg := a.client.Config
462+
if cfg.WorkspaceID != "" {
463+
headers["X-Databricks-Org-Id"] = cfg.WorkspaceID
464+
}
437465
err := a.client.Do(ctx, http.MethodPost, path, headers, queryParams, request, &servicePrincipal)
438466
return &servicePrincipal, err
439467
}
@@ -442,6 +470,10 @@ func (a *servicePrincipalsImpl) Delete(ctx context.Context, request DeleteServic
442470
path := fmt.Sprintf("/api/2.0/preview/scim/v2/ServicePrincipals/%v", request.Id)
443471
queryParams := make(map[string]any)
444472
headers := make(map[string]string)
473+
cfg := a.client.Config
474+
if cfg.WorkspaceID != "" {
475+
headers["X-Databricks-Org-Id"] = cfg.WorkspaceID
476+
}
445477
err := a.client.Do(ctx, http.MethodDelete, path, headers, queryParams, request, nil)
446478
return err
447479
}
@@ -452,6 +484,10 @@ func (a *servicePrincipalsImpl) Get(ctx context.Context, request GetServicePrinc
452484
queryParams := make(map[string]any)
453485
headers := make(map[string]string)
454486
headers["Accept"] = "application/json"
487+
cfg := a.client.Config
488+
if cfg.WorkspaceID != "" {
489+
headers["X-Databricks-Org-Id"] = cfg.WorkspaceID
490+
}
455491
err := a.client.Do(ctx, http.MethodGet, path, headers, queryParams, request, &servicePrincipal)
456492
return &servicePrincipal, err
457493
}
@@ -503,6 +539,10 @@ func (a *servicePrincipalsImpl) internalList(ctx context.Context, request ListSe
503539
queryParams := make(map[string]any)
504540
headers := make(map[string]string)
505541
headers["Accept"] = "application/json"
542+
cfg := a.client.Config
543+
if cfg.WorkspaceID != "" {
544+
headers["X-Databricks-Org-Id"] = cfg.WorkspaceID
545+
}
506546
err := a.client.Do(ctx, http.MethodGet, path, headers, queryParams, request, &listServicePrincipalResponse)
507547
return &listServicePrincipalResponse, err
508548
}
@@ -512,6 +552,10 @@ func (a *servicePrincipalsImpl) Patch(ctx context.Context, request PartialUpdate
512552
queryParams := make(map[string]any)
513553
headers := make(map[string]string)
514554
headers["Content-Type"] = "application/json"
555+
cfg := a.client.Config
556+
if cfg.WorkspaceID != "" {
557+
headers["X-Databricks-Org-Id"] = cfg.WorkspaceID
558+
}
515559
err := a.client.Do(ctx, http.MethodPatch, path, headers, queryParams, request, nil)
516560
return err
517561
}
@@ -521,6 +565,10 @@ func (a *servicePrincipalsImpl) Update(ctx context.Context, request ServicePrinc
521565
queryParams := make(map[string]any)
522566
headers := make(map[string]string)
523567
headers["Content-Type"] = "application/json"
568+
cfg := a.client.Config
569+
if cfg.WorkspaceID != "" {
570+
headers["X-Databricks-Org-Id"] = cfg.WorkspaceID
571+
}
524572
err := a.client.Do(ctx, http.MethodPut, path, headers, queryParams, request, nil)
525573
return err
526574
}
@@ -537,6 +585,10 @@ func (a *usersImpl) Create(ctx context.Context, request User) (*User, error) {
537585
headers := make(map[string]string)
538586
headers["Accept"] = "application/json"
539587
headers["Content-Type"] = "application/json"
588+
cfg := a.client.Config
589+
if cfg.WorkspaceID != "" {
590+
headers["X-Databricks-Org-Id"] = cfg.WorkspaceID
591+
}
540592
err := a.client.Do(ctx, http.MethodPost, path, headers, queryParams, request, &user)
541593
return &user, err
542594
}
@@ -545,6 +597,10 @@ func (a *usersImpl) Delete(ctx context.Context, request DeleteUserRequest) error
545597
path := fmt.Sprintf("/api/2.0/preview/scim/v2/Users/%v", request.Id)
546598
queryParams := make(map[string]any)
547599
headers := make(map[string]string)
600+
cfg := a.client.Config
601+
if cfg.WorkspaceID != "" {
602+
headers["X-Databricks-Org-Id"] = cfg.WorkspaceID
603+
}
548604
err := a.client.Do(ctx, http.MethodDelete, path, headers, queryParams, request, nil)
549605
return err
550606
}
@@ -555,6 +611,10 @@ func (a *usersImpl) Get(ctx context.Context, request GetUserRequest) (*User, err
555611
queryParams := make(map[string]any)
556612
headers := make(map[string]string)
557613
headers["Accept"] = "application/json"
614+
cfg := a.client.Config
615+
if cfg.WorkspaceID != "" {
616+
headers["X-Databricks-Org-Id"] = cfg.WorkspaceID
617+
}
558618
err := a.client.Do(ctx, http.MethodGet, path, headers, queryParams, request, &user)
559619
return &user, err
560620
}
@@ -565,6 +625,10 @@ func (a *usersImpl) GetPermissionLevels(ctx context.Context) (*GetPasswordPermis
565625

566626
headers := make(map[string]string)
567627
headers["Accept"] = "application/json"
628+
cfg := a.client.Config
629+
if cfg.WorkspaceID != "" {
630+
headers["X-Databricks-Org-Id"] = cfg.WorkspaceID
631+
}
568632
err := a.client.Do(ctx, http.MethodGet, path, headers, nil, nil, &getPasswordPermissionLevelsResponse)
569633
return &getPasswordPermissionLevelsResponse, err
570634
}
@@ -575,6 +639,10 @@ func (a *usersImpl) GetPermissions(ctx context.Context) (*PasswordPermissions, e
575639

576640
headers := make(map[string]string)
577641
headers["Accept"] = "application/json"
642+
cfg := a.client.Config
643+
if cfg.WorkspaceID != "" {
644+
headers["X-Databricks-Org-Id"] = cfg.WorkspaceID
645+
}
578646
err := a.client.Do(ctx, http.MethodGet, path, headers, nil, nil, &passwordPermissions)
579647
return &passwordPermissions, err
580648
}
@@ -626,6 +694,10 @@ func (a *usersImpl) internalList(ctx context.Context, request ListUsersRequest)
626694
queryParams := make(map[string]any)
627695
headers := make(map[string]string)
628696
headers["Accept"] = "application/json"
697+
cfg := a.client.Config
698+
if cfg.WorkspaceID != "" {
699+
headers["X-Databricks-Org-Id"] = cfg.WorkspaceID
700+
}
629701
err := a.client.Do(ctx, http.MethodGet, path, headers, queryParams, request, &listUsersResponse)
630702
return &listUsersResponse, err
631703
}
@@ -635,6 +707,10 @@ func (a *usersImpl) Patch(ctx context.Context, request PartialUpdate) error {
635707
queryParams := make(map[string]any)
636708
headers := make(map[string]string)
637709
headers["Content-Type"] = "application/json"
710+
cfg := a.client.Config
711+
if cfg.WorkspaceID != "" {
712+
headers["X-Databricks-Org-Id"] = cfg.WorkspaceID
713+
}
638714
err := a.client.Do(ctx, http.MethodPatch, path, headers, queryParams, request, nil)
639715
return err
640716
}
@@ -646,6 +722,10 @@ func (a *usersImpl) SetPermissions(ctx context.Context, request PasswordPermissi
646722
headers := make(map[string]string)
647723
headers["Accept"] = "application/json"
648724
headers["Content-Type"] = "application/json"
725+
cfg := a.client.Config
726+
if cfg.WorkspaceID != "" {
727+
headers["X-Databricks-Org-Id"] = cfg.WorkspaceID
728+
}
649729
err := a.client.Do(ctx, http.MethodPut, path, headers, queryParams, request, &passwordPermissions)
650730
return &passwordPermissions, err
651731
}
@@ -655,6 +735,10 @@ func (a *usersImpl) Update(ctx context.Context, request User) error {
655735
queryParams := make(map[string]any)
656736
headers := make(map[string]string)
657737
headers["Content-Type"] = "application/json"
738+
cfg := a.client.Config
739+
if cfg.WorkspaceID != "" {
740+
headers["X-Databricks-Org-Id"] = cfg.WorkspaceID
741+
}
658742
err := a.client.Do(ctx, http.MethodPut, path, headers, queryParams, request, nil)
659743
return err
660744
}
@@ -666,6 +750,10 @@ func (a *usersImpl) UpdatePermissions(ctx context.Context, request PasswordPermi
666750
headers := make(map[string]string)
667751
headers["Accept"] = "application/json"
668752
headers["Content-Type"] = "application/json"
753+
cfg := a.client.Config
754+
if cfg.WorkspaceID != "" {
755+
headers["X-Databricks-Org-Id"] = cfg.WorkspaceID
756+
}
669757
err := a.client.Do(ctx, http.MethodPatch, path, headers, queryParams, request, &passwordPermissions)
670758
return &passwordPermissions, err
671759
}

0 commit comments

Comments
 (0)