Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions scim/data_service_principal_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package scim

import (
"context"
"testing"

"github.com/databricks/terraform-provider-databricks/common"
"github.com/databricks/terraform-provider-databricks/qa"
"github.com/stretchr/testify/assert"
)
Expand Down Expand Up @@ -253,6 +255,78 @@ func TestDataServicePrincipalReadNoParams(t *testing.T) {
}.ExpectError(t, "please specify either application_id, display_name, or scim_id")
}

// TestDataServicePrincipalRead_AccountLevelNoHookFailure is a regression test
// for https://github.com/databricks/terraform-provider-databricks/issues/5664.
// When `databricks_service_principal` data source is used with an account-level
// provider, the post-Read provider_config hook used to call CurrentWorkspaceID
// and fail with:
//
// Error: cannot populate provider_config for service principal:
// failed to resolve workspace_id: failed to get the workspace_id:
// strconv.ParseInt: parsing "": invalid syntax
//
// The fix in main adds `api` to the data source schema and marks it
// `IsDual: true` so the post-Read hook is short-circuited at account level.
//
// Fixtures cover BOTH the workspace SCIM path (used by v1.114.0 where the
// `api` field does not exist and HostType falls back to WorkspaceHost) and
// the account SCIM path (used on main once `api = "account"` is set). The
// test asserts the hook does not fire by deliberately NOT stubbing
// /api/2.0/preview/scim/v2/Me — if the hook runs it will hit the test server
// with no matching fixture and the assertion fails with a missing-stub
// error referencing /Me.
func TestDataServicePrincipalRead_AccountLevelNoHookFailure(t *testing.T) {
spResources := UserList{
Resources: []User{
{
ID: "spid",
DisplayName: "testsp",
Active: true,
ApplicationID: "appid",
},
},
}
client, server, err := qa.HttpFixtureClient(t, []qa.HTTPFixture{
{
Method: "GET",
Resource: "/api/2.0/accounts/abc/scim/v2/ServicePrincipals?excludedAttributes=roles&filter=displayName%20eq%20%22testsp%22",
ReuseRequest: true,
Response: spResources,
},
{
Method: "GET",
Resource: "/api/2.0/preview/scim/v2/ServicePrincipals?excludedAttributes=roles&filter=displayName%20eq%20%22testsp%22",
ReuseRequest: true,
Response: spResources,
},
// Deliberately NO fixture for /api/2.0/preview/scim/v2/Me — if the
// post-Read provider_config hook fires, it will try to call /Me and
// the test will fail with a missing-stub error.
})
assert.NoError(t, err)
defer server.Close()

// Simulate a real account-level provider: AccountID set and no cached
// workspace ID so the post-Read hook (if it fires) is forced to call /Me.
client.Config.AccountID = "abc"
client.SetCachedWorkspaceID(0)

r := DataSourceServicePrincipal().ToResource()
d := r.TestResourceData()
// On main the `api` field exists and routes to account-level SCIM; on
// v1.114.0 the schema has no such field and Set returns an error which
// we deliberately ignore (the data source then falls back to workspace
// SCIM, but the bug still surfaces because the hook runs unconditionally).
_ = d.Set("api", "account")
assert.NoError(t, d.Set("display_name", "testsp"))
ctx := context.WithValue(context.Background(), common.ResourceName, "service_principal")
diags := r.ReadContext(ctx, d, client)

assert.False(t, diags.HasError(),
"post-Read provider_config hook must be skipped for service_principal data source at account level; got: %v", diags)
assert.Equal(t, "spid", d.Id())
}

func TestDataServicePrincipalReadInvalidConfig(t *testing.T) {
qa.ResourceFixture{
Resource: DataSourceServicePrincipal(),
Expand Down
Loading