Skip to content

Commit 3c45df6

Browse files
authored
Merge pull request #340 from SumoLogic/sumo.170432.permission.api.resource
2 parents 7d76c91 + 0c669fa commit 3c45df6

8 files changed

+688
-19
lines changed

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
## 2.12.1 (Unreleased)
1+
## 2.13.0 (Unreleased)
2+
3+
FEATURES:
4+
* **New Resource:** sumologic_content_permission (GH-340)
25

36
ENHANCEMENTS:
47
* Add support for importing folder resource (GH-345)

sumologic/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ func Provider() terraform.ResourceProvider {
9696
"sumologic_token": resourceSumologicToken(),
9797
"sumologic_policies": resourceSumologicPolicies(),
9898
"sumologic_hierarchy": resourceSumologicHierarchy(),
99+
"sumologic_content_permission": resourceSumologicPermissions(),
99100
},
100101
DataSourcesMap: map[string]*schema.Resource{
101102
"sumologic_cse_log_mapping_vendor_product": dataSourceCSELogMappingVendorAndProduct(),

sumologic/resource_sumologic_dashboard_test.go

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,10 @@ func TestAccSumologicDashboard_basic(t *testing.T) {
2424
testNameSuffix := acctest.RandString(16)
2525
title := "terraform_test_dashboard_" + testNameSuffix
2626

27-
var dashboard Dashboard
2827
resource.Test(t, resource.TestCase{
2928
PreCheck: func() { testAccPreCheck(t) },
3029
Providers: testAccProviders,
31-
CheckDestroy: testAccCheckDashboardDestroy(dashboard),
30+
CheckDestroy: testAccCheckDashboardDestroy(),
3231
Steps: []resource.TestStep{
3332
{
3433
Config: dashboardImportConfig(title),
@@ -81,7 +80,7 @@ func TestAccSumologicDashboard_create(t *testing.T) {
8180
resource.Test(t, resource.TestCase{
8281
PreCheck: func() { testAccPreCheck(t) },
8382
Providers: testAccProviders,
84-
CheckDestroy: testAccCheckDashboardDestroy(dashboard),
83+
CheckDestroy: testAccCheckDashboardDestroy(),
8584
Steps: []resource.TestStep{
8685
{
8786
Config: dashboardCreateConfig(title, description, theme, refreshInterval,
@@ -211,7 +210,7 @@ func TestAccSumologicDashboard_update(t *testing.T) {
211210
resource.Test(t, resource.TestCase{
212211
PreCheck: func() { testAccPreCheck(t) },
213212
Providers: testAccProviders,
214-
CheckDestroy: testAccCheckDashboardDestroy(dashboard),
213+
CheckDestroy: testAccCheckDashboardDestroy(),
215214
Steps: []resource.TestStep{
216215
{
217216
Config: dashboardCreateConfig(title, description, theme, refreshInterval,
@@ -301,12 +300,22 @@ func TestAccSumologicDashboard_update(t *testing.T) {
301300
})
302301
}
303302

304-
func testAccCheckDashboardDestroy(dashboard Dashboard) resource.TestCheckFunc {
303+
func testAccCheckDashboardDestroy() resource.TestCheckFunc {
305304
return func(s *terraform.State) error {
306305
client := testAccProvider.Meta().(*Client)
307-
_, err := client.GetDashboard(dashboard.ID)
308-
if err == nil {
309-
return fmt.Errorf("Dashboard (id=%s) still exists", dashboard.ID)
306+
for _, r := range s.RootModule().Resources {
307+
if r.Type != "sumologic_dashboard" {
308+
continue
309+
}
310+
311+
id := r.Primary.ID
312+
dashboard, err := client.GetDashboard(id)
313+
if err != nil {
314+
return fmt.Errorf("Encountered an error: " + err.Error())
315+
}
316+
if dashboard != nil {
317+
return fmt.Errorf("Dashboard (id=%s) still exists", id)
318+
}
310319
}
311320
return nil
312321
}
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
package sumologic
2+
3+
import (
4+
"errors"
5+
"log"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
8+
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
9+
)
10+
11+
func resourceSumologicPermissions() *schema.Resource {
12+
return &schema.Resource{
13+
Create: resourceSumologicPermissionsCreate,
14+
Read: resourceSumologicPermissionsRead,
15+
Delete: resourceSumologicPermissionsDelete,
16+
Update: resourceSumologicPermissionsUpdate,
17+
Importer: &schema.ResourceImporter{
18+
State: schema.ImportStatePassthrough,
19+
},
20+
21+
Schema: map[string]*schema.Schema{
22+
"content_id": {
23+
Type: schema.TypeString,
24+
Required: true,
25+
},
26+
"notify_recipient": {
27+
Type: schema.TypeBool,
28+
Required: true,
29+
},
30+
"notification_message": {
31+
Type: schema.TypeString,
32+
Optional: true,
33+
Default: "",
34+
},
35+
"permission": {
36+
Type: schema.TypeSet,
37+
Required: true,
38+
Elem: &schema.Resource{
39+
Schema: map[string]*schema.Schema{
40+
"permission_name": {
41+
Type: schema.TypeString,
42+
Required: true,
43+
ValidateFunc: validation.StringInSlice(
44+
[]string{"View", "GrantView", "Edit", "GrantEdit", "Manage", "GrantManage"}, false),
45+
},
46+
"source_type": {
47+
Type: schema.TypeString,
48+
Required: true,
49+
ValidateFunc: validation.StringInSlice([]string{"user", "role", "org"}, false),
50+
},
51+
"source_id": {
52+
Type: schema.TypeString,
53+
Required: true,
54+
},
55+
},
56+
},
57+
},
58+
},
59+
}
60+
}
61+
62+
func resourceSumologicPermissionsCreate(d *schema.ResourceData, meta interface{}) error {
63+
c := meta.(*Client)
64+
65+
if d.Id() == "" {
66+
id, err := c.UpdatePermissions(PermissionsRequest{
67+
Permissions: resourceToPermissionsArray(d.Get("permission").(*schema.Set),
68+
d.Get("content_id").(string)),
69+
NotifyRecipients: d.Get("notify_recipient").(bool),
70+
NotificationMessage: d.Get("notification_message").(string),
71+
}, d.Get("content_id").(string))
72+
73+
if err != nil {
74+
return err
75+
}
76+
d.SetId(id)
77+
}
78+
79+
return resourceSumologicPermissionsRead(d, meta)
80+
}
81+
82+
func resourceSumologicPermissionsRead(d *schema.ResourceData, meta interface{}) error {
83+
c := meta.(*Client)
84+
85+
var permissionsResponse *PermissionsResponse
86+
id := d.Id()
87+
88+
permissionsResponse, err := c.GetPermissions(id)
89+
if err != nil {
90+
log.Printf("[WARN] Error getting permissions for content(id=%s), err: %v", id, err)
91+
return err
92+
}
93+
94+
if permissionsResponse == nil {
95+
log.Printf("[WARN] Permissions not found for content(id=%s), removing from state. err: %v",
96+
id, err)
97+
d.SetId("")
98+
return nil
99+
}
100+
101+
creatorId, err := getCreatorId(id, meta)
102+
if err != nil {
103+
log.Printf("[ERROR] Cannot find owner of content %s", id)
104+
return err
105+
}
106+
107+
d.Set("permission",
108+
permissionsArrayToResource(permissionsResponse.ExplicitPermissions, creatorId))
109+
log.Printf("[WARN] Content id %v", d.Get("content_id"))
110+
111+
return nil
112+
}
113+
114+
func resourceSumologicPermissionsDelete(d *schema.ResourceData, meta interface{}) error {
115+
resourceSumologicPermissionsRead(d, meta)
116+
c := meta.(*Client)
117+
permissionRequest, err := resourceToPermissionRequest(d)
118+
if err != nil {
119+
return err
120+
}
121+
return c.DeletePermissions(permissionRequest, d.Get("content_id").(string))
122+
}
123+
124+
func resourceSumologicPermissionsUpdate(d *schema.ResourceData, meta interface{}) error {
125+
c := meta.(*Client)
126+
permissionRequest, err := resourceToPermissionRequest(d)
127+
if err != nil {
128+
return err
129+
}
130+
resourceSumologicPermissionsDelete(d, meta)
131+
if _, err = c.UpdatePermissions(permissionRequest, d.Id()); err != nil {
132+
return err
133+
}
134+
return resourceSumologicPermissionsRead(d, meta)
135+
}
136+
137+
func getCreatorId(contentId string, meta interface{}) (string, error) {
138+
c := meta.(*Client)
139+
path, err := c.GetContentPath(contentId)
140+
if err != nil {
141+
log.Printf("[ERROR] Cannot get path for content %s - %v", contentId, err)
142+
return "", err
143+
}
144+
145+
creatorId, err := c.GetCreatorId(path)
146+
if err != nil {
147+
log.Printf("[ERROR] Cannot find owner of content %s - %v", contentId, err)
148+
return "", err
149+
}
150+
log.Printf("[DEBUG] content=%s, path='%s', owner=%s", contentId, path, creatorId)
151+
return creatorId, nil
152+
}
153+
154+
func resourceToPermissionsArray(resourcePermissions *schema.Set, contentId string) []Permission {
155+
result := make([]Permission, resourcePermissions.Len())
156+
157+
for i, resourcePermission := range resourcePermissions.List() {
158+
PermissionMap := resourcePermission.(map[string]interface{})
159+
result[i] = Permission{
160+
PermissionName: PermissionMap["permission_name"].(string),
161+
SourceType: PermissionMap["source_type"].(string),
162+
SourceId: PermissionMap["source_id"].(string),
163+
ContentId: contentId,
164+
}
165+
}
166+
167+
return result
168+
}
169+
170+
func permissionsArrayToResource(permissions []Permission, creatorId string) []map[string]interface{} {
171+
172+
result := make([]map[string]interface{}, 0)
173+
174+
for _, permission := range permissions {
175+
if permission.SourceType == "user" && permission.SourceId == creatorId {
176+
continue
177+
}
178+
result = append(result, map[string]interface{}{
179+
"permission_name": permission.PermissionName,
180+
"source_type": permission.SourceType,
181+
"source_id": permission.SourceId,
182+
})
183+
}
184+
185+
return result
186+
}
187+
188+
func resourceToPermissionRequest(d *schema.ResourceData) (PermissionsRequest, error) {
189+
id := d.Id()
190+
if id == "" {
191+
return PermissionsRequest{}, errors.New("premission resource id not specified")
192+
}
193+
194+
return PermissionsRequest{
195+
Permissions: resourceToPermissionsArray(d.Get("permission").(*schema.Set), id),
196+
NotifyRecipients: d.Get("notify_recipient").(bool),
197+
NotificationMessage: d.Get("notification_message").(string),
198+
}, nil
199+
}

0 commit comments

Comments
 (0)