Skip to content

Commit

Permalink
data.azuread_users: support the return_all_users property (#513)
Browse files Browse the repository at this point in the history
* First Stab

Have not added tests.

* Updated datasource - Include Elem

* Refactor to data_source - Added basic test

* Small fmt and refactor

* Forgot Docs

Added Documentation for the datasource.

* Further Fmt'ing - Apologies

* Delete Documentation

* added show_all_users

- Added show_all_users flag
- Implemented cross flag logic
- fetched all users logic and append to list

* Added basic test.

- Added basic test for showAllUsers flag
- Started second test to check for error but couldn't get it to work.

* Deleted old spare datasources

* Updated Documentation

* Fix first lint issue - removing redundent

* Trying to fix the linting

* Fixing linting and syntax

* Fixing lint? Last one?

* Removed redundent commented Test - Linting again?!

* Fixing linting issues (thanks)

* data.azuread_users: use ConflictsWith for ignore_missing, remove apply-time validation, rename `show_all_user` to `return_all_users`

Co-authored-by: Tom Bamford <[email protected]>
  • Loading branch information
Threpio and manicminer authored Sep 2, 2021
1 parent 7ed0969 commit dd84294
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 12 deletions.
5 changes: 3 additions & 2 deletions docs/data-sources/users.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ data "azuread_users" "users" {

The following arguments are supported:

* `mail_nicknames` - (Optional) The email aliases of the users.
* `ignore_missing` - (Optional) Ignore missing users and return users that were found. The data source will still fail if no users are found. Defaults to false.
* `mail_nicknames` - (Optional) The email aliases of the users.
* `object_ids` - (Optional) The object IDs of the users.
* `return_all_users` - (Optional) When `true`, the data source will return all users. Cannot be used with `ignore_missing`. Defaults to false.
* `user_principal_names` - (Optional) The user principal names (UPNs) of the users.

~> One of `user_principal_names`, `object_ids` or `mail_nicknames` must be specified. These _may_ be specified as an empty list, in which case no results will be returned.
~> Either `return_all_users`, or one of `user_principal_names`, `object_ids` or `mail_nicknames` must be specified. These _may_ be specified as an empty list, in which case no results will be returned.

## Attributes Reference

Expand Down
2 changes: 1 addition & 1 deletion internal/services/users/user_data_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func (UserDataSource) testCheckFunc(data acceptance.TestData) resource.TestCheck
check.That(data.ResourceName).Key("display_name").HasValue(fmt.Sprintf("acctestUser-%d-DisplayName", data.RandomInteger)),
check.That(data.ResourceName).Key("given_name").HasValue(fmt.Sprintf("acctestUser-%d-GivenName", data.RandomInteger)),
check.That(data.ResourceName).Key("job_title").HasValue(fmt.Sprintf("acctestUser-%d-Job", data.RandomInteger)),
//check.That(data.ResourceName).Key("mail").Exists(), // TODO only set for O365 domains
// check.That(data.ResourceName).Key("mail").Exists(), // TODO only set for O365 domains
check.That(data.ResourceName).Key("mail_nickname").HasValue(fmt.Sprintf("acctestUser-%d-MailNickname", data.RandomInteger)),
check.That(data.ResourceName).Key("mobile_phone").HasValue("(555) 555-5555"),
check.That(data.ResourceName).Key("object_id").IsUuid(),
Expand Down
39 changes: 30 additions & 9 deletions internal/services/users/users_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func usersData() *schema.Resource {
Type: schema.TypeList,
Optional: true,
Computed: true,
ExactlyOneOf: []string{"object_ids", "user_principal_names", "mail_nicknames"},
ExactlyOneOf: []string{"object_ids", "user_principal_names", "mail_nicknames", "return_all_users"},
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateDiagFunc: validate.NoEmptyStrings,
Expand All @@ -46,7 +46,7 @@ func usersData() *schema.Resource {
Type: schema.TypeList,
Optional: true,
Computed: true,
ExactlyOneOf: []string{"object_ids", "user_principal_names", "mail_nicknames"},
ExactlyOneOf: []string{"object_ids", "user_principal_names", "mail_nicknames", "return_all_users"},
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateDiagFunc: validate.UUID,
Expand All @@ -58,18 +58,28 @@ func usersData() *schema.Resource {
Type: schema.TypeList,
Optional: true,
Computed: true,
ExactlyOneOf: []string{"object_ids", "user_principal_names", "mail_nicknames"},
ExactlyOneOf: []string{"object_ids", "user_principal_names", "mail_nicknames", "return_all_users"},
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateDiagFunc: validate.NoEmptyStrings,
},
},

"ignore_missing": {
Description: "Ignore missing users and return users that were found. The data source will still fail if no users are found",
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "Ignore missing users and return users that were found. The data source will still fail if no users are found",
Type: schema.TypeBool,
Optional: true,
Default: false,
ConflictsWith: []string{"return_all_users"},
},

"return_all_users": {
Description: "Fetch all users with no filter and return all that were found. The data source will still fail if no users are found.",
Type: schema.TypeBool,
Optional: true,
Default: false,
ConflictsWith: []string{"ignore_missing"},
ExactlyOneOf: []string{"object_ids", "user_principal_names", "mail_nicknames", "return_all_users"},
},

"users": {
Expand Down Expand Up @@ -151,8 +161,18 @@ func usersDataSourceRead(ctx context.Context, d *schema.ResourceData, meta inter
var users []msgraph.User
var expectedCount int
ignoreMissing := d.Get("ignore_missing").(bool)
returnAllUsers := d.Get("return_all_users").(bool)

if upns, ok := d.Get("user_principal_names").([]interface{}); ok && len(upns) > 0 {
if returnAllUsers {
result, _, err := client.List(ctx, odata.Query{})
if err != nil {
return tf.ErrorDiagF(err, "Could not retrieve users")
}
if result == nil {
return tf.ErrorDiagF(errors.New("API returned nil result"), "Bad API Response")
}
users = append(users, *result...)
} else if upns, ok := d.Get("user_principal_names").([]interface{}); ok && len(upns) > 0 {
expectedCount = len(upns)
for _, v := range upns {
query := odata.Query{
Expand Down Expand Up @@ -223,7 +243,8 @@ func usersDataSourceRead(ctx context.Context, d *schema.ResourceData, meta inter
}
}

if !ignoreMissing && len(users) != expectedCount {
// Check that the right number of users were returned
if !returnAllUsers && !ignoreMissing && len(users) != expectedCount {
return tf.ErrorDiagF(fmt.Errorf("Expected: %d, Actual: %d", expectedCount, len(users)), "Unexpected number of users returned")
}

Expand Down
22 changes: 22 additions & 0 deletions internal/services/users/users_data_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,20 @@ func TestAccUsersDataSource_noNames(t *testing.T) {
}})
}

func TestAccUsersDataSource_returnAll(t *testing.T) {
data := acceptance.BuildTestData(t, "data.azuread_users", "test")

data.DataSourceTest(t, []resource.TestStep{{
Config: UsersDataSource{}.returnAll(),
Check: resource.ComposeTestCheckFunc(
check.That(data.ResourceName).Key("user_principal_names.#").Exists(),
check.That(data.ResourceName).Key("object_ids.#").Exists(),
check.That(data.ResourceName).Key("mail_nicknames.#").Exists(),
check.That(data.ResourceName).Key("users.#").Exists(),
),
}})
}

func (UsersDataSource) byUserPrincipalNames(data acceptance.TestData) string {
return fmt.Sprintf(`
%[1]s
Expand Down Expand Up @@ -192,3 +206,11 @@ data "azuread_users" "test" {
}
`
}

func (UsersDataSource) returnAll() string {
return `
data "azuread_users" "test" {
return_all_users = true
}
`
}

0 comments on commit dd84294

Please sign in to comment.