Skip to content

Commit 133a9fe

Browse files
CSOAR-3990: Add Terraform support for CSOAR Playbooks
1 parent 3d97b05 commit 133a9fe

File tree

3 files changed

+209
-0
lines changed

3 files changed

+209
-0
lines changed

sumologic/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ func Provider() *schema.Provider {
6666
"sumologic_cse_threshold_rule": resourceSumologicCSEThresholdRule(),
6767
"sumologic_cse_first_seen_rule": resourceSumologicCSEFirstSeenRule(),
6868
"sumologic_cse_outlier_rule": resourceSumologicCSEOutlierRule(),
69+
"sumologic_csoar_playbook": resourceSumologicCsoarPlaybook(),
6970
"sumologic_collector": resourceSumologicCollector(),
7071
"sumologic_installed_collector": resourceSumologicInstalledCollector(),
7172
"sumologic_http_source": resourceSumologicHTTPSource(),
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
package sumologic
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
7+
)
8+
9+
func resourceSumologicCsoarPlaybook() *schema.Resource {
10+
return &schema.Resource{
11+
Create: resourceSumologicCsoarPlaybookCreate,
12+
Read: resourceSumologicCsoarPlaybookRead,
13+
Update: resourceSumologicCsoarPlaybookUpdate,
14+
Delete: resourceSumologicCsoarPlaybookDelete,
15+
Importer: &schema.ResourceImporter{
16+
State: resourceSumologicCsoarPlaybookImport,
17+
},
18+
19+
Schema: map[string]*schema.Schema{
20+
"name": {
21+
Type: schema.TypeString,
22+
Required: true,
23+
},
24+
"description": {
25+
Type: schema.TypeString,
26+
Optional: true,
27+
},
28+
"updated_name": {
29+
Type: schema.TypeString,
30+
Optional: true,
31+
},
32+
"tags": {
33+
Type: schema.TypeString,
34+
Optional: true,
35+
},
36+
"is_deleted": {
37+
Type: schema.TypeBool,
38+
Optional: true,
39+
Default: false,
40+
},
41+
"draft": {
42+
Type: schema.TypeBool,
43+
Optional: true,
44+
Default: false,
45+
},
46+
"is_published": {
47+
Type: schema.TypeBool,
48+
Optional: true,
49+
Default: false,
50+
},
51+
"last_updated": {
52+
Type: schema.TypeInt,
53+
Computed: true, // This should be set by the API, not by user
54+
},
55+
"created_by": {
56+
Type: schema.TypeInt,
57+
Computed: true, // This should be set by the API, not by user
58+
},
59+
"updated_by": {
60+
Type: schema.TypeInt,
61+
Computed: true, // This should be set by the API, not by user
62+
},
63+
"nested": {
64+
Type: schema.TypeBool,
65+
Optional: true,
66+
Default: false,
67+
},
68+
"type": {
69+
Type: schema.TypeString,
70+
Optional: true,
71+
},
72+
"is_enabled": {
73+
Type: schema.TypeBool,
74+
Optional: true,
75+
Default: true,
76+
},
77+
"links": {
78+
Type: schema.TypeList,
79+
Optional: true,
80+
Elem: &schema.Schema{
81+
Type: schema.TypeMap,
82+
Elem: &schema.Schema{
83+
Type: schema.TypeString,
84+
},
85+
},
86+
},
87+
"nodes": {
88+
Type: schema.TypeList,
89+
Optional: true,
90+
Elem: &schema.Schema{
91+
Type: schema.TypeMap,
92+
Elem: &schema.Schema{
93+
Type: schema.TypeString,
94+
},
95+
},
96+
},
97+
},
98+
}
99+
}
100+
101+
func resourceSumologicCsoarPlaybookDelete(d *schema.ResourceData, meta interface{}) error {
102+
c := meta.(*Client)
103+
name := d.Get("name").(string)
104+
return c.DeletePlaybook(name)
105+
}
106+
107+
func resourceSumologicCsoarPlaybookUpdate(d *schema.ResourceData, meta interface{}) error {
108+
c := meta.(*Client)
109+
110+
playbook := Playbook{
111+
Description: d.Get("description").(string),
112+
Name: d.Get("name").(string),
113+
UpdatedName: d.Get("updated_name").(string),
114+
Tags: d.Get("tags").(string),
115+
IsDeleted: d.Get("is_deleted").(bool),
116+
Draft: d.Get("draft").(bool),
117+
IsPublished: d.Get("is_published").(bool),
118+
LastUpdated: int64(d.Get("last_updated").(int)),
119+
CreatedBy: int64(d.Get("created_by").(int)),
120+
UpdatedBy: int64(d.Get("updated_by").(int)),
121+
Nested: d.Get("nested").(bool),
122+
Type: d.Get("type").(string),
123+
IsEnabled: d.Get("is_enabled").(bool),
124+
}
125+
126+
if v, ok := d.Get("links").([]interface{}); ok {
127+
links := make([]map[string]interface{}, len(v))
128+
for i, link := range v {
129+
if linkMap, ok := link.(map[string]interface{}); ok {
130+
links[i] = linkMap
131+
}
132+
}
133+
playbook.Links = links
134+
}
135+
136+
if v, ok := d.Get("nodes").([]interface{}); ok {
137+
nodes := make([]map[string]interface{}, len(v))
138+
for i, node := range v {
139+
if nodeMap, ok := node.(map[string]interface{}); ok {
140+
nodes[i] = nodeMap
141+
}
142+
}
143+
playbook.Nodes = nodes
144+
}
145+
146+
return c.UpdatePlaybook(playbook)
147+
}
148+
149+
func resourceSumologicCsoarPlaybookCreate(d *schema.ResourceData, meta interface{}) error {
150+
return fmt.Errorf("playbooks cannot be created via Terraform. Please create the playbook in the Sumo Logic UI and then import it using 'terraform import'")
151+
}
152+
153+
func resourceSumologicCsoarPlaybookRead(d *schema.ResourceData, meta interface{}) error {
154+
if d.Id() == "" {
155+
return fmt.Errorf("resource ID is empty")
156+
}
157+
158+
return nil
159+
}
160+
161+
func resourceSumologicCsoarPlaybookImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
162+
playbookName := d.Id()
163+
164+
if playbookName == "" {
165+
return nil, fmt.Errorf("import ID (playbook name) cannot be empty")
166+
}
167+
168+
d.SetId(playbookName)
169+
d.Set("name", playbookName)
170+
171+
return []*schema.ResourceData{d}, nil
172+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package sumologic
2+
3+
import (
4+
"fmt"
5+
"net/url"
6+
)
7+
8+
func (s *Client) DeletePlaybook(name string) error {
9+
_, err := s.Delete(fmt.Sprintf("api/csoar/v3/playbook/?name=%s", url.QueryEscape(name)))
10+
11+
return err
12+
}
13+
14+
func (s *Client) UpdatePlaybook(playbook Playbook) error {
15+
_, err := s.Put("api/csoar/v3/playbook/", playbook)
16+
17+
return err
18+
}
19+
20+
type Playbook struct {
21+
Description string `json:"description,omitempty"`
22+
Name string `json:"name"`
23+
UpdatedName string `json:"updated_name,omitempty"`
24+
Tags string `json:"tags,omitempty"`
25+
IsDeleted bool `json:"is_deleted,omitempty"`
26+
Draft bool `json:"draft,omitempty"`
27+
IsPublished bool `json:"is_published,omitempty"`
28+
LastUpdated int64 `json:"last_updated,omitempty"`
29+
Links []map[string]interface{} `json:"links,omitempty"`
30+
Nodes []map[string]interface{} `json:"nodes,omitempty"`
31+
CreatedBy int64 `json:"created_by,omitempty"`
32+
UpdatedBy int64 `json:"updated_by,omitempty"`
33+
Nested bool `json:"nested,omitempty"`
34+
Type string `json:"type,omitempty"`
35+
IsEnabled bool `json:"is_enabled,omitempty"`
36+
}

0 commit comments

Comments
 (0)