Skip to content

Commit 7376ed9

Browse files
authored
Improve databricks_service_principals data source (#5164)
## Changes <!-- Summary of your changes that are easy to understand --> Changes include: - don't throw an error when nothing is found/got an empty result - Added `service_principals` attribute to contain more information about service principals - SCIM ID, display name, etc. Resolves #5162, Resolves #4997 ## Tests <!-- How is this tested? Please see the checklist below and also describe any other relevant tests --> - [x] `make test` run locally - [x] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] using Go SDK - [ ] using TF Plugin Framework - [x] has entry in `NEXT_CHANGELOG.md` file
1 parent cdd008b commit 7376ed9

File tree

6 files changed

+55
-23
lines changed

6 files changed

+55
-23
lines changed

NEXT_CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
### New Features and Improvements
88

9+
* Improve `databricks_service_principals` data source ([#5164](https://github.com/databricks/terraform-provider-databricks/pull/5164))
10+
911
### Bug Fixes
1012

1113
### Documentation

docs/data-sources/service_principal.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ Data source exposes the following attributes:
4747
- `home` - Home folder of the [service principal](../resources/service_principal.md), e.g. `/Users/11111111-2222-3333-4444-555666777888`.
4848
- `repos` - Repos location of the [service principal](../resources/service_principal.md), e.g. `/Repos/11111111-2222-3333-4444-555666777888`.
4949
- `active` - Whether service principal is active or not.
50-
51-
* `acl_principal_id` - identifier for use in [databricks_access_control_rule_set](../resources/access_control_rule_set.md), e.g. `servicePrincipals/00000000-0000-0000-0000-000000000000`.
50+
- `acl_principal_id` - identifier for use in [databricks_access_control_rule_set](../resources/access_control_rule_set.md), e.g. `servicePrincipals/00000000-0000-0000-0000-000000000000`.
5251

5352
## Related Resources
5453

docs/data-sources/service_principals.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,17 @@ Data source allows you to pick service principals by the following attributes
4343

4444
Data source exposes the following attributes:
4545

46-
- `application_ids` - List of `application_ids` of service principals. Individual service principal can be retrieved using [databricks_service_principal](service_principal.md) data source
46+
- `application_ids` - List of `application_ids` of service principals. Individual service principal can be retrieved using [databricks_service_principal](service_principal.md) data source or from `service_principals` attribute.
47+
- `service_principals` - List of objects describing individual service principals. Each object has the following attributes:
48+
- `id` - The id of the service principal (SCIM ID).
49+
- `application_id` - Application ID of the service principal.
50+
- `display_name` - Display name of the [service principal](../resources/service_principal.md), e.g. `Foo SPN`.
51+
- `scim_id` - same as `id`.
52+
- `external_id` - ID of the service principal in an external identity provider.
53+
- `home` - Home folder of the [service principal](../resources/service_principal.md), e.g. `/Users/11111111-2222-3333-4444-555666777888`.
54+
- `repos` - Repos location of the [service principal](../resources/service_principal.md), e.g. `/Repos/11111111-2222-3333-4444-555666777888`.
55+
- `active` - Whether service principal is active or not.
56+
- `acl_principal_id` - identifier for use in [databricks_access_control_rule_set](../resources/access_control_rule_set.md), e.g. `servicePrincipals/00000000-0000-0000-0000-000000000000`.
4757

4858
## Related Resources
4959

scim/data_service_principal.go

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,23 @@ import (
88
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
99
)
1010

11+
type servicePrincipalData struct {
12+
ApplicationID string `json:"application_id,omitempty" tf:"computed"`
13+
DisplayName string `json:"display_name,omitempty" tf:"computed"`
14+
SpID string `json:"sp_id,omitempty" tf:"computed"`
15+
ScimID string `json:"scim_id,omitempty" tf:"computed"`
16+
ID string `json:"id,omitempty" tf:"computed"`
17+
Home string `json:"home,omitempty" tf:"computed"`
18+
Repos string `json:"repos,omitempty" tf:"computed"`
19+
Active bool `json:"active,omitempty" tf:"computed"`
20+
ExternalID string `json:"external_id,omitempty" tf:"computed"`
21+
AclPrincipalID string `json:"acl_principal_id,omitempty" tf:"computed"`
22+
}
23+
1124
// DataSourceServicePrincipal returns information about the spn specified by the application_id, id, display_name, or scim_id
1225
func DataSourceServicePrincipal() common.Resource {
13-
type spnData struct {
14-
ApplicationID string `json:"application_id,omitempty" tf:"computed"`
15-
DisplayName string `json:"display_name,omitempty" tf:"computed"`
16-
SpID string `json:"sp_id,omitempty" tf:"computed"`
17-
ScimID string `json:"scim_id,omitempty" tf:"computed"`
18-
ID string `json:"id,omitempty" tf:"computed"`
19-
Home string `json:"home,omitempty" tf:"computed"`
20-
Repos string `json:"repos,omitempty" tf:"computed"`
21-
Active bool `json:"active,omitempty" tf:"computed"`
22-
ExternalID string `json:"external_id,omitempty" tf:"computed"`
23-
AclPrincipalID string `json:"acl_principal_id,omitempty" tf:"computed"`
24-
}
2526

26-
s := common.StructToSchema(spnData{}, func(
27+
s := common.StructToSchema(servicePrincipalData{}, func(
2728
s map[string]*schema.Schema) map[string]*schema.Schema {
2829
s["application_id"].ExactlyOneOf = []string{"application_id", "display_name", "scim_id"}
2930
s["display_name"].ExactlyOneOf = []string{"application_id", "display_name", "scim_id"}
@@ -34,7 +35,7 @@ func DataSourceServicePrincipal() common.Resource {
3435
return common.Resource{
3536
Schema: s,
3637
Read: func(ctx context.Context, d *schema.ResourceData, m *common.DatabricksClient) error {
37-
var response spnData
38+
var response servicePrincipalData
3839
var spList []User
3940
var err error
4041

scim/data_service_principals.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package scim
33
import (
44
"context"
55
"fmt"
6+
"log"
67
"sort"
78

89
"github.com/databricks/terraform-provider-databricks/common"
@@ -11,8 +12,9 @@ import (
1112
// DataSourceServicePrincipals searches for service principals based on display_name
1213
func DataSourceServicePrincipals() common.Resource {
1314
type spnsData struct {
14-
DisplayNameContains string `json:"display_name_contains,omitempty" tf:"computed"`
15-
ApplicationIDs []string `json:"application_ids,omitempty" tf:"computed,slice_set"`
15+
DisplayNameContains string `json:"display_name_contains,omitempty" tf:"computed"`
16+
ApplicationIDs []string `json:"application_ids,omitempty" tf:"computed,slice_set"`
17+
ServicePrincipals []servicePrincipalData `json:"service_principals,omitempty" tf:"computed"`
1618
}
1719
return common.DataResource(spnsData{}, func(ctx context.Context, e any, c *common.DatabricksClient) error {
1820
response := e.(*spnsData)
@@ -28,12 +30,27 @@ func DataSourceServicePrincipals() common.Resource {
2830
return err
2931
}
3032
if len(spList) == 0 {
31-
return fmt.Errorf("cannot find SPs with display name containing %s", response.DisplayNameContains)
33+
log.Printf("[INFO] cannot find SPs with display name containing %s", response.DisplayNameContains)
3234
}
3335
for _, sp := range spList {
3436
response.ApplicationIDs = append(response.ApplicationIDs, sp.ApplicationID)
37+
response.ServicePrincipals = append(response.ServicePrincipals, servicePrincipalData{
38+
ApplicationID: sp.ApplicationID,
39+
DisplayName: sp.DisplayName,
40+
Active: sp.Active,
41+
ID: sp.ID,
42+
SpID: sp.ID,
43+
ScimID: sp.ID,
44+
ExternalID: sp.ExternalID,
45+
AclPrincipalID: fmt.Sprintf("servicePrincipals/%s", sp.ApplicationID),
46+
Home: fmt.Sprintf("/Users/%s", sp.ApplicationID),
47+
Repos: fmt.Sprintf("/Repos/%s", sp.ApplicationID),
48+
})
3549
}
3650
sort.Strings(response.ApplicationIDs)
51+
sort.Slice(response.ServicePrincipals, func(i, j int) bool {
52+
return response.ServicePrincipals[i].ApplicationID < response.ServicePrincipals[j].ApplicationID
53+
})
3754
return nil
3855
})
3956
}

scim/data_service_principals_test.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func TestDataServicePrincipalsReadByDisplayName(t *testing.T) {
4242
}
4343

4444
func TestDataServicePrincipalsReadNotFound(t *testing.T) {
45-
_, err := qa.ResourceFixture{
45+
qa.ResourceFixture{
4646
Fixtures: []qa.HTTPFixture{
4747
{
4848
Method: "GET",
@@ -55,8 +55,11 @@ func TestDataServicePrincipalsReadNotFound(t *testing.T) {
5555
Read: true,
5656
NonWritable: true,
5757
ID: "_",
58-
}.Apply(t)
59-
require.Error(t, err)
58+
}.ApplyAndExpectData(t, map[string]any{
59+
"application_ids": []string{},
60+
"service_principals": []any{},
61+
"display_name_contains": "def",
62+
})
6063
}
6164

6265
func TestDataServicePrincipalsReadNoFilter(t *testing.T) {

0 commit comments

Comments
 (0)