Skip to content

Commit 8e15552

Browse files
Merge pull request #291 from grafana/julienduchesne/data-user
Add new datasource: `grafana_user`
2 parents 7591124 + 6e340a1 commit 8e15552

File tree

9 files changed

+216
-3
lines changed

9 files changed

+216
-3
lines changed

GNUmakefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@ testacc-docker:
1414
docker-compose \
1515
-f ./docker-compose.yml \
1616
run --rm grafana-provider \
17-
make testacc
17+
make testacc TESTARGS="$(TESTARGS)"
1818

1919
testacc-docker-tls:
2020
GRAFANA_VERSION=$(GRAFANA_VERSION) \
2121
docker-compose \
2222
-f ./docker-compose.yml \
2323
-f ./docker-compose.tls.yml \
2424
run --rm grafana-provider \
25-
make testacc
25+
make testacc TESTARGS="$(TESTARGS)"
2626

2727
changelog:
2828
@test $${RELEASE_VERSION?Please set environment variable RELEASE_VERSION}

docs/data-sources/user.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "grafana_user Data Source - terraform-provider-grafana"
4+
subcategory: ""
5+
description: |-
6+
Official documentation https://grafana.com/docs/grafana/latest/manage-users/server-admin/server-admin-manage-users/HTTP API https://grafana.com/docs/grafana/latest/http_api/user/
7+
This resource uses Grafana's admin APIs for creating and updating users which
8+
does not currently work with API Tokens. You must use basic auth.
9+
---
10+
11+
# grafana_user (Data Source)
12+
13+
* [Official documentation](https://grafana.com/docs/grafana/latest/manage-users/server-admin/server-admin-manage-users/)
14+
* [HTTP API](https://grafana.com/docs/grafana/latest/http_api/user/)
15+
16+
This resource uses Grafana's admin APIs for creating and updating users which
17+
does not currently work with API Tokens. You must use basic auth.
18+
19+
## Example Usage
20+
21+
```terraform
22+
resource "grafana_user" "test" {
23+
24+
name = "Testing Datasource"
25+
login = "test-datasource"
26+
password = "my-password"
27+
is_admin = true
28+
}
29+
30+
data "grafana_user" "from_id" {
31+
user_id = grafana_user.test.user_id
32+
}
33+
34+
data "grafana_user" "from_email" {
35+
email = grafana_user.test.email
36+
}
37+
38+
data "grafana_user" "from_login" {
39+
login = grafana_user.test.login
40+
}
41+
```
42+
43+
<!-- schema generated by tfplugindocs -->
44+
## Schema
45+
46+
### Optional
47+
48+
- **email** (String) The email address of the Grafana user. Defaults to ``.
49+
- **id** (String) The ID of this resource.
50+
- **login** (String) The username for the Grafana user. Defaults to ``.
51+
- **user_id** (Number) The numerical ID of the Grafana user. Defaults to `-1`.
52+
53+
### Read-Only
54+
55+
- **is_admin** (Boolean) Whether the user is an admin.
56+
- **name** (String) The display name for the Grafana user.
57+
58+

docs/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ provider "grafana" {
3232
- **ca_cert** (String) Certificate CA bundle to use to verify the Grafana server's certificate. May alternatively be set via the `GRAFANA_CA_CERT` environment variable.
3333
- **insecure_skip_verify** (Boolean) Skip TLS certificate verification. May alternatively be set via the `GRAFANA_INSECURE_SKIP_VERIFY` environment variable.
3434
- **org_id** (Number) The organization id to operate on within grafana. May alternatively be set via the `GRAFANA_ORG_ID` environment variable.
35+
- **retries** (Number) The amount of retries to use for Grafana API calls. May alternatively be set via the `GRAFANA_RETRIES` environment variable.
3536
- **sm_access_token** (String, Sensitive) A Synthetic Monitoring access token. May alternatively be set via the `GRAFANA_SM_ACCESS_TOKEN` environment variable.
3637
- **sm_url** (String) Synthetic monitoring backend address. May alternatively be set via the `GRAFANA_SM_URL` environment variable.
3738
- **tls_cert** (String) Client TLS certificate file to use to authenticate to the Grafana server. May alternatively be set via the `GRAFANA_TLS_CERT` environment variable.

docs/resources/user.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ resource "grafana_user" "staff" {
4343
- **login** (String) The username for the Grafana user.
4444
- **name** (String) The display name for the Grafana user.
4545

46+
### Read-Only
47+
48+
- **user_id** (Number) The numerical ID of the Grafana user.
49+
4650
## Import
4751

4852
Import is supported using the following syntax:
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
resource "grafana_user" "test" {
2+
3+
name = "Testing Datasource"
4+
login = "test-datasource"
5+
password = "my-password"
6+
is_admin = true
7+
}
8+
9+
data "grafana_user" "from_id" {
10+
user_id = grafana_user.test.user_id
11+
}
12+
13+
data "grafana_user" "from_email" {
14+
email = grafana_user.test.email
15+
}
16+
17+
data "grafana_user" "from_login" {
18+
login = grafana_user.test.login
19+
}

grafana/data_source_user.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package grafana
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
gapi "github.com/grafana/grafana-api-golang-client"
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
10+
)
11+
12+
func DatasourceUser() *schema.Resource {
13+
return &schema.Resource{
14+
Description: `
15+
* [Official documentation](https://grafana.com/docs/grafana/latest/manage-users/server-admin/server-admin-manage-users/)
16+
* [HTTP API](https://grafana.com/docs/grafana/latest/http_api/user/)
17+
18+
This resource uses Grafana's admin APIs for creating and updating users which
19+
does not currently work with API Tokens. You must use basic auth.
20+
`,
21+
ReadContext: dataSourceUserRead,
22+
Schema: map[string]*schema.Schema{
23+
"user_id": {
24+
Type: schema.TypeInt,
25+
Optional: true,
26+
Default: -1,
27+
Description: "The numerical ID of the Grafana user.",
28+
},
29+
"email": {
30+
Type: schema.TypeString,
31+
Optional: true,
32+
Default: "",
33+
Description: "The email address of the Grafana user.",
34+
},
35+
"login": {
36+
Type: schema.TypeString,
37+
Optional: true,
38+
Default: "",
39+
Description: "The username for the Grafana user.",
40+
},
41+
"name": {
42+
Type: schema.TypeString,
43+
Computed: true,
44+
Description: "The display name for the Grafana user.",
45+
},
46+
"is_admin": {
47+
Type: schema.TypeBool,
48+
Computed: true,
49+
Description: "Whether the user is an admin.",
50+
},
51+
},
52+
}
53+
}
54+
55+
func dataSourceUserRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
56+
client := meta.(*client).gapi
57+
58+
var user gapi.User
59+
var err error
60+
if id := d.Get("user_id").(int); id >= 0 {
61+
user, err = client.User(int64(id))
62+
} else if email := d.Get("email").(string); email != "" {
63+
user, err = client.UserByEmail(email)
64+
} else if login := d.Get("login").(string); login != "" {
65+
user, err = client.UserByEmail(login)
66+
} else {
67+
err = fmt.Errorf("must specify one of user_id, email, or login")
68+
}
69+
70+
if err != nil {
71+
return diag.FromErr(err)
72+
}
73+
74+
d.SetId(fmt.Sprintf("%d", user.ID))
75+
d.Set("email", user.Email)
76+
d.Set("name", user.Name)
77+
d.Set("login", user.Login)
78+
d.Set("is_admin", user.IsAdmin)
79+
80+
return nil
81+
}

grafana/data_source_user_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package grafana
2+
3+
import (
4+
"testing"
5+
6+
gapi "github.com/grafana/grafana-api-golang-client"
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
8+
)
9+
10+
func TestAccDatasourceUser(t *testing.T) {
11+
var user gapi.User
12+
checks := []resource.TestCheckFunc{
13+
testAccUserCheckExists("grafana_user.test", &user),
14+
}
15+
for _, rName := range []string{"from_email", "from_login", "from_id"} {
16+
checks = append(checks,
17+
resource.TestCheckResourceAttr(
18+
"data.grafana_user."+rName, "email", "[email protected]",
19+
),
20+
resource.TestCheckResourceAttr(
21+
"data.grafana_user."+rName, "name", "Testing Datasource",
22+
),
23+
resource.TestCheckResourceAttr(
24+
"data.grafana_user."+rName, "login", "test-datasource",
25+
),
26+
resource.TestCheckResourceAttr(
27+
"data.grafana_user."+rName, "is_admin", "true",
28+
),
29+
)
30+
}
31+
32+
resource.Test(t, resource.TestCase{
33+
PreCheck: func() { testAccPreCheck(t) },
34+
ProviderFactories: testAccProviderFactories,
35+
CheckDestroy: testAccUserCheckDestroy(&user),
36+
Steps: []resource.TestStep{
37+
{
38+
Config: testAccExample(t, "data-sources/grafana_user/data-source.tf"),
39+
Check: resource.ComposeTestCheckFunc(checks...),
40+
},
41+
},
42+
})
43+
}

grafana/provider.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ func Provider(version string) func() *schema.Provider {
9898
},
9999

100100
ResourcesMap: map[string]*schema.Resource{
101-
102101
// Grafana
103102
"grafana_alert_notification": ResourceAlertNotification(),
104103
"grafana_builtin_role_assignment": ResourceBuiltInRoleAssignment(),
@@ -120,6 +119,8 @@ func Provider(version string) func() *schema.Provider {
120119
},
121120

122121
DataSourcesMap: map[string]*schema.Resource{
122+
// Grafana
123+
"grafana_user": DatasourceUser(),
123124

124125
// Synthetic Monitoring
125126
"grafana_synthetic_monitoring_probe": dataSourceSyntheticMonitoringProbe(),

grafana/resource_user.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ does not currently work with API Tokens. You must use basic auth.
2929
StateContext: schema.ImportStatePassthroughContext,
3030
},
3131
Schema: map[string]*schema.Schema{
32+
"user_id": {
33+
Type: schema.TypeInt,
34+
Computed: true,
35+
Description: "The numerical ID of the Grafana user.",
36+
},
3237
"email": {
3338
Type: schema.TypeString,
3439
Required: true,
@@ -92,6 +97,7 @@ func ReadUser(ctx context.Context, d *schema.ResourceData, meta interface{}) dia
9297
if err != nil {
9398
return diag.FromErr(err)
9499
}
100+
d.Set("user_id", user.ID)
95101
d.Set("email", user.Email)
96102
d.Set("name", user.Name)
97103
d.Set("login", user.Login)

0 commit comments

Comments
 (0)