Skip to content

Commit

Permalink
[datadog_user] Add support for exact_match in data source (#1968)
Browse files Browse the repository at this point in the history
* add support for exact match

* fix docs
  • Loading branch information
skarimo authored Jun 16, 2023
1 parent a9a73d6 commit 651ff2f
Show file tree
Hide file tree
Showing 8 changed files with 533 additions and 9 deletions.
34 changes: 33 additions & 1 deletion datadog/data_source_datadog_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ func dataSourceDatadogUser() *schema.Resource {
Type: schema.TypeString,
Required: true,
},
"exact_match": {
Description: "When true, `filter` string is exact matched againts the users `email`, followed by `name` attribute.",
Type: schema.TypeBool,
Default: false,
Optional: true,
},
// Computed values
"email": {
Description: "Email of the user.",
Expand All @@ -41,6 +47,7 @@ func dataSourceDatadogUserRead(ctx context.Context, d *schema.ResourceData, meta
apiInstances := providerConf.DatadogApiInstances
auth := providerConf.Auth
filter := d.Get("filter").(string) // string | Filter all users by the given string. Defaults to no filtering. (optional) // string | Filter on status attribute. Comma separated list, with possible values `Active`, `Pending`, and `Disabled`. Defaults to no filtering. (optional)
exactMatch := d.Get("exact_match").(bool)
optionalParams := datadogV2.ListUsersOptionalParameters{
Filter: &filter,
}
Expand All @@ -53,14 +60,39 @@ func dataSourceDatadogUserRead(ctx context.Context, d *schema.ResourceData, meta
return diag.FromErr(err)
}
users := res.GetData()
if len(users) > 1 {
if len(users) > 1 && !exactMatch {
return diag.Errorf("your query returned more than one result for filter \"%s\", please try a more specific search criteria",
filter,
)
} else if len(users) == 0 {
return diag.Errorf("didn't find any user matching filter string \"%s\"", filter)
}

matchedUser := users[0]
if exactMatch {
matchCount := 0
for _, user := range users {
if user.Attributes.GetEmail() == filter {
matchedUser = user
matchCount++
continue
}
if user.Attributes.GetName() == filter {
matchedUser = user
matchCount++
continue
}
}
if matchCount > 1 {
return diag.Errorf("your query returned more than one result for filter with exact match \"%s\", please try a more specific search criteria",
filter,
)
}
if matchCount == 0 {
return diag.Errorf("didn't find any user matching filter string with exact match \"%s\"", filter)
}
}

d.SetId(matchedUser.GetId())
if err := d.Set("name", matchedUser.Attributes.GetName()); err != nil {
return diag.FromErr(err)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2023-06-15T16:12:30.013645-04:00

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2023-06-15T16:14:26.293469-04:00
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
---
version: 1
interactions:
- request:
body: |
{"data":{"attributes":{"email":"othertf-testaccdatadoguserdatasourcewithexactmatcherror-local-1686860066@example.com"},"relationships":{"roles":{"data":[]}},"type":"users"}}
form: {}
headers:
Accept:
- application/json
Content-Type:
- application/json
url: https://api.datadoghq.com/api/v2/users
method: POST
response:
body: |
{"data":{"type":"users","id":"3ab23d20-0bb9-11ee-bbf8-f23132112677","attributes":{"name":null,"handle":"othertf-testaccdatadoguserdatasourcewithexactmatcherror-local-1686860066@example.com","created_at":"2023-06-15T20:14:27.668685+00:00","modified_at":"2023-06-15T20:14:27.670771+00:00","email":"othertf-testaccdatadoguserdatasourcewithexactmatcherror-local-1686860066@example.com","icon":"https://secure.gravatar.com/avatar/4b98fced45ce7e33e9b2ff6a0fcc420f?s=48&d=retro","title":null,"verified":false,"service_account":false,"disabled":false,"allowed_login_methods":[],"status":"Pending"},"relationships":{"roles":{"data":[]},"org":{"data":{"type":"orgs","id":"4dee724d-00cc-11ea-a77b-570c9d03c6c5"}}}}}
headers:
Content-Type:
- application/json
status: 201 Created
code: 201
duration: ""
- request:
body: |
{"data":{"attributes":{"email":"tf-testaccdatadoguserdatasourcewithexactmatcherror-local-1686860066@example.com"},"relationships":{"roles":{"data":[]}},"type":"users"}}
form: {}
headers:
Accept:
- application/json
Content-Type:
- application/json
url: https://api.datadoghq.com/api/v2/users
method: POST
response:
body: |
{"data":{"type":"users","id":"3ab78abe-0bb9-11ee-bbf8-f23132112677","attributes":{"name":null,"handle":"tf-testaccdatadoguserdatasourcewithexactmatcherror-local-1686860066@example.com","created_at":"2023-06-15T20:14:27.703650+00:00","modified_at":"2023-06-15T20:14:27.708243+00:00","email":"tf-testaccdatadoguserdatasourcewithexactmatcherror-local-1686860066@example.com","icon":"https://secure.gravatar.com/avatar/37cbde901c4ff41f71273bfa9ac34c15?s=48&d=retro","title":null,"verified":false,"service_account":false,"disabled":false,"allowed_login_methods":[],"status":"Pending"},"relationships":{"roles":{"data":[]},"org":{"data":{"type":"orgs","id":"4dee724d-00cc-11ea-a77b-570c9d03c6c5"}}}}}
headers:
Content-Type:
- application/json
status: 201 Created
code: 201
duration: ""
- request:
body: |
{"data":[{"relationships":{"user":{"data":{"id":"3ab23d20-0bb9-11ee-bbf8-f23132112677","type":"users"}}},"type":"user_invitations"}]}
form: {}
headers:
Accept:
- application/json
Content-Type:
- application/json
url: https://api.datadoghq.com/api/v2/user_invitations
method: POST
response:
body: |
{"data":[{"type":"user_invitations","id":"3adc6fba-0bb9-11ee-93a7-da7ad0900002","attributes":{"uuid":"3adc6fba-0bb9-11ee-93a7-da7ad0900002","login_method":null,"invite_type":"basic_invite","created_at":"2023-06-15T20:14:27.943629+00:00","expires_at":"2023-06-17T20:14:27.863220+00:00"},"relationships":{"user":{"data":{"type":"users","id":"3ab23d20-0bb9-11ee-bbf8-f23132112677"}}}}]}
headers:
Content-Type:
- application/json
status: 201 Created
code: 201
duration: ""
- request:
body: |
{"data":[{"relationships":{"user":{"data":{"id":"3ab78abe-0bb9-11ee-bbf8-f23132112677","type":"users"}}},"type":"user_invitations"}]}
form: {}
headers:
Accept:
- application/json
Content-Type:
- application/json
url: https://api.datadoghq.com/api/v2/user_invitations
method: POST
response:
body: |
{"data":[{"type":"user_invitations","id":"3adf13b4-0bb9-11ee-a6cc-da7ad0900002","attributes":{"uuid":"3adf13b4-0bb9-11ee-a6cc-da7ad0900002","login_method":null,"invite_type":"basic_invite","created_at":"2023-06-15T20:14:27.961604+00:00","expires_at":"2023-06-17T20:14:27.857120+00:00"},"relationships":{"user":{"data":{"type":"users","id":"3ab78abe-0bb9-11ee-bbf8-f23132112677"}}}}]}
headers:
Content-Type:
- application/json
status: 201 Created
code: 201
duration: ""
- request:
body: ""
form: {}
headers:
Accept:
- application/json
url: https://api.datadoghq.com/api/v2/users?filter=tf-testaccdatadoguserdatasourcewithexactmatcherror-local-1686860066%40example.com
method: GET
response:
body: |
{"data":[{"type":"users","id":"3ab23d20-0bb9-11ee-bbf8-f23132112677","attributes":{"name":null,"handle":"othertf-testaccdatadoguserdatasourcewithexactmatcherror-local-1686860066@example.com","created_at":"2023-06-15T20:14:27.668685+00:00","modified_at":"2023-06-15T20:14:27.670771+00:00","email":"othertf-testaccdatadoguserdatasourcewithexactmatcherror-local-1686860066@example.com","icon":"https://secure.gravatar.com/avatar/4b98fced45ce7e33e9b2ff6a0fcc420f?s=48&d=retro","title":null,"verified":false,"service_account":false,"disabled":false,"allowed_login_methods":[],"status":"Pending"},"relationships":{"roles":{"data":[]},"org":{"data":{"type":"orgs","id":"4dee724d-00cc-11ea-a77b-570c9d03c6c5"}}}},{"type":"users","id":"3ab78abe-0bb9-11ee-bbf8-f23132112677","attributes":{"name":null,"handle":"tf-testaccdatadoguserdatasourcewithexactmatcherror-local-1686860066@example.com","created_at":"2023-06-15T20:14:27.703650+00:00","modified_at":"2023-06-15T20:14:27.708243+00:00","email":"tf-testaccdatadoguserdatasourcewithexactmatcherror-local-1686860066@example.com","icon":"https://secure.gravatar.com/avatar/37cbde901c4ff41f71273bfa9ac34c15?s=48&d=retro","title":null,"verified":false,"service_account":false,"disabled":false,"allowed_login_methods":[],"status":"Pending"},"relationships":{"roles":{"data":[]},"org":{"data":{"type":"orgs","id":"4dee724d-00cc-11ea-a77b-570c9d03c6c5"}}}}],"meta":{"page":{"total_count":175486,"total_filtered_count":2}}}
headers:
Content-Type:
- application/json
status: 200 OK
code: 200
duration: ""
- request:
body: ""
form: {}
headers:
Accept:
- '*/*'
url: https://api.datadoghq.com/api/v2/users/3ab23d20-0bb9-11ee-bbf8-f23132112677
method: DELETE
response:
body: ""
headers: {}
status: 204 No Content
code: 204
duration: ""
- request:
body: ""
form: {}
headers:
Accept:
- '*/*'
url: https://api.datadoghq.com/api/v2/users/3ab78abe-0bb9-11ee-bbf8-f23132112677
method: DELETE
response:
body: ""
headers: {}
status: 204 No Content
code: 204
duration: ""
- request:
body: ""
form: {}
headers:
Accept:
- application/json
url: https://api.datadoghq.com/api/v2/users/3ab23d20-0bb9-11ee-bbf8-f23132112677
method: GET
response:
body: |
{"data":{"type":"users","id":"3ab23d20-0bb9-11ee-bbf8-f23132112677","attributes":{"name":null,"handle":"othertf-testaccdatadoguserdatasourcewithexactmatcherror-local-1686860066@example.com","created_at":"2023-06-15T20:14:27.668685+00:00","modified_at":"2023-06-15T20:14:34.176472+00:00","email":"othertf-testaccdatadoguserdatasourcewithexactmatcherror-local-1686860066@example.com","icon":"https://secure.gravatar.com/avatar/4b98fced45ce7e33e9b2ff6a0fcc420f?s=48&d=retro","title":null,"verified":false,"service_account":false,"disabled":true,"allowed_login_methods":[],"status":"Disabled"},"relationships":{"roles":{"data":[]},"org":{"data":{"type":"orgs","id":"4dee724d-00cc-11ea-a77b-570c9d03c6c5"}}}}}
headers:
Content-Type:
- application/json
status: 200 OK
code: 200
duration: ""
- request:
body: ""
form: {}
headers:
Accept:
- application/json
url: https://api.datadoghq.com/api/v2/users/3ab78abe-0bb9-11ee-bbf8-f23132112677
method: GET
response:
body: |
{"data":{"type":"users","id":"3ab78abe-0bb9-11ee-bbf8-f23132112677","attributes":{"name":null,"handle":"tf-testaccdatadoguserdatasourcewithexactmatcherror-local-1686860066@example.com","created_at":"2023-06-15T20:14:27.703650+00:00","modified_at":"2023-06-15T20:14:34.250169+00:00","email":"tf-testaccdatadoguserdatasourcewithexactmatcherror-local-1686860066@example.com","icon":"https://secure.gravatar.com/avatar/37cbde901c4ff41f71273bfa9ac34c15?s=48&d=retro","title":null,"verified":false,"service_account":false,"disabled":true,"allowed_login_methods":[],"status":"Disabled"},"relationships":{"roles":{"data":[]},"org":{"data":{"type":"orgs","id":"4dee724d-00cc-11ea-a77b-570c9d03c6c5"}}}}}
headers:
Content-Type:
- application/json
status: 200 OK
code: 200
duration: ""
70 changes: 62 additions & 8 deletions datadog/tests/data_source_datadog_user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,71 @@ func TestAccDatadogUserDatasourceError(t *testing.T) {
})
}

func TestAccDatadogUserDatasourceWithExactMatch(t *testing.T) {
t.Parallel()
ctx, accProviders := testAccProviders(context.Background(), t)
email := strings.ToLower(uniqueEntityName(ctx, t)) + "@example.com"
accProvider := testAccProvider(t, accProviders)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: accProviders,
CheckDestroy: testAccCheckDatadogUserV2Destroy(accProvider),
Steps: []resource.TestStep{
{
Config: testAccDatasourceUserWithExactMatchConfig(email, "true"),
Check: resource.TestCheckResourceAttr("data.datadog_user.test", "email", email),
},
},
})
}

func TestAccDatadogUserDatasourceWithExactMatchError(t *testing.T) {
t.Parallel()
ctx, accProviders := testAccProviders(context.Background(), t)
email := strings.ToLower(uniqueEntityName(ctx, t)) + "@example.com"
accProvider := testAccProvider(t, accProviders)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: accProviders,
CheckDestroy: testAccCheckDatadogUserV2Destroy(accProvider),
Steps: []resource.TestStep{
{
Config: testAccDatasourceUserWithExactMatchConfig(email, "false"),
ExpectError: regexp.MustCompile("your query returned more than one result for filter"),
},
},
})
}

