Skip to content

Commit d8ec8ab

Browse files
[IAM] Add data source to import org user using token auth (#2051)
1 parent 55da61e commit d8ec8ab

File tree

6 files changed

+190
-11
lines changed

6 files changed

+190
-11
lines changed

.github/CODEOWNERS

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
* @grafana/platform-monitoring
22

3-
/internal/resources/grafana/*_alerting_* @grafana/platform-monitoring @grafana/alerting-squad
4-
/internal/resources/cloud/* @grafana/platform-monitoring @grafana/grafana-com-maintainers
5-
/internal/resources/cloud/*_access_policy_* @grafana/platform-monitoring @grafana/identity-squad
6-
/internal/resources/cloudprovider/* @grafana/platform-monitoring @grafana/middleware-apps
7-
/internal/resources/connections/* @grafana/platform-monitoring @grafana/middleware-apps
8-
/internal/resources/fleetmanagement/* @grafana/platform-monitoring @grafana/fleet-management-backend
9-
/internal/resources/frontendo11y/* @grafana/platform-monitoring @grafana/frontend-o11y
10-
/internal/resources/machinelearning/* @grafana/platform-monitoring @grafana/machine-learning
11-
/internal/resources/oncall/* @grafana/platform-monitoring @grafana/grafana-irm-backend
12-
/internal/resources/slo/* @grafana/platform-monitoring @grafana/slo-squad
13-
/internal/resources/syntheticmonitoring/* @grafana/platform-monitoring @grafana/synthetic-monitoring
3+
/internal/resources/grafana/*_alerting_* @grafana/platform-monitoring @grafana/alerting-squad
4+
/internal/resources/cloud/* @grafana/platform-monitoring @grafana/grafana-com-maintainers
5+
/internal/resources/cloud/*_access_policy_* @grafana/platform-monitoring @grafana/identity-squad
6+
/internal/resources/grafana/*_organization_user* @grafana/platform-monitoring @grafana/identity-squad
7+
/internal/resources/cloudprovider/* @grafana/platform-monitoring @grafana/middleware-apps
8+
/internal/resources/connections/* @grafana/platform-monitoring @grafana/middleware-apps
9+
/internal/resources/fleetmanagement/* @grafana/platform-monitoring @grafana/fleet-management-backend
10+
/internal/resources/frontendo11y/* @grafana/platform-monitoring @grafana/frontend-o11y
11+
/internal/resources/machinelearning/* @grafana/platform-monitoring @grafana/machine-learning
12+
/internal/resources/oncall/* @grafana/platform-monitoring @grafana/grafana-irm-backend
13+
/internal/resources/slo/* @grafana/platform-monitoring @grafana/slo-squad
14+
/internal/resources/syntheticmonitoring/* @grafana/platform-monitoring @grafana/synthetic-monitoring
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "grafana_organization_user Data Source - terraform-provider-grafana"
4+
subcategory: "Grafana OSS"
5+
description: |-
6+
Official documentation https://grafana.com/docs/grafana/latest/administration/user-management/server-user-management/HTTP API https://grafana.com/docs/grafana/latest/developers/http_api/org/#get-all-users-within-the-current-organization-lookup
7+
---
8+
9+
# grafana_organization_user (Data Source)
10+
11+
* [Official documentation](https://grafana.com/docs/grafana/latest/administration/user-management/server-user-management/)
12+
* [HTTP API](https://grafana.com/docs/grafana/latest/developers/http_api/org/#get-all-users-within-the-current-organization-lookup)
13+
14+
## Example Usage
15+
16+
```terraform
17+
resource "grafana_user" "test" {
18+
19+
name = "Testing Datasource"
20+
login = "test-datasource"
21+
password = "my-password"
22+
}
23+
24+
data "grafana_organization_user" "from_email" {
25+
email = grafana_user.test.email
26+
}
27+
28+
data "grafana_organization_user" "from_login" {
29+
login = grafana_user.test.login
30+
}
31+
```
32+
33+
<!-- schema generated by tfplugindocs -->
34+
## Schema
35+
36+
### Optional
37+
38+
- `email` (String) The email address of the Grafana user. Defaults to ``.
39+
- `login` (String) The username of the Grafana user. Defaults to ``.
40+
- `org_id` (String) The Organization ID. If not set, the Org ID defined in the provider block will be used.
41+
42+
### Read-Only
43+
44+
- `id` (String) The ID of this resource.
45+
- `user_id` (Number) The numerical ID of the Grafana user.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
resource "grafana_user" "test" {
2+
3+
name = "Testing Datasource"
4+
login = "test-datasource"
5+
password = "my-password"
6+
}
7+
8+
data "grafana_organization_user" "from_email" {
9+
email = grafana_user.test.email
10+
}
11+
12+
data "grafana_organization_user" "from_login" {
13+
login = grafana_user.test.login
14+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package grafana
2+
3+
import (
4+
"context"
5+
6+
"github.com/grafana/grafana-openapi-client-go/client/org"
7+
"github.com/grafana/grafana-openapi-client-go/models"
8+
"github.com/grafana/terraform-provider-grafana/v3/internal/common"
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
11+
)
12+
13+
func datasourceOrganizationUser() *common.DataSource {
14+
schema := &schema.Resource{
15+
Description: `
16+
* [Official documentation](https://grafana.com/docs/grafana/latest/administration/user-management/server-user-management/)
17+
* [HTTP API](https://grafana.com/docs/grafana/latest/developers/http_api/org/#get-all-users-within-the-current-organization-lookup)
18+
`,
19+
ReadContext: dataSourceOrganizationUserRead,
20+
Schema: map[string]*schema.Schema{
21+
"org_id": orgIDAttribute(),
22+
"email": {
23+
Type: schema.TypeString,
24+
Optional: true,
25+
Default: "",
26+
Description: "The email address of the Grafana user.",
27+
},
28+
"login": {
29+
Type: schema.TypeString,
30+
Optional: true,
31+
Default: "",
32+
Description: "The username of the Grafana user.",
33+
},
34+
"user_id": {
35+
Type: schema.TypeInt,
36+
Computed: true,
37+
Description: "The numerical ID of the Grafana user.",
38+
},
39+
},
40+
}
41+
return common.NewLegacySDKDataSource(common.CategoryGrafanaOSS, "grafana_organization_user", schema)
42+
}
43+
44+
func dataSourceOrganizationUserRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
45+
client, orgID := OAPIClientFromNewOrgResource(meta, d)
46+
47+
var resp interface {
48+
GetPayload() []*models.UserLookupDTO
49+
}
50+
51+
emailOrLogin := d.Get("email").(string)
52+
if emailOrLogin == "" {
53+
emailOrLogin = d.Get("login").(string)
54+
}
55+
if emailOrLogin == "" {
56+
return diag.Errorf("must specify one of email or login")
57+
}
58+
59+
params := org.NewGetOrgUsersForCurrentOrgLookupParams().WithQuery(&emailOrLogin)
60+
resp, err := client.Org.GetOrgUsersForCurrentOrgLookup(params)
61+
if err != nil {
62+
return diag.FromErr(err)
63+
}
64+
65+
// Make sure that exactly 1 user was returned
66+
if len(resp.GetPayload()) > 1 {
67+
return diag.Errorf("ambiguous query when reading organization user, multiple users returned by query: %q", emailOrLogin)
68+
} else if len(resp.GetPayload()) == 0 {
69+
return diag.Errorf("organization user not found with query: %q", emailOrLogin)
70+
}
71+
72+
user := resp.GetPayload()[0]
73+
d.Set("user_id", user.UserID)
74+
d.Set("login", user.Login)
75+
76+
d.SetId(MakeOrgResourceID(orgID, user.UserID))
77+
return nil
78+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package grafana_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/grafana/grafana-openapi-client-go/models"
7+
"github.com/grafana/terraform-provider-grafana/v3/internal/common"
8+
"github.com/grafana/terraform-provider-grafana/v3/internal/testutils"
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
10+
)
11+
12+
func TestAccDatasourceOrganizationUser_basic(t *testing.T) {
13+
testutils.CheckOSSTestsEnabled(t)
14+
15+
var user models.UserProfileDTO
16+
checks := []resource.TestCheckFunc{
17+
userCheckExists.exists("grafana_user.test", &user),
18+
}
19+
for _, rName := range []string{"from_email", "from_login"} {
20+
checks = append(checks,
21+
resource.TestMatchResourceAttr(
22+
"data.grafana_organization_user."+rName, "user_id", common.IDRegexp,
23+
),
24+
resource.TestCheckResourceAttr(
25+
"data.grafana_organization_user."+rName, "login", "test-datasource",
26+
),
27+
)
28+
}
29+
30+
resource.ParallelTest(t, resource.TestCase{
31+
ProtoV5ProviderFactories: testutils.ProtoV5ProviderFactories,
32+
CheckDestroy: userCheckExists.destroyed(&user, nil),
33+
Steps: []resource.TestStep{
34+
{
35+
Config: testutils.TestAccExample(t, "data-sources/grafana_organization_user/data-source.tf"),
36+
Check: resource.ComposeTestCheckFunc(checks...),
37+
},
38+
},
39+
})
40+
}

internal/resources/grafana/resources.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ var DataSources = addValidationToDataSources(
9494
datasourceLibraryPanels(),
9595
datasourceUser(),
9696
datasourceUsers(),
97+
datasourceOrganizationUser(),
9798
datasourceRole(),
9899
datasourceServiceAccount(),
99100
datasourceTeam(),

0 commit comments

Comments
 (0)