Skip to content

Commit d5aed61

Browse files
Data sources: Add Admin permission to data source permission options (#1133)
* bring data source permissions up to date with Golang API client changes and add Admin permission * bump golang API version * test fix
1 parent 9b479bf commit d5aed61

File tree

4 files changed

+90
-66
lines changed

4 files changed

+90
-66
lines changed

docs/resources/data_source_permission.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ resource "grafana_data_source_permission" "fooPermissions" {
4848
datasource_id = grafana_data_source.foo.id
4949
permissions {
5050
team_id = grafana_team.team.id
51-
permission = "Query"
51+
permission = "Admin"
5252
}
5353
permissions {
5454
user_id = grafana_user.user.id
@@ -86,7 +86,7 @@ resource "grafana_data_source_permission" "fooPermissions" {
8686

8787
Required:
8888

89-
- `permission` (String) Permission to associate with item. Options: `Query` or `Edit` (`Edit` can only be used with Grafana v9.2.3+).
89+
- `permission` (String) Permission to associate with item. Options: `Query`, `Edit` or `Admin` (`Admin` can only be used with Grafana v10.3.0+).
9090

9191
Optional:
9292

examples/resources/grafana_data_source_permission/resource.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ resource "grafana_data_source_permission" "fooPermissions" {
3333
datasource_id = grafana_data_source.foo.id
3434
permissions {
3535
team_id = grafana_team.team.id
36-
permission = "Query"
36+
permission = "Admin"
3737
}
3838
permissions {
3939
user_id = grafana_user.user.id

internal/resources/grafana/resource_data_source_permission.go

Lines changed: 60 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package grafana
22

33
import (
44
"context"
5-
"fmt"
65
"strconv"
76

87
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
@@ -68,8 +67,8 @@ func ResourceDatasourcePermission() *schema.Resource {
6867
"permission": {
6968
Type: schema.TypeString,
7069
Required: true,
71-
ValidateFunc: validation.StringInSlice([]string{"Query", "Edit"}, false),
72-
Description: "Permission to associate with item. Options: `Query` or `Edit` (`Edit` can only be used with Grafana v9.2.3+).",
70+
ValidateFunc: validation.StringInSlice([]string{"Query", "Edit", "Admin"}, false),
71+
Description: "Permission to associate with item. Options: `Query`, `Edit` or `Admin` (`Admin` can only be used with Grafana v10.3.0+).",
7372
},
7473
},
7574
},
@@ -89,10 +88,15 @@ func UpdateDatasourcePermissions(ctx context.Context, d *schema.ResourceData, me
8988
_, datasourceIDStr := SplitOrgResourceID(d.Get("datasource_id").(string))
9089
datasourceID, _ := strconv.ParseInt(datasourceIDStr, 10, 64)
9190

92-
configuredPermissions := []*gapi.DatasourcePermissionAddPayload{}
91+
dataSource, err := client.DataSource(datasourceID)
92+
if err != nil {
93+
return diag.FromErr(err)
94+
}
95+
96+
var configuredPermissions []gapi.SetResourcePermissionItem
9397
for _, permission := range v.(*schema.Set).List() {
9498
permission := permission.(map[string]interface{})
95-
permissionItem := gapi.DatasourcePermissionAddPayload{}
99+
var permissionItem gapi.SetResourcePermissionItem
96100
_, teamIDStr := SplitOrgResourceID(permission["team_id"].(string))
97101
teamID, _ := strconv.ParseInt(teamIDStr, 10, 64)
98102
if teamID > 0 {
@@ -104,16 +108,13 @@ func UpdateDatasourcePermissions(ctx context.Context, d *schema.ResourceData, me
104108
permissionItem.UserID = userID
105109
}
106110
if permission["built_in_role"].(string) != "" {
107-
permissionItem.BuiltInRole = permission["built_in_role"].(string)
111+
permissionItem.BuiltinRole = permission["built_in_role"].(string)
108112
}
109-
var err error
110-
if permissionItem.Permission, err = mapDatasourcePermissionStringToType(permission["permission"].(string)); err != nil {
111-
return diag.FromErr(err)
112-
}
113-
configuredPermissions = append(configuredPermissions, &permissionItem)
113+
permissionItem.Permission = permission["permission"].(string)
114+
configuredPermissions = append(configuredPermissions, permissionItem)
114115
}
115116

116-
if err := updateDatasourcePermissions(client, datasourceID, configuredPermissions, true, false); err != nil {
117+
if err := updateDatasourcePermissions(client, dataSource.UID, configuredPermissions); err != nil {
117118
return diag.FromErr(err)
118119
}
119120

@@ -130,23 +131,29 @@ func ReadDatasourcePermissions(ctx context.Context, d *schema.ResourceData, meta
130131
return diag.FromErr(err)
131132
}
132133

133-
response, err := client.DatasourcePermissions(id)
134+
dataSource, err := client.DataSource(id)
135+
if err != nil {
136+
return diag.FromErr(err)
137+
}
138+
139+
response, err := client.ListDatasourceResourcePermissions(dataSource.UID)
134140
if err, shouldReturn := common.CheckReadError("datasource permissions", d, err); shouldReturn {
135141
return err
136142
}
137143

138-
permissionItems := make([]interface{}, len(response.Permissions))
139-
for i, permission := range response.Permissions {
144+
var permissionItems []interface{}
145+
for _, permission := range response {
146+
// Only managed permissions can be provisioned through this resource, so we disregard the permissions obtained through custom and fixed roles here
147+
if !permission.IsManaged {
148+
continue
149+
}
140150
permissionItem := make(map[string]interface{})
141151
permissionItem["built_in_role"] = permission.BuiltInRole
142152
permissionItem["team_id"] = strconv.FormatInt(permission.TeamID, 10)
143153
permissionItem["user_id"] = strconv.FormatInt(permission.UserID, 10)
154+
permissionItem["permission"] = permission.Permission
144155

145-
if permissionItem["permission"], err = mapDatasourcePermissionTypeToString(permission.Permission); err != nil {
146-
return diag.FromErr(err)
147-
}
148-
149-
permissionItems[i] = permissionItem
156+
permissionItems = append(permissionItems, permissionItem)
150157
}
151158

152159
d.Set("permissions", permissionItems)
@@ -161,80 +168,70 @@ func DeleteDatasourcePermissions(ctx context.Context, d *schema.ResourceData, me
161168
if err != nil {
162169
return diag.FromErr(err)
163170
}
164-
err = updateDatasourcePermissions(client, id, []*gapi.DatasourcePermissionAddPayload{}, false, true)
171+
172+
dataSource, err := client.DataSource(id)
173+
if err != nil {
174+
return diag.FromErr(err)
175+
}
176+
177+
err = updateDatasourcePermissions(client, dataSource.UID, []gapi.SetResourcePermissionItem{})
165178
diags, _ := common.CheckReadError("datasource permissions", d, err)
166179
return diags
167180
}
168181

169-
func updateDatasourcePermissions(client *gapi.Client, id int64, permissions []*gapi.DatasourcePermissionAddPayload, enable, disable bool) error {
170-
areEqual := func(a *gapi.DatasourcePermission, b *gapi.DatasourcePermissionAddPayload) bool {
171-
return a.Permission == b.Permission && a.TeamID == b.TeamID && a.UserID == b.UserID && a.BuiltInRole == b.BuiltInRole
182+
func updateDatasourcePermissions(client *gapi.Client, uid string, permissions []gapi.SetResourcePermissionItem) error {
183+
areEqual := func(a *gapi.ResourcePermission, b gapi.SetResourcePermissionItem) bool {
184+
return a.Permission == b.Permission && a.TeamID == b.TeamID && a.UserID == b.UserID && a.BuiltInRole == b.BuiltinRole
172185
}
173186

174-
response, err := client.DatasourcePermissions(id)
187+
response, err := client.ListDatasourceResourcePermissions(uid)
175188
if err != nil {
176189
return err
177190
}
178191

179-
if !response.Enabled && enable {
180-
if err := client.EnableDatasourcePermissions(id); err != nil {
181-
return err
182-
}
183-
}
192+
var permissionList []gapi.SetResourcePermissionItem
184193

185194
deleteLoop:
186-
for _, current := range response.Permissions {
195+
for _, current := range response {
196+
// Only managed permissions can be provisioned through this resource, so we disregard the permissions obtained through custom and fixed roles here
197+
if !current.IsManaged {
198+
continue
199+
}
187200
for _, new := range permissions {
188201
if areEqual(current, new) {
189202
continue deleteLoop
190203
}
191204
}
192205

193-
err := client.RemoveDatasourcePermission(id, current.ID)
194-
if err != nil {
195-
return err
206+
permToRemove := gapi.SetResourcePermissionItem{
207+
TeamID: current.TeamID,
208+
UserID: current.UserID,
209+
BuiltinRole: current.BuiltInRole,
210+
Permission: "",
196211
}
212+
213+
permissionList = append(permissionList, permToRemove)
197214
}
198215

199216
addLoop:
200217
for _, new := range permissions {
201-
for _, current := range response.Permissions {
218+
for _, current := range response {
202219
if areEqual(current, new) {
203220
continue addLoop
204221
}
205222
}
206223

207-
err := client.AddDatasourcePermission(id, new)
208-
if err != nil {
209-
return err
224+
permToAdd := gapi.SetResourcePermissionItem{
225+
TeamID: new.TeamID,
226+
UserID: new.UserID,
227+
BuiltinRole: new.BuiltinRole,
228+
Permission: new.Permission,
210229
}
211-
}
212230

213-
if response.Enabled && disable {
214-
if err := client.DisableDatasourcePermissions(id); err != nil {
215-
return err
216-
}
231+
permissionList = append(permissionList, permToAdd)
217232
}
218233

219-
return nil
220-
}
234+
_, err = client.SetDatasourceResourcePermissions(uid, gapi.SetResourcePermissionsBody{Permissions: permissionList})
221235

222-
func mapDatasourcePermissionStringToType(permission string) (gapi.DatasourcePermissionType, error) {
223-
switch permission {
224-
case "Query":
225-
return gapi.DatasourcePermissionQuery, nil
226-
case "Edit":
227-
return gapi.DatasourcePermissionEdit, nil
228-
}
229-
return 0, fmt.Errorf("unknown datasource permission: %s", permission)
230-
}
231-
232-
func mapDatasourcePermissionTypeToString(permission gapi.DatasourcePermissionType) (string, error) {
233-
switch permission {
234-
case gapi.DatasourcePermissionQuery:
235-
return "Query", nil
236-
case gapi.DatasourcePermissionEdit:
237-
return "Edit", nil
238-
}
239-
return "", fmt.Errorf("unknown permission type: %d", permission)
236+
return err
240237
}

internal/resources/grafana/resource_data_source_permission_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package grafana_test
33
import (
44
"fmt"
55
"strconv"
6+
"strings"
67
"testing"
78

89
"github.com/grafana/terraform-provider-grafana/internal/common"
@@ -15,6 +16,32 @@ import (
1516
func TestAccDatasourcePermission_basic(t *testing.T) {
1617
testutils.CheckEnterpriseTestsEnabled(t)
1718

19+
datasourceID := int64(-1)
20+
// Admin role can only be set from Grafana 10.3.0 onwards
21+
config := testutils.TestAccExample(t, "resources/grafana_data_source_permission/resource.tf")
22+
config = strings.Replace(config, "Admin", "Edit", 1)
23+
24+
resource.ParallelTest(t, resource.TestCase{
25+
ProviderFactories: testutils.ProviderFactories,
26+
Steps: []resource.TestStep{
27+
{
28+
Config: config,
29+
Check: resource.ComposeAggregateTestCheckFunc(
30+
testAccDatasourcePermissionsCheckExists("grafana_data_source_permission.fooPermissions", &datasourceID),
31+
resource.TestCheckResourceAttr("grafana_data_source_permission.fooPermissions", "permissions.#", "4"),
32+
),
33+
},
34+
{
35+
Config: testutils.TestAccExample(t, "resources/grafana_data_source_permission/_acc_resource_remove.tf"),
36+
Check: testAccDatasourcePermissionCheckDestroy(&datasourceID),
37+
},
38+
},
39+
})
40+
}
41+
42+
func TestAccDatasourcePermission_AdminRole(t *testing.T) {
43+
testutils.CheckEnterpriseTestsEnabled(t, ">=10.3.0")
44+
1845
datasourceID := int64(-1)
1946

2047
resource.ParallelTest(t, resource.TestCase{

0 commit comments

Comments
 (0)