Skip to content

Commit e67b238

Browse files
author
Josh Williams
authored
Merge pull request #287 from SumoLogic/cse-rule-resource
Add support for CSE Match/Threshold rules
2 parents 8a955e1 + 3179107 commit e67b238

12 files changed

+1237
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ FEATURES:
1212
* **New Resource:** sumologic_cse_insights_configuration (GH-274)
1313
* **New Resource:** sumologic_cse_log_mapping (GH-284)
1414
* **New Datasource:** sumologic_cse_log_mapping_vendor_product (GH-284)
15+
* **New Resource:** sumologic_cse_match_rule (GH-287)
16+
* **New Resource:** sumologic_cse_threshold_rule (GH-287)
1517

1618
BUG FIXES:
1719

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ $ make build
4848

4949
In order to test the provider, you can run `make test`.
5050

51-
For manual testing, run `make install` in the root direcory to install it as a plugin.
51+
For manual testing, run `make install` in the root directory to install it as a plugin.
5252
Then run `terraform init` to initialize it.
5353

5454
In order to run the full suite of Acceptance tests, run `make testacc`.

sumologic/provider.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ func Provider() terraform.ResourceProvider {
5151
"sumologic_cse_insights_configuration": resourceSumologicCSEInsightsConfiguration(),
5252
"sumologic_cse_insights_resolution": resourceSumologicCSEInsightsResolution(),
5353
"sumologic_cse_insights_status": resourceSumologicCSEInsightsStatus(),
54+
"sumologic_cse_match_rule": resourceSumologicCSEMatchRule(),
55+
"sumologic_cse_threshold_rule": resourceSumologicCSEThresholdRule(),
5456
"sumologic_collector": resourceSumologicCollector(),
5557
"sumologic_http_source": resourceSumologicHTTPSource(),
5658
"sumologic_gcp_source": resourceSumologicGCPSource(),
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
package sumologic
2+
3+
import (
4+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
5+
"log"
6+
)
7+
8+
func resourceSumologicCSEMatchRule() *schema.Resource {
9+
return &schema.Resource{
10+
Create: resourceSumologicCSEMatchRuleCreate,
11+
Read: resourceSumologicCSEMatchRuleRead,
12+
Delete: resourceSumologicCSEMatchRuleDelete,
13+
Update: resourceSumologicCSEMatchRuleUpdate,
14+
Importer: &schema.ResourceImporter{
15+
State: schema.ImportStatePassthrough,
16+
},
17+
18+
Schema: map[string]*schema.Schema{
19+
"description_expression": {
20+
Type: schema.TypeString,
21+
Required: true,
22+
},
23+
"enabled": {
24+
Type: schema.TypeBool,
25+
Required: true,
26+
},
27+
"entity_selectors": getEntitySelectorsSchema(),
28+
"expression": {
29+
Type: schema.TypeString,
30+
Required: true,
31+
},
32+
"is_prototype": {
33+
Type: schema.TypeBool,
34+
Optional: true,
35+
},
36+
"name": {
37+
Type: schema.TypeString,
38+
Required: true,
39+
},
40+
"name_expression": {
41+
Type: schema.TypeString,
42+
Required: true,
43+
},
44+
"severity_mapping": getSeverityMappingSchema(),
45+
"summary_expression": {
46+
Type: schema.TypeString,
47+
Optional: true,
48+
},
49+
"tags": {
50+
Type: schema.TypeList,
51+
Optional: true,
52+
Elem: &schema.Schema{
53+
Type: schema.TypeString,
54+
},
55+
},
56+
},
57+
}
58+
}
59+
60+
func resourceSumologicCSEMatchRuleRead(d *schema.ResourceData, meta interface{}) error {
61+
c := meta.(*Client)
62+
63+
var CSEMatchRuleGet *CSEMatchRule
64+
id := d.Id()
65+
66+
CSEMatchRuleGet, err := c.GetCSEMatchRule(id)
67+
if err != nil {
68+
log.Printf("[WARN] CSE Match Rule not found when looking by id: %s, err: %v", id, err)
69+
70+
}
71+
72+
if CSEMatchRuleGet == nil {
73+
log.Printf("[WARN] CSE Match Rule not found, removing from state: %v - %v", id, err)
74+
d.SetId("")
75+
return nil
76+
}
77+
78+
d.Set("description_expression", CSEMatchRuleGet.DescriptionExpression)
79+
d.Set("enabled", CSEMatchRuleGet.Enabled)
80+
d.Set("entity_selectors", entitySelectorArrayToResource(CSEMatchRuleGet.EntitySelectors))
81+
d.Set("expression", CSEMatchRuleGet.Expression)
82+
d.Set("is_prototype", CSEMatchRuleGet.IsPrototype)
83+
d.Set("name", CSEMatchRuleGet.Name)
84+
d.Set("name_expression", CSEMatchRuleGet.NameExpression)
85+
d.Set("severity_mapping", severityMappingToResource(CSEMatchRuleGet.SeverityMapping))
86+
d.Set("summary_expression", CSEMatchRuleGet.SummaryExpression)
87+
d.Set("tags", CSEMatchRuleGet.Tags)
88+
89+
return nil
90+
}
91+
92+
func resourceSumologicCSEMatchRuleDelete(d *schema.ResourceData, meta interface{}) error {
93+
c := meta.(*Client)
94+
95+
return c.DeleteCSEMatchRule(d.Id())
96+
97+
}
98+
99+
func resourceSumologicCSEMatchRuleCreate(d *schema.ResourceData, meta interface{}) error {
100+
c := meta.(*Client)
101+
102+
if d.Id() == "" {
103+
id, err := c.CreateCSEMatchRule(CSEMatchRule{
104+
DescriptionExpression: d.Get("description_expression").(string),
105+
Enabled: d.Get("enabled").(bool),
106+
EntitySelectors: resourceToEntitySelectorArray(d.Get("entity_selectors").([]interface{})),
107+
Expression: d.Get("expression").(string),
108+
IsPrototype: d.Get("is_prototype").(bool),
109+
Name: d.Get("name").(string),
110+
NameExpression: d.Get("name_expression").(string),
111+
SeverityMapping: resourceToSeverityMapping(d.Get("severity_mapping").([]interface{})[0]),
112+
Stream: "record",
113+
SummaryExpression: d.Get("summary_expression").(string),
114+
Tags: resourceToStringArray(d.Get("tags").([]interface{})),
115+
})
116+
117+
if err != nil {
118+
return err
119+
}
120+
d.SetId(id)
121+
}
122+
123+
return resourceSumologicCSEMatchRuleRead(d, meta)
124+
}
125+
126+
func resourceSumologicCSEMatchRuleUpdate(d *schema.ResourceData, meta interface{}) error {
127+
CSEMatchRule, err := resourceToCSEMatchRule(d)
128+
if err != nil {
129+
return err
130+
}
131+
132+
c := meta.(*Client)
133+
if err = c.UpdateCSEMatchRule(CSEMatchRule); err != nil {
134+
return err
135+
}
136+
137+
return resourceSumologicCSEMatchRuleRead(d, meta)
138+
}
139+
140+
func resourceToCSEMatchRule(d *schema.ResourceData) (CSEMatchRule, error) {
141+
id := d.Id()
142+
if id == "" {
143+
return CSEMatchRule{}, nil
144+
}
145+
146+
return CSEMatchRule{
147+
ID: id,
148+
DescriptionExpression: d.Get("description_expression").(string),
149+
Enabled: d.Get("enabled").(bool),
150+
EntitySelectors: resourceToEntitySelectorArray(d.Get("entity_selectors").([]interface{})),
151+
Expression: d.Get("expression").(string),
152+
IsPrototype: d.Get("is_prototype").(bool),
153+
Name: d.Get("name").(string),
154+
NameExpression: d.Get("name_expression").(string),
155+
SeverityMapping: resourceToSeverityMapping(d.Get("severity_mapping").([]interface{})[0]),
156+
Stream: "record",
157+
SummaryExpression: d.Get("summary_expression").(string),
158+
Tags: resourceToStringArray(d.Get("tags").([]interface{})),
159+
}, nil
160+
}
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
package sumologic
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
8+
"github.com/hashicorp/terraform-plugin-sdk/terraform"
9+
)
10+
11+
func TestAccSumologicCSEMatchRule_createAndUpdate(t *testing.T) {
12+
var matchRule CSEMatchRule
13+
descriptionExpression := "Test description"
14+
enabled := true
15+
entitySelectorEntityType := "_ip"
16+
entitySelectorExpression := "srcDevice_ip"
17+
expression := "foo = bar"
18+
isPrototype := false
19+
name := "Test Match Rule"
20+
nameExpression := "Signal Name"
21+
severityMappingType := "constant"
22+
severityMappingDefault := 5
23+
summaryExpression := "Signal Summary"
24+
tag := "foo"
25+
26+
nameUpdated := "Updated Match Rule"
27+
tagUpdated := "bar"
28+
29+
resourceName := "sumologic_cse_match_rule.match_rule"
30+
resource.Test(t, resource.TestCase{
31+
PreCheck: func() { testAccPreCheck(t) },
32+
Providers: testAccProviders,
33+
CheckDestroy: testAccCSEMatchRuleDestroy,
34+
Steps: []resource.TestStep{
35+
{
36+
Config: testCreateCSEMatchRuleConfig(descriptionExpression, enabled,
37+
entitySelectorEntityType, entitySelectorExpression, expression,
38+
isPrototype, name, nameExpression, severityMappingType, severityMappingDefault,
39+
summaryExpression, tag),
40+
Check: resource.ComposeTestCheckFunc(
41+
testCheckCSEMatchRuleExists(resourceName, &matchRule),
42+
testCheckMatchRuleValues(&matchRule, descriptionExpression, enabled,
43+
entitySelectorEntityType, entitySelectorExpression, expression,
44+
isPrototype, name, nameExpression, severityMappingType, severityMappingDefault,
45+
summaryExpression, tag),
46+
resource.TestCheckResourceAttrSet(resourceName, "id"),
47+
),
48+
},
49+
{
50+
Config: testCreateCSEMatchRuleConfig(descriptionExpression, enabled,
51+
entitySelectorEntityType, entitySelectorExpression, expression,
52+
isPrototype, nameUpdated, nameExpression, severityMappingType, severityMappingDefault,
53+
summaryExpression, tagUpdated),
54+
Check: resource.ComposeTestCheckFunc(
55+
testCheckCSEMatchRuleExists(resourceName, &matchRule),
56+
testCheckMatchRuleValues(&matchRule, descriptionExpression, enabled,
57+
entitySelectorEntityType, entitySelectorExpression, expression,
58+
isPrototype, nameUpdated, nameExpression, severityMappingType, severityMappingDefault,
59+
summaryExpression, tagUpdated),
60+
resource.TestCheckResourceAttrSet(resourceName, "id"),
61+
),
62+
},
63+
},
64+
})
65+
}
66+
67+
func testAccCSEMatchRuleDestroy(s *terraform.State) error {
68+
client := testAccProvider.Meta().(*Client)
69+
70+
for _, rs := range s.RootModule().Resources {
71+
if rs.Type != "sumologic_cse_match_rule" {
72+
continue
73+
}
74+
75+
if rs.Primary.ID == "" {
76+
return fmt.Errorf("CSE Match Rule destruction check: CSE Match Rule ID is not set")
77+
}
78+
79+
s, err := client.GetCSEMatchRule(rs.Primary.ID)
80+
if err != nil {
81+
return fmt.Errorf("Encountered an error: " + err.Error())
82+
}
83+
if s != nil {
84+
return fmt.Errorf("Match rule still exists")
85+
}
86+
}
87+
return nil
88+
}
89+
90+
func testCreateCSEMatchRuleConfig(
91+
descriptionExpression string, enabled bool, entitySelectorEntityType string,
92+
entitySelectorExpression string, expression string, isPrototype bool, name string,
93+
nameExpression string, severityMappingType string, severityMappingDefault int,
94+
summaryExpression string, tag string) string {
95+
return fmt.Sprintf(`
96+
resource "sumologic_cse_match_rule" "match_rule" {
97+
description_expression = "%s"
98+
enabled = %t
99+
entity_selectors {
100+
entity_type = "%s"
101+
expression = "%s"
102+
}
103+
expression = "%s"
104+
is_prototype = %t
105+
name = "%s"
106+
name_expression = "%s"
107+
severity_mapping {
108+
type = "%s"
109+
default = %d
110+
}
111+
summary_expression = "%s"
112+
tags = ["%s"]
113+
}
114+
`, descriptionExpression, enabled, entitySelectorEntityType, entitySelectorExpression,
115+
expression, isPrototype, name, nameExpression, severityMappingType, severityMappingDefault,
116+
summaryExpression, tag)
117+
}
118+
119+
func testCheckCSEMatchRuleExists(n string, matchRule *CSEMatchRule) resource.TestCheckFunc {
120+
return func(s *terraform.State) error {
121+
rs, ok := s.RootModule().Resources[n]
122+
if !ok {
123+
return fmt.Errorf("not found: %s", n)
124+
}
125+
126+
if rs.Primary.ID == "" {
127+
return fmt.Errorf("match rule ID is not set")
128+
}
129+
130+
c := testAccProvider.Meta().(*Client)
131+
matchRuleResp, err := c.GetCSEMatchRule(rs.Primary.ID)
132+
if err != nil {
133+
return err
134+
}
135+
136+
*matchRule = *matchRuleResp
137+
138+
return nil
139+
}
140+
}
141+
142+
func testCheckMatchRuleValues(matchRule *CSEMatchRule, descriptionExpression string, enabled bool,
143+
entitySelectorEntityType string, entitySelectorExpression string, expression string,
144+
isPrototype bool, name string, nameExpression string, severityMappingType string, severityMappingDefault int,
145+
summaryExpression string, tag string) resource.TestCheckFunc {
146+
return func(s *terraform.State) error {
147+
if matchRule.DescriptionExpression != descriptionExpression {
148+
return fmt.Errorf("bad descriptionExpression, expected \"%s\", got %#v", descriptionExpression, matchRule.DescriptionExpression)
149+
}
150+
if matchRule.Enabled != enabled {
151+
return fmt.Errorf("bad enabled, expected \"%t\", got %#v", enabled, matchRule.Enabled)
152+
}
153+
if matchRule.EntitySelectors[0].EntityType != entitySelectorEntityType {
154+
return fmt.Errorf("bad entitySelectorEntityType, expected \"%s\", got %#v", entitySelectorEntityType, matchRule.EntitySelectors[0].EntityType)
155+
}
156+
if matchRule.EntitySelectors[0].Expression != entitySelectorExpression {
157+
return fmt.Errorf("bad entitySelectorExpression, expected \"%s\", got %#v", entitySelectorExpression, matchRule.EntitySelectors[0].Expression)
158+
}
159+
if matchRule.Expression != expression {
160+
return fmt.Errorf("bad expression, expected \"%s\", got %#v", expression, matchRule.Expression)
161+
}
162+
if matchRule.IsPrototype != isPrototype {
163+
return fmt.Errorf("bad isPrototype, expected \"%t\", got %#v", isPrototype, matchRule.IsPrototype)
164+
}
165+
if matchRule.Name != name {
166+
return fmt.Errorf("bad name, expected \"%s\", got %#v", name, matchRule.Name)
167+
}
168+
if matchRule.NameExpression != nameExpression {
169+
return fmt.Errorf("bad nameExpression, expected \"%s\", got %#v", nameExpression, matchRule.NameExpression)
170+
}
171+
if matchRule.SeverityMapping.Type != severityMappingType {
172+
return fmt.Errorf("bad severityMappingType, expected \"%s\", got %#v", severityMappingType, matchRule.SeverityMapping.Type)
173+
}
174+
if matchRule.SeverityMapping.Default != severityMappingDefault {
175+
return fmt.Errorf("bad severityMappingDefault, expected \"%d\", got %#v", severityMappingDefault, matchRule.SeverityMapping.Default)
176+
}
177+
if matchRule.SummaryExpression != summaryExpression {
178+
return fmt.Errorf("bad summaryExpression, expected \"%s\", got %#v", summaryExpression, matchRule.SummaryExpression)
179+
}
180+
if matchRule.Tags[0] != tag {
181+
return fmt.Errorf("bad tag, expected \"%s\", got %#v", tag, matchRule.Tags[0])
182+
}
183+
184+
return nil
185+
}
186+
}

0 commit comments

Comments
 (0)