From 71c4fd49362ca374a4d37fd24b45ded8d6109caa Mon Sep 17 00:00:00 2001 From: dgomez04 Date: Fri, 13 Sep 2024 15:58:02 -0600 Subject: [PATCH 01/10] #3468: added initial data_users.go resource --- scim/data_users.go | 52 +++++++++++++++++++++++++++++++++++++++++ scim/data_users_test.go | 29 +++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100755 scim/data_users.go create mode 100755 scim/data_users_test.go diff --git a/scim/data_users.go b/scim/data_users.go new file mode 100755 index 0000000000..f3a8b873bc --- /dev/null +++ b/scim/data_users.go @@ -0,0 +1,52 @@ +package scim + +import ( + "context" + "fmt" + + "github.com/databricks/databricks-sdk-go" + "github.com/databricks/databricks-sdk-go/service/iam" + "github.com/databricks/terraform-provider-databricks/common" +) + +func DataSourceDataUsers() common.Resource { + + type DataUsers struct { + Id string `json:"id,omitempty" tf:"computed"` + DisplayNameContains string `json:"display_name_contains,omitempty" tf:"computed"` + Users []map[string]interface{} `json:"users,omitempty" tf:"computed"` + } + + return common.AccountData(func(ctx context.Context, data *DataUsers, acc *databricks.AccountClient) error { + listRequest := iam.ListAccountUsersRequest{} + + if data.DisplayNameContains != "" { + listRequest.Filter = fmt.Sprintf("displayName co \"%s\"", data.DisplayNameContains) + } + + userList, err := acc.Users.ListAll(ctx, listRequest) + + if err != nil { + return err + } + + if len(userList) == 0 { + return fmt.Errorf("cannot find users with display name containing %s", data.DisplayNameContains) + } + + var users []map[string]interface{} + + for _, u := range userList { + user := map[string]interface{}{ + "id": u.Id, + "user_name": u.UserName, + "display_name": u.DisplayName, + } + users = append(users, user) + } + + data.Users = users + + return nil + }) +} diff --git a/scim/data_users_test.go b/scim/data_users_test.go new file mode 100755 index 0000000000..0d45fa9a0c --- /dev/null +++ b/scim/data_users_test.go @@ -0,0 +1,29 @@ +package scim + +import ( + "testing" + + "github.com/databricks/terraform-provider-databricks/qa" +) + +func TestDataSourceDataUsers(t *testing.T) { + qa.ResourceFixture{ + Fixtures: []qa.HTTPFixture{ + // TODO: run this test to get fixtures + }, + Resource: DataSourceDataUsers(), + Read: true, + NonWritable: true, + ID: "_", + }.ApplyNoError(t) +} + +func TestCatalogsData_Error(t *testing.T) { + qa.ResourceFixture{ + Fixtures: qa.HTTPFailures, + Resource: DataSourceDataUsers(), + Read: true, + NonWritable: true, + ID: "_", + }.ExpectError(t, "i'm a teapot") +} From a81fbd836636763858dcfb314c167bd2501aea7b Mon Sep 17 00:00:00 2001 From: dgomez04 Date: Mon, 16 Sep 2024 17:16:13 -0600 Subject: [PATCH 02/10] #3468: made changes to data_users.go to explicitly define schema, and only request the id, userName, and displayName attributes. added succesful initial test_case on data_users_test.go --- scim/data_users.go | 25 ++++++++++++++++--------- scim/data_users_test.go | 37 ++++++++++++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/scim/data_users.go b/scim/data_users.go index f3a8b873bc..576ed2ebb8 100755 --- a/scim/data_users.go +++ b/scim/data_users.go @@ -11,14 +11,21 @@ import ( func DataSourceDataUsers() common.Resource { + type UserInfo struct { + Id string `json:"id,omitempty" tf:"computed"` + UserName string `json:"user_name,omitempty" tf:"computed"` + DisplayName string `json:"display_name,omitempty" tf:"computed"` + } + type DataUsers struct { - Id string `json:"id,omitempty" tf:"computed"` - DisplayNameContains string `json:"display_name_contains,omitempty" tf:"computed"` - Users []map[string]interface{} `json:"users,omitempty" tf:"computed"` + DisplayNameContains string `json:"display_name_contains,omitempty" tf:"computed"` + Users []UserInfo `json:"users,omitempty" tf:"computed"` } return common.AccountData(func(ctx context.Context, data *DataUsers, acc *databricks.AccountClient) error { - listRequest := iam.ListAccountUsersRequest{} + listRequest := iam.ListAccountUsersRequest{ + Attributes: "id,userName,displayName", + } if data.DisplayNameContains != "" { listRequest.Filter = fmt.Sprintf("displayName co \"%s\"", data.DisplayNameContains) @@ -34,13 +41,13 @@ func DataSourceDataUsers() common.Resource { return fmt.Errorf("cannot find users with display name containing %s", data.DisplayNameContains) } - var users []map[string]interface{} + var users []UserInfo for _, u := range userList { - user := map[string]interface{}{ - "id": u.Id, - "user_name": u.UserName, - "display_name": u.DisplayName, + user := UserInfo{ + Id: u.Id, + UserName: u.UserName, + DisplayName: u.DisplayName, } users = append(users, user) } diff --git a/scim/data_users_test.go b/scim/data_users_test.go index 0d45fa9a0c..13fecdc47e 100755 --- a/scim/data_users_test.go +++ b/scim/data_users_test.go @@ -3,19 +3,50 @@ package scim import ( "testing" + "github.com/databricks/databricks-sdk-go/experimental/mocks" + "github.com/databricks/databricks-sdk-go/service/iam" "github.com/databricks/terraform-provider-databricks/qa" + "github.com/stretchr/testify/mock" ) func TestDataSourceDataUsers(t *testing.T) { qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - // TODO: run this test to get fixtures + MockAccountClientFunc: func(m *mocks.MockAccountClient) { + e := m.GetMockAccountUsersAPI() + e.On("ListAll", + mock.Anything, + mock.MatchedBy(func(req iam.ListAccountUsersRequest) bool { + return req.Filter == `displayName co "testuser"` && + req.Attributes == "id,userName,displayName" + })).Return([]iam.User{ + { + Id: "123", + UserName: "testuser@example.com", + DisplayName: "testuser", + }, + { + Id: "456", + UserName: "testuser2@example.com", + DisplayName: "testuser2", + }, + }, nil) }, Resource: DataSourceDataUsers(), Read: true, NonWritable: true, ID: "_", - }.ApplyNoError(t) + HCL: ` + display_name_contains = "testuser" + `, + }.ApplyAndExpectData(t, map[string]any{ + "users.#": 2, + "users.0.id": "123", + "users.0.user_name": "testuser@example.com", + "users.0.display_name": "testuser", + "users.1.id": "456", + "users.1.user_name": "testuser2@example.com", + "users.1.display_name": "testuser2", + }) } func TestCatalogsData_Error(t *testing.T) { From 1c4ad8567370cc6bbe639bb6eb21786363c2ccf6 Mon Sep 17 00:00:00 2001 From: dgomez04 Date: Tue, 17 Sep 2024 15:57:19 -0600 Subject: [PATCH 03/10] #3468: added 'user_name_contains' attribute to data_users.go to allow filtering by userName, and added additional test cases on data_users_test.go --- scim/data_users.go | 17 ++++- scim/data_users_test.go | 136 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 147 insertions(+), 6 deletions(-) diff --git a/scim/data_users.go b/scim/data_users.go index 576ed2ebb8..9c1b3783cf 100755 --- a/scim/data_users.go +++ b/scim/data_users.go @@ -19,6 +19,7 @@ func DataSourceDataUsers() common.Resource { type DataUsers struct { DisplayNameContains string `json:"display_name_contains,omitempty" tf:"computed"` + UserNameContains string `json:"user_name_contains,omitempty" tf:"computed"` Users []UserInfo `json:"users,omitempty" tf:"computed"` } @@ -27,7 +28,13 @@ func DataSourceDataUsers() common.Resource { Attributes: "id,userName,displayName", } - if data.DisplayNameContains != "" { + if data.DisplayNameContains != "" && data.UserNameContains != "" { + return fmt.Errorf("exactly one of display_name_contains or user_name_contains should be specified, not both") + } + + if data.UserNameContains != "" { + listRequest.Filter = fmt.Sprintf("userName co \"%s\"", data.UserNameContains) + } else if data.DisplayNameContains != "" { listRequest.Filter = fmt.Sprintf("displayName co \"%s\"", data.DisplayNameContains) } @@ -38,7 +45,13 @@ func DataSourceDataUsers() common.Resource { } if len(userList) == 0 { - return fmt.Errorf("cannot find users with display name containing %s", data.DisplayNameContains) + if data.DisplayNameContains != "" { + return fmt.Errorf("cannot find users with display name containing %s", data.DisplayNameContains) + } else if data.UserNameContains != "" { + return fmt.Errorf("cannot find users with username containing %s", data.UserNameContains) + } else { + return fmt.Errorf("no users found") + } } var users []UserInfo diff --git a/scim/data_users_test.go b/scim/data_users_test.go index 13fecdc47e..5c19f8342c 100755 --- a/scim/data_users_test.go +++ b/scim/data_users_test.go @@ -1,6 +1,7 @@ package scim import ( + "fmt" "testing" "github.com/databricks/databricks-sdk-go/experimental/mocks" @@ -9,7 +10,7 @@ import ( "github.com/stretchr/testify/mock" ) -func TestDataSourceDataUsers(t *testing.T) { +func TestDataSourceDataUsers_DisplayNameContains(t *testing.T) { qa.ResourceFixture{ MockAccountClientFunc: func(m *mocks.MockAccountClient) { e := m.GetMockAccountUsersAPI() @@ -49,12 +50,139 @@ func TestDataSourceDataUsers(t *testing.T) { }) } -func TestCatalogsData_Error(t *testing.T) { +func TestDataSourceDataUsers_UserNameContains(t *testing.T) { qa.ResourceFixture{ - Fixtures: qa.HTTPFailures, + MockAccountClientFunc: func(m *mocks.MockAccountClient) { + e := m.GetMockAccountUsersAPI() + e.On("ListAll", + mock.Anything, + mock.MatchedBy(func(req iam.ListAccountUsersRequest) bool { + return req.Filter == `userName co "testuser"` && + req.Attributes == "id,userName,displayName" + })).Return([]iam.User{ + { + Id: "123", + UserName: "testuser@example.com", + DisplayName: "testuser", + }, + { + Id: "456", + UserName: "testuser2@example.com", + DisplayName: "testuser2", + }, + }, nil) + }, + Resource: DataSourceDataUsers(), + Read: true, + NonWritable: true, + ID: "_", + HCL: ` + user_name_contains = "testuser" + `, + }.ApplyAndExpectData(t, map[string]any{ + "users.#": 2, + "users.0.id": "123", + "users.0.user_name": "testuser@example.com", + "users.0.display_name": "testuser", + "users.1.id": "456", + "users.1.user_name": "testuser2@example.com", + "users.1.display_name": "testuser2", + }) +} + +func TestDataSourceDataUsers_BothFiltersSpecified(t *testing.T) { + qa.ResourceFixture{ + Resource: DataSourceDataUsers(), + Read: true, + NonWritable: true, + ID: "_", + HCL: ` + display_name_contains = "user" + user_name_contains = "example.com" + `, + }.ExpectError(t, "exactly one of display_name_contains or user_name_contains should be specified, not both") +} + +func TestDataSourceDataUsersNoUsers(t *testing.T) { + qa.ResourceFixture{ + MockAccountClientFunc: func(m *mocks.MockAccountClient) { + e := m.GetMockAccountUsersAPI() + e.On("ListAll", + mock.Anything, + mock.MatchedBy(func(req iam.ListAccountUsersRequest) bool { + return req.Filter == `displayName co "testuser"` && + req.Attributes == "id,userName,displayName" + })).Return([]iam.User{}, nil) + }, Resource: DataSourceDataUsers(), Read: true, NonWritable: true, ID: "_", - }.ExpectError(t, "i'm a teapot") + HCL: ` + display_name_contains = "testuser" + `, + }.ExpectError(t, "cannot find users with display name containing testuser") +} + +func TestDataSourceDataUsersNoFilter(t *testing.T) { + qa.ResourceFixture{ + MockAccountClientFunc: func(m *mocks.MockAccountClient) { + e := m.GetMockAccountUsersAPI() + e.On("ListAll", + mock.Anything, + mock.MatchedBy(func(req iam.ListAccountUsersRequest) bool { + return req.Attributes == "id,userName,displayName" + })).Return([]iam.User{ + { + Id: "123", + UserName: "testuser@example.com", + DisplayName: "testuser", + }, + { + Id: "456", + UserName: "testuser2@example.com", + DisplayName: "testuser2", + }, + { + Id: "789", + UserName: "testuser3@example.com", + DisplayName: "testuser3", + }, + }, nil) + }, + Resource: DataSourceDataUsers(), + Read: true, + NonWritable: true, + ID: "_", + }.ApplyAndExpectData(t, map[string]any{ + "users.#": 3, + "users.0.id": "123", + "users.0.user_name": "testuser@example.com", + "users.0.display_name": "testuser", + "users.1.id": "456", + "users.1.user_name": "testuser2@example.com", + "users.1.display_name": "testuser2", + "users.2.id": "789", + "users.2.user_name": "testuser3@example.com", + "users.2.display_name": "testuser3", + }) +} + +func TestDataSourceDataUsers_APIError(t *testing.T) { + qa.ResourceFixture{ + MockAccountClientFunc: func(m *mocks.MockAccountClient) { + usersAPI := m.GetMockAccountUsersAPI() + usersAPI.On("ListAll", + mock.Anything, + mock.Anything, + ).Return(nil, fmt.Errorf("api error")) + }, + Resource: DataSourceDataUsers(), + Read: true, + NonWritable: true, + ID: "_", + HCL: ` + display_name_contains = "testuser" + `, + }.ExpectError(t, "api error") } From 772799540267fe4f373ca6e10e63763838a7dd2e Mon Sep 17 00:00:00 2001 From: dgomez04 Date: Tue, 17 Sep 2024 16:24:46 -0600 Subject: [PATCH 04/10] #3468: added acceptance tests for data_users --- internal/acceptance/data_users_test.go | 67 ++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 internal/acceptance/data_users_test.go diff --git a/internal/acceptance/data_users_test.go b/internal/acceptance/data_users_test.go new file mode 100644 index 0000000000..9c624e28d2 --- /dev/null +++ b/internal/acceptance/data_users_test.go @@ -0,0 +1,67 @@ +package acceptance + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/terraform" +) + +func TestAccDataSourceDataUsers_DisplayNameContains(t *testing.T) { + accountLevel(t, step{ + Template: ` + data "databricks_data_users" "this" { + display_name_contains = "testuser" + }`, + Check: func(s *terraform.State) error { + r, ok := s.RootModule().Resources["data.databricks_data_users.this"] + if !ok { + return fmt.Errorf("data not found in state") + } + ids := r.Primary.Attributes["users.#"] + if ids == "" { + return fmt.Errorf("users is empty: %v", r.Primary.Attributes) + } + return nil + }, + }) +} + +func TestAccDataSourceDataUsers_UserNameContains(t *testing.T) { + accountLevel(t, step{ + Template: ` + data "databricks_data_users" "this" { + user_name_contains = "example.com" + }`, + Check: func(s *terraform.State) error { + r, ok := s.RootModule().Resources["data.databricks_data_users.this"] + if !ok { + return fmt.Errorf("data not found in state") + } + usersCount := r.Primary.Attributes["users.#"] + if usersCount == "" || usersCount == "0" { + return fmt.Errorf("users list is empty: %v", r.Primary.Attributes) + } + return nil + }, + }) +} + +func TestAccDataSourceDataUsers_NoFilters(t *testing.T) { + accountLevel(t, step{ + Template: ` + data "databricks_data_users" "this" { + }`, + Check: func(s *terraform.State) error { + r, ok := s.RootModule().Resources["data.databricks_data_users.this"] + if !ok { + return fmt.Errorf("data not found in state") + } + usersCount := r.Primary.Attributes["users.#"] + if usersCount == "" || usersCount == "0" { + return fmt.Errorf("users list is empty: %v", r.Primary.Attributes) + } + return nil + }, + }) +} From d5a5f7d1067187d48c6b5a961337b6b34859c812 Mon Sep 17 00:00:00 2001 From: dgomez04 Date: Tue, 17 Sep 2024 16:49:09 -0600 Subject: [PATCH 05/10] #3468: added documentation for databricks_users data source. --- docs/data-sources/users.md | 63 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 docs/data-sources/users.md diff --git a/docs/data-sources/users.md b/docs/data-sources/users.md new file mode 100644 index 0000000000..b3c2cbcd96 --- /dev/null +++ b/docs/data-sources/users.md @@ -0,0 +1,63 @@ +--- +subcategory: "Security" +--- + +# databricks_users Data Source + +->**Note** This is an account-level data source. + +-> **Note** If you have a fully automated setup with workspaces created by [databricks_mws_workspaces](../resources/mws_workspaces.md) or [azurerm_databricks_workspace](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/databricks_workspace), please make sure to add [depends_on attribute](../guides/troubleshooting.md#data-resources-and-authentication-is-not-configured-errors) in order to prevent _default auth: cannot configure default credentials_ errors. + +Retrieves information about multiple [databricks_user](../resources/user.md) resources. + +## Example Usage + +Adding a subset of users to a group + +```hcl +data "databricks_users" "company_users" { + user_name_contains = "@domain.org" +} + +resource "databricks_group" "data_users_group" { + display_name = "Data Users" +} + +resource "databricks_group_member" "add_users_to_group" { + for_each = { for user in data.databricks_users.company_users.users : user.id => user } + group_id = databricks_group.data_users_group.id + member_id = each.value.id +} +``` + +## Argument Reference + +This data source allows you to filter the list of users using the following optional arguments: + +- `display_name_contains` - (Optional) A substring to filter users by their display name. Only users whose display names contain this substring will be included in the results. +- `user_name_contains` - (Optional) A substring to filter users by their username. Only users whose usernames contain this substring will be included in the results. + +->**Note** You can specify **exactly one** of `display_name_contains` or `user_name_contains`. If neither is specified, all users will be returned. + +## Attribute Reference + +This data source exposes the following attributes: + +- `users` - A list of users matching the specified criteria. Each user has the following attributes: + - `id` - The ID of the user. + - `user_name` - The username of the user. + - `display_name` - The display name of the user. + +## Related Resources + +The following resources are used in the same context: + +- [**databricks_user**](../resources/user.md): Resource to manage individual users in Databricks. + +- [**databricks_group**](../resources/group.md): Resource to manage groups in Databricks. + +- [**databricks_group_member**](../resources/group_member.md): Resource to manage group memberships by adding users to groups. + +- [**databricks_permissions**](../resources/permissions.md): Resource to manage access control in the Databricks workspace. + +- [**databricks_current_user**](current_user.md): Data source to retrieve information about the user or service principal that is calling the Databricks REST API. From 300991035b3d62c5c8f36db8661f07c4eb7a0611 Mon Sep 17 00:00:00 2001 From: dgomez04 Date: Fri, 20 Sep 2024 10:07:31 -0600 Subject: [PATCH 06/10] renamed resource func to DataSourceUsers, removed various acceptance tests, and added the resource definition into the provider --- internal/acceptance/data_users_test.go | 41 +------------------------- internal/providers/sdkv2/sdkv2.go | 1 + scim/data_users.go | 2 +- scim/data_users_test.go | 24 +++++++-------- 4 files changed, 15 insertions(+), 53 deletions(-) diff --git a/internal/acceptance/data_users_test.go b/internal/acceptance/data_users_test.go index 9c624e28d2..0107203bc9 100644 --- a/internal/acceptance/data_users_test.go +++ b/internal/acceptance/data_users_test.go @@ -7,7 +7,7 @@ import ( "github.com/hashicorp/terraform-plugin-testing/terraform" ) -func TestAccDataSourceDataUsers_DisplayNameContains(t *testing.T) { +func TestAccDataSourceDataUsers(t *testing.T) { accountLevel(t, step{ Template: ` data "databricks_data_users" "this" { @@ -26,42 +26,3 @@ func TestAccDataSourceDataUsers_DisplayNameContains(t *testing.T) { }, }) } - -func TestAccDataSourceDataUsers_UserNameContains(t *testing.T) { - accountLevel(t, step{ - Template: ` - data "databricks_data_users" "this" { - user_name_contains = "example.com" - }`, - Check: func(s *terraform.State) error { - r, ok := s.RootModule().Resources["data.databricks_data_users.this"] - if !ok { - return fmt.Errorf("data not found in state") - } - usersCount := r.Primary.Attributes["users.#"] - if usersCount == "" || usersCount == "0" { - return fmt.Errorf("users list is empty: %v", r.Primary.Attributes) - } - return nil - }, - }) -} - -func TestAccDataSourceDataUsers_NoFilters(t *testing.T) { - accountLevel(t, step{ - Template: ` - data "databricks_data_users" "this" { - }`, - Check: func(s *terraform.State) error { - r, ok := s.RootModule().Resources["data.databricks_data_users.this"] - if !ok { - return fmt.Errorf("data not found in state") - } - usersCount := r.Primary.Attributes["users.#"] - if usersCount == "" || usersCount == "0" { - return fmt.Errorf("users list is empty: %v", r.Primary.Attributes) - } - return nil - }, - }) -} diff --git a/internal/providers/sdkv2/sdkv2.go b/internal/providers/sdkv2/sdkv2.go index b9ee686121..2b26624b14 100644 --- a/internal/providers/sdkv2/sdkv2.go +++ b/internal/providers/sdkv2/sdkv2.go @@ -122,6 +122,7 @@ func DatabricksProvider() *schema.Provider { "databricks_volume": catalog.DataSourceVolume().ToResource(), "databricks_volumes": catalog.DataSourceVolumes().ToResource(), "databricks_user": scim.DataSourceUser().ToResource(), + "databricks_users": scim.DataSourceUsers().ToResource(), "databricks_zones": clusters.DataSourceClusterZones().ToResource(), }, ResourcesMap: map[string]*schema.Resource{ // must be in alphabetical order diff --git a/scim/data_users.go b/scim/data_users.go index 9c1b3783cf..b3fcd03782 100755 --- a/scim/data_users.go +++ b/scim/data_users.go @@ -9,7 +9,7 @@ import ( "github.com/databricks/terraform-provider-databricks/common" ) -func DataSourceDataUsers() common.Resource { +func DataSourceUsers() common.Resource { type UserInfo struct { Id string `json:"id,omitempty" tf:"computed"` diff --git a/scim/data_users_test.go b/scim/data_users_test.go index 5c19f8342c..6c11e97594 100755 --- a/scim/data_users_test.go +++ b/scim/data_users_test.go @@ -10,7 +10,7 @@ import ( "github.com/stretchr/testify/mock" ) -func TestDataSourceDataUsers_DisplayNameContains(t *testing.T) { +func TestDataSourceUsers_DisplayNameContains(t *testing.T) { qa.ResourceFixture{ MockAccountClientFunc: func(m *mocks.MockAccountClient) { e := m.GetMockAccountUsersAPI() @@ -32,7 +32,7 @@ func TestDataSourceDataUsers_DisplayNameContains(t *testing.T) { }, }, nil) }, - Resource: DataSourceDataUsers(), + Resource: DataSourceUsers(), Read: true, NonWritable: true, ID: "_", @@ -50,7 +50,7 @@ func TestDataSourceDataUsers_DisplayNameContains(t *testing.T) { }) } -func TestDataSourceDataUsers_UserNameContains(t *testing.T) { +func TestDataSourceUsers_UserNameContains(t *testing.T) { qa.ResourceFixture{ MockAccountClientFunc: func(m *mocks.MockAccountClient) { e := m.GetMockAccountUsersAPI() @@ -72,7 +72,7 @@ func TestDataSourceDataUsers_UserNameContains(t *testing.T) { }, }, nil) }, - Resource: DataSourceDataUsers(), + Resource: DataSourceUsers(), Read: true, NonWritable: true, ID: "_", @@ -90,9 +90,9 @@ func TestDataSourceDataUsers_UserNameContains(t *testing.T) { }) } -func TestDataSourceDataUsers_BothFiltersSpecified(t *testing.T) { +func TestDataSourceUsers_BothFiltersSpecified(t *testing.T) { qa.ResourceFixture{ - Resource: DataSourceDataUsers(), + Resource: DataSourceUsers(), Read: true, NonWritable: true, ID: "_", @@ -103,7 +103,7 @@ func TestDataSourceDataUsers_BothFiltersSpecified(t *testing.T) { }.ExpectError(t, "exactly one of display_name_contains or user_name_contains should be specified, not both") } -func TestDataSourceDataUsersNoUsers(t *testing.T) { +func TestDataSourceUsersNoUsers(t *testing.T) { qa.ResourceFixture{ MockAccountClientFunc: func(m *mocks.MockAccountClient) { e := m.GetMockAccountUsersAPI() @@ -114,7 +114,7 @@ func TestDataSourceDataUsersNoUsers(t *testing.T) { req.Attributes == "id,userName,displayName" })).Return([]iam.User{}, nil) }, - Resource: DataSourceDataUsers(), + Resource: DataSourceUsers(), Read: true, NonWritable: true, ID: "_", @@ -124,7 +124,7 @@ func TestDataSourceDataUsersNoUsers(t *testing.T) { }.ExpectError(t, "cannot find users with display name containing testuser") } -func TestDataSourceDataUsersNoFilter(t *testing.T) { +func TestDataSourceUsersNoFilter(t *testing.T) { qa.ResourceFixture{ MockAccountClientFunc: func(m *mocks.MockAccountClient) { e := m.GetMockAccountUsersAPI() @@ -150,7 +150,7 @@ func TestDataSourceDataUsersNoFilter(t *testing.T) { }, }, nil) }, - Resource: DataSourceDataUsers(), + Resource: DataSourceUsers(), Read: true, NonWritable: true, ID: "_", @@ -168,7 +168,7 @@ func TestDataSourceDataUsersNoFilter(t *testing.T) { }) } -func TestDataSourceDataUsers_APIError(t *testing.T) { +func TestDataSourceUsers_APIError(t *testing.T) { qa.ResourceFixture{ MockAccountClientFunc: func(m *mocks.MockAccountClient) { usersAPI := m.GetMockAccountUsersAPI() @@ -177,7 +177,7 @@ func TestDataSourceDataUsers_APIError(t *testing.T) { mock.Anything, ).Return(nil, fmt.Errorf("api error")) }, - Resource: DataSourceDataUsers(), + Resource: DataSourceUsers(), Read: true, NonWritable: true, ID: "_", From d572c1cf62968a2833f74fc5f0cf698ce5577afc Mon Sep 17 00:00:00 2001 From: dgomez04 Date: Fri, 20 Sep 2024 10:33:52 -0600 Subject: [PATCH 07/10] added correct reference to data resource 'databricks_users' on the acceptance test. --- internal/acceptance/data_users_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/acceptance/data_users_test.go b/internal/acceptance/data_users_test.go index 0107203bc9..c8730eee96 100644 --- a/internal/acceptance/data_users_test.go +++ b/internal/acceptance/data_users_test.go @@ -10,7 +10,7 @@ import ( func TestAccDataSourceDataUsers(t *testing.T) { accountLevel(t, step{ Template: ` - data "databricks_data_users" "this" { + data "databricks_users" "this" { display_name_contains = "testuser" }`, Check: func(s *terraform.State) error { From d316517a17588aab0aad8a6c18f1f85718f22d71 Mon Sep 17 00:00:00 2001 From: dgomez04 Date: Fri, 20 Sep 2024 10:37:18 -0600 Subject: [PATCH 08/10] name format changes to acceptance tests --- internal/acceptance/data_users_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/acceptance/data_users_test.go b/internal/acceptance/data_users_test.go index c8730eee96..29c6098099 100644 --- a/internal/acceptance/data_users_test.go +++ b/internal/acceptance/data_users_test.go @@ -14,7 +14,7 @@ func TestAccDataSourceDataUsers(t *testing.T) { display_name_contains = "testuser" }`, Check: func(s *terraform.State) error { - r, ok := s.RootModule().Resources["data.databricks_data_users.this"] + r, ok := s.RootModule().Resources["data.databricks_users.this"] if !ok { return fmt.Errorf("data not found in state") } From 56d69948b6aa2924a3f02a54a96f1b8c9bfefac1 Mon Sep 17 00:00:00 2001 From: dgomez04 Date: Wed, 2 Oct 2024 10:05:12 -0600 Subject: [PATCH 09/10] modified acceptance test --- internal/acceptance/data_users_test.go | 58 +++++++++++++++++++------- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/internal/acceptance/data_users_test.go b/internal/acceptance/data_users_test.go index 29c6098099..d758200c29 100644 --- a/internal/acceptance/data_users_test.go +++ b/internal/acceptance/data_users_test.go @@ -1,28 +1,54 @@ package acceptance import ( - "fmt" "testing" "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) +const dataSourceTemplate = ` + resource "databricks_user" "user1" { + user_name = "testuser1@databricks.com" + } + + resource "databricks_user" "user2" { + user_name = "testuser2@databricks.com" + } + + data "databricks_users" "this" { + user_name_contains = "testuser" + } +` + +func checkUsersDataSourcePopulated(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + ds, ok := s.Modules[0].Resources["data.databricks_users.this"] + require.True(t, ok, "data.databricks_users.this has to be there") + + usersCount := ds.Primary.Attributes["users.#"] + require.Equal(t, "2", usersCount, "expected two users") + + userIds := []string{ + ds.Primary.Attributes["users.0.id"], + ds.Primary.Attributes["users.1.id"], + } + + expectedUserIDs := []string{ + s.Modules[0].Resources["databricks_user.user1"].Primary.ID, + s.Modules[0].Resources["databricks_user.user2"].Primary.ID, + } + + assert.ElementsMatch(t, expectedUserIDs, userIds, "expected user ids to match") + + return nil + } +} + func TestAccDataSourceDataUsers(t *testing.T) { accountLevel(t, step{ - Template: ` - data "databricks_users" "this" { - display_name_contains = "testuser" - }`, - Check: func(s *terraform.State) error { - r, ok := s.RootModule().Resources["data.databricks_users.this"] - if !ok { - return fmt.Errorf("data not found in state") - } - ids := r.Primary.Attributes["users.#"] - if ids == "" { - return fmt.Errorf("users is empty: %v", r.Primary.Attributes) - } - return nil - }, + Template: dataSourceTemplate, + Check: checkUsersDataSourcePopulated(t), }) } From 7e4b3d96d571ea9f8ff140b2b53b8d53cfa5c5d3 Mon Sep 17 00:00:00 2001 From: dgomez04 Date: Wed, 2 Oct 2024 10:09:49 -0600 Subject: [PATCH 10/10] fixed integration test to point to correct import --- internal/acceptance/data_users_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/acceptance/data_users_test.go b/internal/acceptance/data_users_test.go index d758200c29..21c1764798 100644 --- a/internal/acceptance/data_users_test.go +++ b/internal/acceptance/data_users_test.go @@ -47,7 +47,7 @@ func checkUsersDataSourcePopulated(t *testing.T) func(s *terraform.State) error } func TestAccDataSourceDataUsers(t *testing.T) { - accountLevel(t, step{ + AccountLevel(t, Step{ Template: dataSourceTemplate, Check: checkUsersDataSourcePopulated(t), })