Skip to content

Commit 335b322

Browse files
authored
Add role data_source (#917)
1 parent 8d5bb42 commit 335b322

File tree

6 files changed

+273
-0
lines changed

6 files changed

+273
-0
lines changed

docs/data-sources/role.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "grafana_role Data Source - terraform-provider-grafana"
4+
subcategory: "Grafana Enterprise"
5+
description: |-
6+
Note: This resource is available only with Grafana Enterprise 8.+.
7+
Official documentation https://grafana.com/docs/grafana/latest/administration/roles-and-permissions/access-control/HTTP API https://grafana.com/docs/grafana/latest/developers/http_api/access_control/
8+
---
9+
10+
# grafana_role (Data Source)
11+
12+
**Note:** This resource is available only with Grafana Enterprise 8.+.
13+
14+
* [Official documentation](https://grafana.com/docs/grafana/latest/administration/roles-and-permissions/access-control/)
15+
* [HTTP API](https://grafana.com/docs/grafana/latest/developers/http_api/access_control/)
16+
17+
## Example Usage
18+
19+
```terraform
20+
resource "grafana_role" "test" {
21+
name = "test-role"
22+
description = "test-role description"
23+
uid = "test-ds-role-uid"
24+
version = 1
25+
global = true
26+
27+
permissions {
28+
action = "org.users:add"
29+
scope = "users:*"
30+
}
31+
permissions {
32+
action = "org.users:write"
33+
scope = "users:*"
34+
}
35+
permissions {
36+
action = "org.users:read"
37+
scope = "users:*"
38+
}
39+
}
40+
41+
data "grafana_role" "from_name" {
42+
name = grafana_role.test.name
43+
}
44+
```
45+
46+
<!-- schema generated by tfplugindocs -->
47+
## Schema
48+
49+
### Required
50+
51+
- `name` (String) Name of the role
52+
53+
### Read-Only
54+
55+
- `description` (String) Description of the role.
56+
- `display_name` (String) Display name of the role. Available with Grafana 8.5+.
57+
- `global` (Boolean) Boolean to state whether the role is available across all organizations or not.
58+
- `group` (String) Group of the role. Available with Grafana 8.5+.
59+
- `hidden` (Boolean) Boolean to state whether the role should be visible in the Grafana UI or not. Available with Grafana 8.5+.
60+
- `id` (String) The ID of this resource.
61+
- `permissions` (Set of Object) Specific set of actions granted by the role. (see [below for nested schema](#nestedatt--permissions))
62+
- `uid` (String) Unique identifier of the role. Used for assignments.
63+
- `version` (Number) Version of the role. A role is updated only on version increase.
64+
65+
<a id="nestedatt--permissions"></a>
66+
### Nested Schema for `permissions`
67+
68+
Read-Only:
69+
70+
- `action` (String)
71+
- `scope` (String)
72+
73+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
resource "grafana_role" "test" {
2+
name = "test-role"
3+
description = "test-role description"
4+
uid = "test-ds-role-uid"
5+
version = 1
6+
global = true
7+
8+
permissions {
9+
action = "org.users:add"
10+
scope = "users:*"
11+
}
12+
permissions {
13+
action = "org.users:write"
14+
scope = "users:*"
15+
}
16+
permissions {
17+
action = "org.users:read"
18+
scope = "users:*"
19+
}
20+
}
21+
22+
data "grafana_role" "from_name" {
23+
name = grafana_role.test.name
24+
}

internal/provider/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ func Provider(version string) func() *schema.Provider {
123123
"grafana_library_panel": grafana.DatasourceLibraryPanel(),
124124
"grafana_user": grafana.DatasourceUser(),
125125
"grafana_users": grafana.DatasourceUsers(),
126+
"grafana_role": grafana.DatasourceRole(),
126127
"grafana_team": grafana.DatasourceTeam(),
127128
"grafana_organization": grafana.DatasourceOrganization(),
128129
"grafana_organization_preferences": grafana.DatasourceOrganizationPreferences(),
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
package grafana
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
gapi "github.com/grafana/grafana-api-golang-client"
8+
"github.com/grafana/terraform-provider-grafana/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 DatasourceRole() *schema.Resource {
14+
return &schema.Resource{
15+
Description: `
16+
**Note:** This resource is available only with Grafana Enterprise 8.+.
17+
18+
* [Official documentation](https://grafana.com/docs/grafana/latest/administration/roles-and-permissions/access-control/)
19+
* [HTTP API](https://grafana.com/docs/grafana/latest/developers/http_api/access_control/)
20+
`,
21+
ReadContext: dataSourceRoleRead,
22+
Schema: map[string]*schema.Schema{
23+
"uid": {
24+
Type: schema.TypeString,
25+
Computed: true,
26+
Description: "Unique identifier of the role. Used for assignments.",
27+
},
28+
"version": {
29+
Type: schema.TypeInt,
30+
Computed: true,
31+
Description: "Version of the role. A role is updated only on version increase.",
32+
},
33+
"name": {
34+
Type: schema.TypeString,
35+
Required: true,
36+
Description: "Name of the role",
37+
},
38+
"description": {
39+
Type: schema.TypeString,
40+
Computed: true,
41+
Description: "Description of the role.",
42+
},
43+
"display_name": {
44+
Type: schema.TypeString,
45+
Computed: true,
46+
Description: "Display name of the role. Available with Grafana 8.5+.",
47+
},
48+
"group": {
49+
Type: schema.TypeString,
50+
Computed: true,
51+
Description: "Group of the role. Available with Grafana 8.5+.",
52+
},
53+
"hidden": {
54+
Type: schema.TypeBool,
55+
Computed: true,
56+
Description: "Boolean to state whether the role should be visible in the Grafana UI or not. Available with Grafana 8.5+.",
57+
},
58+
"global": {
59+
Type: schema.TypeBool,
60+
Computed: true,
61+
Description: "Boolean to state whether the role is available across all organizations or not.",
62+
},
63+
"permissions": {
64+
Type: schema.TypeSet,
65+
Computed: true,
66+
Description: "Specific set of actions granted by the role.",
67+
Elem: &schema.Resource{
68+
Schema: map[string]*schema.Schema{
69+
"action": {
70+
Type: schema.TypeString,
71+
Computed: true,
72+
Description: "Specific action users granted with the role will be allowed to perform (for example: `users:read`)",
73+
},
74+
"scope": {
75+
Type: schema.TypeString,
76+
Computed: true,
77+
Description: "Scope to restrict the action to a set of resources (for example: `users:*` or `roles:customrole1`)",
78+
},
79+
},
80+
},
81+
},
82+
},
83+
}
84+
}
85+
86+
func findRoleWithName(client *gapi.Client, name string) (*gapi.Role, error) {
87+
roles, err := client.GetRoles()
88+
if err != nil {
89+
return nil, err
90+
}
91+
92+
for _, r := range roles {
93+
if r.Name == name {
94+
// Query the role by UID, that API has additional information
95+
return client.GetRole(r.UID)
96+
}
97+
}
98+
99+
return nil, fmt.Errorf("no role with name %q", name)
100+
}
101+
102+
func dataSourceRoleRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
103+
client := meta.(*common.Client).GrafanaAPI
104+
name := d.Get("name").(string)
105+
role, err := findRoleWithName(client, name)
106+
if err != nil {
107+
return diag.FromErr(err)
108+
}
109+
110+
d.SetId(role.UID)
111+
d.Set("uid", role.UID)
112+
d.Set("version", role.Version)
113+
d.Set("name", role.Name)
114+
if role.Description != "" {
115+
d.Set("description", role.Description)
116+
}
117+
if role.DisplayName != "" {
118+
d.Set("displayName", role.DisplayName)
119+
}
120+
if role.Group != "" {
121+
d.Set("group", role.Group)
122+
}
123+
d.Set("hidden", role.Hidden)
124+
d.Set("global", role.Global)
125+
perms := make([]interface{}, 0)
126+
for _, p := range role.Permissions {
127+
pMap := map[string]interface{}{
128+
"action": p.Action,
129+
"scope": p.Scope,
130+
}
131+
perms = append(perms, pMap)
132+
}
133+
err = d.Set("permissions", perms)
134+
if err != nil {
135+
return diag.FromErr(err)
136+
}
137+
138+
return nil
139+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package grafana_test
2+
3+
import (
4+
"testing"
5+
6+
gapi "github.com/grafana/grafana-api-golang-client"
7+
"github.com/grafana/terraform-provider-grafana/internal/testutils"
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
9+
)
10+
11+
func TestAccDatasourceRole(t *testing.T) {
12+
testutils.CheckEnterpriseTestsEnabled(t)
13+
14+
var role gapi.Role
15+
checks := []resource.TestCheckFunc{
16+
testAccRoleCheckExists("grafana_role.test", &role),
17+
resource.TestCheckResourceAttr(
18+
"data.grafana_role.from_name", "name", "test-role",
19+
),
20+
resource.TestCheckResourceAttr(
21+
"data.grafana_role.from_name", "uid", "test-ds-role-uid",
22+
),
23+
}
24+
25+
resource.ParallelTest(t, resource.TestCase{
26+
ProviderFactories: testutils.ProviderFactories,
27+
CheckDestroy: testAccRoleCheckDestroy(&role),
28+
Steps: []resource.TestStep{
29+
{
30+
Config: testutils.TestAccExample(t, "data-sources/grafana_role/data-source.tf"),
31+
Check: resource.ComposeTestCheckFunc(checks...),
32+
},
33+
},
34+
})
35+
}

tools/subcategories.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
"data-sources/library_panel": "Grafana OSS",
6363
"data-sources/organization": "Grafana OSS",
6464
"data-sources/organization_preferences": "Grafana OSS",
65+
"data-sources/role": "Grafana Enterprise",
6566
"data-sources/team": "Grafana OSS",
6667
"data-sources/user": "Grafana OSS",
6768
"data-sources/users": "Grafana OSS",

0 commit comments

Comments
 (0)