Skip to content

Commit 944cf38

Browse files
Merge pull request grafana#128 from jonathan-dorsey/master
Adding folder permission functionality
2 parents 7d16492 + dd1c433 commit 944cf38

File tree

12 files changed

+813
-1
lines changed

12 files changed

+813
-1
lines changed

grafana/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ func Provider() terraform.ResourceProvider {
3131
"grafana_dashboard": ResourceDashboard(),
3232
"grafana_data_source": ResourceDataSource(),
3333
"grafana_folder": ResourceFolder(),
34+
"grafana_folder_permission": ResourceFolderPermission(),
3435
"grafana_organization": ResourceOrganization(),
3536
"grafana_team": ResourceTeam(),
3637
"grafana_user": ResourceUser(),

grafana/resource_folder.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"log"
77
"strconv"
8+
"strings"
89

910
"github.com/hashicorp/terraform/helper/schema"
1011

@@ -60,7 +61,7 @@ func ReadFolder(d *schema.ResourceData, meta interface{}) error {
6061

6162
folder, err := client.Folder(id)
6263
if err != nil {
63-
if err.Error() == "404 Not Found" {
64+
if strings.HasPrefix(err.Error(), "status: 404") {
6465
log.Printf("[WARN] removing folder %d from state because it no longer exists in grafana", id)
6566
d.SetId("")
6667
return nil
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
package grafana
2+
3+
import (
4+
"log"
5+
"strings"
6+
7+
"github.com/hashicorp/terraform/helper/schema"
8+
"github.com/hashicorp/terraform/helper/validation"
9+
10+
gapi "github.com/grafana/grafana-api-golang-client"
11+
)
12+
13+
func ResourceFolderPermission() *schema.Resource {
14+
return &schema.Resource{
15+
Create: UpdateFolderPermissions,
16+
Read: ReadFolderPermissions,
17+
Update: UpdateFolderPermissions,
18+
Delete: DeleteFolderPermissions,
19+
20+
Schema: map[string]*schema.Schema{
21+
"folder_uid": {
22+
Type: schema.TypeString,
23+
Required: true,
24+
ForceNew: true,
25+
},
26+
"permissions": {
27+
Type: schema.TypeSet,
28+
Required: true,
29+
Elem: &schema.Resource{
30+
Schema: map[string]*schema.Schema{
31+
"role": {
32+
Type: schema.TypeString,
33+
Optional: true,
34+
ValidateFunc: validation.StringInSlice([]string{"Viewer", "Editor"}, false),
35+
},
36+
"team_id": {
37+
Type: schema.TypeInt,
38+
Optional: true,
39+
Default: -1,
40+
},
41+
"user_id": {
42+
Type: schema.TypeInt,
43+
Optional: true,
44+
Default: -1,
45+
},
46+
"permission": {
47+
Type: schema.TypeString,
48+
Required: true,
49+
ValidateFunc: validation.StringInSlice([]string{"View", "Edit", "Admin"}, false),
50+
},
51+
},
52+
},
53+
},
54+
},
55+
}
56+
}
57+
58+
func UpdateFolderPermissions(d *schema.ResourceData, meta interface{}) error {
59+
client := meta.(*gapi.Client)
60+
61+
v, ok := d.GetOk("permissions")
62+
if !ok {
63+
return nil
64+
}
65+
permissionList := gapi.PermissionItems{}
66+
for _, permission := range v.(*schema.Set).List() {
67+
permission := permission.(map[string]interface{})
68+
permissionItem := gapi.PermissionItem{}
69+
if permission["role"].(string) != "" {
70+
permissionItem.Role = permission["role"].(string)
71+
}
72+
if permission["team_id"].(int) != -1 {
73+
permissionItem.TeamId = int64(permission["team_id"].(int))
74+
}
75+
if permission["user_id"].(int) != -1 {
76+
permissionItem.UserId = int64(permission["user_id"].(int))
77+
}
78+
permissionItem.Permission = mapPermissionStringToInt64(permission["permission"].(string))
79+
permissionList.Items = append(permissionList.Items, &permissionItem)
80+
}
81+
82+
folderUID := d.Get("folder_uid").(string)
83+
84+
err := client.UpdateFolderPermissions(folderUID, &permissionList)
85+
if err != nil {
86+
return err
87+
}
88+
89+
d.SetId(folderUID)
90+
91+
return ReadFolderPermissions(d, meta)
92+
}
93+
94+
func ReadFolderPermissions(d *schema.ResourceData, meta interface{}) error {
95+
client := meta.(*gapi.Client)
96+
97+
folderUID := d.Get("folder_uid").(string)
98+
99+
folderPermissions, err := client.FolderPermissions(folderUID)
100+
if err != nil {
101+
if strings.HasPrefix(err.Error(), "status: 404") {
102+
log.Printf("[WARN] removing folder %s from state because it no longer exists in grafana", folderUID)
103+
d.SetId("")
104+
return nil
105+
}
106+
107+
return err
108+
}
109+
110+
permissionItems := make([]interface{}, len(folderPermissions))
111+
count := 0
112+
for _, permission := range folderPermissions {
113+
if permission.FolderUid != "" {
114+
permissionItem := make(map[string]interface{})
115+
permissionItem["role"] = permission.Role
116+
permissionItem["team_id"] = permission.TeamId
117+
permissionItem["user_id"] = permission.UserId
118+
permissionItem["permission"] = mapPermissionInt64ToString(permission.Permission)
119+
120+
permissionItems[count] = permission
121+
count++
122+
}
123+
}
124+
125+
d.Set("permissions", permissionItems)
126+
127+
return nil
128+
}
129+
130+
func DeleteFolderPermissions(d *schema.ResourceData, meta interface{}) error {
131+
//since permissions are tied to folders, we can't really delete the permissions.
132+
//we will simply remove all permissions, leaving a folder that only an admin can access.
133+
//if for some reason the parent folder doesn't exist, we'll just ignore the error
134+
client := meta.(*gapi.Client)
135+
136+
folderUID := d.Get("folder_uid").(string)
137+
emptyPermissions := gapi.PermissionItems{}
138+
139+
err := client.UpdateFolderPermissions(folderUID, &emptyPermissions)
140+
if err != nil {
141+
if strings.HasPrefix(err.Error(), "status: 404") {
142+
d.SetId("")
143+
return nil
144+
}
145+
return err
146+
}
147+
148+
return nil
149+
}
150+
151+
func mapPermissionStringToInt64(permission string) int64 {
152+
permissionInt := int64(-1)
153+
switch permission {
154+
case "View":
155+
permissionInt = int64(1)
156+
case "Edit":
157+
permissionInt = int64(2)
158+
case "Admin":
159+
permissionInt = int64(4)
160+
}
161+
return permissionInt
162+
}
163+
164+
func mapPermissionInt64ToString(permission int64) string {
165+
permissionString := "-1"
166+
switch permission {
167+
case 1:
168+
permissionString = "View"
169+
case 2:
170+
permissionString = "Edit"
171+
case 4:
172+
permissionString = "Admin"
173+
}
174+
return permissionString
175+
}
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
package grafana
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
gapi "github.com/grafana/grafana-api-golang-client"
8+
9+
"github.com/hashicorp/terraform/helper/resource"
10+
"github.com/hashicorp/terraform/terraform"
11+
)
12+
13+
func TestAccFolderPermission_basic(t *testing.T) {
14+
folderUID := "uninitialized"
15+
16+
resource.Test(t, resource.TestCase{
17+
PreCheck: func() { testAccPreCheck(t) },
18+
Providers: testAccProviders,
19+
CheckDestroy: testAccFolderPermissionCheckDestroy(),
20+
Steps: []resource.TestStep{
21+
{
22+
Config: testAccFolderPermissionConfig_Basic,
23+
Check: resource.ComposeAggregateTestCheckFunc(
24+
testAccFolderPermissionsCheckExists("grafana_folder_permission.testPermission", &folderUID),
25+
resource.TestCheckResourceAttr("grafana_folder_permission.testPermission", "permissions.#", "4"),
26+
),
27+
},
28+
{
29+
Config: testAccFolderPermissionConfig_Remove,
30+
Check: resource.ComposeAggregateTestCheckFunc(
31+
testAccFolderPermissionsCheckEmpty(&folderUID),
32+
),
33+
},
34+
},
35+
})
36+
}
37+
38+
func testAccFolderPermissionsCheckExists(rn string, folderUID *string) resource.TestCheckFunc {
39+
return func(s *terraform.State) error {
40+
rs, ok := s.RootModule().Resources[rn]
41+
if !ok {
42+
return fmt.Errorf("Resource not found: %s\n %#v", rn, s.RootModule().Resources)
43+
}
44+
45+
if rs.Primary.ID == "" {
46+
return fmt.Errorf("Resource id not set")
47+
}
48+
49+
client := testAccProvider.Meta().(*gapi.Client)
50+
51+
gotFolderUID := rs.Primary.ID
52+
_, err := client.FolderPermissions(gotFolderUID)
53+
if err != nil {
54+
return fmt.Errorf("Error getting folder permissions: %s", err)
55+
}
56+
57+
*folderUID = gotFolderUID
58+
59+
return nil
60+
}
61+
}
62+
63+
func testAccFolderPermissionsCheckEmpty(folderUID *string) resource.TestCheckFunc {
64+
return func(s *terraform.State) error {
65+
client := testAccProvider.Meta().(*gapi.Client)
66+
permissions, err := client.FolderPermissions(*folderUID)
67+
if err != nil {
68+
return fmt.Errorf("Error getting folder permissions %s: %s", *folderUID, err)
69+
}
70+
if len(permissions) > 0 {
71+
return fmt.Errorf("Permissions were not empty when expected")
72+
}
73+
74+
return nil
75+
}
76+
}
77+
78+
func testAccFolderPermissionCheckDestroy() resource.TestCheckFunc {
79+
return func(s *terraform.State) error {
80+
//you can't really destroy folder permissions so nothing to check for
81+
return nil
82+
}
83+
}
84+
85+
func testAccFolderPermissionsRemoval(permissions *gapi.FolderPermission) resource.TestCheckFunc {
86+
return func(s *terraform.State) error {
87+
//since the permissions aren't deleted, let's just check if we have empty permissions
88+
client := testAccProvider.Meta().(*gapi.Client)
89+
newPermissions, err := client.FolderPermissions(permissions.FolderUid)
90+
if err != nil {
91+
return fmt.Errorf(err.Error())
92+
}
93+
if len(newPermissions) > 0 {
94+
return fmt.Errorf("Permissions still exist for folder")
95+
}
96+
return nil
97+
}
98+
}
99+
100+
const testAccFolderPermissionConfig_Basic = `
101+
resource "grafana_folder" "testFolder" {
102+
title = "terraform-test-folder-permissions"
103+
}
104+
105+
resource "grafana_team" "testTeam" {
106+
name = "terraform-test-team-permissions"
107+
}
108+
109+
resource "grafana_user" "testAdminUser" {
110+
email = "terraform-test-permissions@localhost"
111+
name = "Terraform Test Permissions"
112+
login = "ttp"
113+
password = "zyx987"
114+
}
115+
116+
resource "grafana_folder_permission" "testPermission" {
117+
folder_uid = grafana_folder.testFolder.uid
118+
permissions {
119+
role = "Viewer"
120+
permission = "View"
121+
}
122+
permissions {
123+
role = "Editor"
124+
permission = "Edit"
125+
}
126+
permissions {
127+
team_id = grafana_team.testTeam.id
128+
permission = "View"
129+
}
130+
permissions {
131+
user_id = grafana_user.testAdminUser.id
132+
permission = "Admin"
133+
}
134+
}
135+
`
136+
const testAccFolderPermissionConfig_Remove = `
137+
resource "grafana_folder" "testFolder" {
138+
title = "terraform-test-folder-permissions"
139+
}
140+
141+
resource "grafana_team" "testTeam" {
142+
name = "terraform-test-team-permissions"
143+
}
144+
145+
resource "grafana_user" "testAdminUser" {
146+
email = "terraform-test-permissions@localhost"
147+
name = "Terraform Test Permissions"
148+
login = "ttp"
149+
password = "zyx987"
150+
}
151+
`

vendor/github.com/hashicorp/terraform/helper/structure/expand_json.go

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/hashicorp/terraform/helper/structure/flatten_json.go

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)