func testAccDatasourceUserWithExactMatchConfig(uniq, exactMatch string) string {
return fmt.Sprintf(`
data "datadog_user" "test" {
filter = "%[1]s"
exact_match = %[2]s
depends_on = [ datadog_user.foo, datadog_user.bar ]
}
resource "datadog_user" "foo" {
email = "%[1]s"
}
resource "datadog_user" "bar" {
email = "other%[1]s"
}`, uniq, exactMatch)
}

func testAccDatasourceUserConfig(uniq string) string {
return fmt.Sprintf(`
data "datadog_user" "test" {
filter = "%s"
depends_on = [
datadog_user.foo
]
}
resource "datadog_user" "foo" {
data "datadog_user" "test" {
filter = "%s"
depends_on = [
datadog_user.foo
]
}
resource "datadog_user" "foo" {
email = "%s"
}`, uniq, uniq)
}`, uniq, uniq)
}

func testAccDatasourceUserError() string {
Expand Down
10 changes: 10 additions & 0 deletions docs/data-sources/user.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ description: |-

Use this data source to retrieve information about an existing user to use it in an other resources.

## Example Usage

```terraform
data "datadog_user" "test" {
filter = "user.name@company.com"
}
```

<!-- schema generated by tfplugindocs -->
## Schema
Expand All @@ -19,6 +25,10 @@ Use this data source to retrieve information about an existing user to use it in

- `filter` (String) Filter all users by the given string.

### Optional

- `exact_match` (Boolean) When true, `filter` string is exact matched againts the users `email`, followed by `name` attribute.

### Read-Only

- `email` (String) Email of the user.
Expand Down

0 comments on commit 651ff2f

Please sign in to comment.