Skip to content

Commit eac929f

Browse files
committed
Merge branch 'master' into INVS-1408-match-lists
2 parents b2588ea + b4f1ccb commit eac929f

15 files changed

+629
-15
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
## 2.23.1 (Unreleased)
2+
FEATURES:
3+
* **New Resource:** sumologic_cse_outlier_rule (GH-532)
4+
* Add new optional `global_signal_suppression_window` field to sumologic_cse_insights_configuration (TRIDENT-18052)
5+
6+
BUG FIXES:
7+
* Enforce validation of `group_by_fields` in cse_*_rule resources, on non empty string elements. (GH-535)
28

39
## 2.23.0 (May 24, 2023)
410
FEATURES:

sumologic/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ func Provider() terraform.ResourceProvider {
6363
"sumologic_cse_match_rule": resourceSumologicCSEMatchRule(),
6464
"sumologic_cse_threshold_rule": resourceSumologicCSEThresholdRule(),
6565
"sumologic_cse_first_seen_rule": resourceSumologicCSEFirstSeenRule(),
66+
"sumologic_cse_outlier_rule": resourceSumologicCSEOutlierRule(),
6667
"sumologic_collector": resourceSumologicCollector(),
6768
"sumologic_installed_collector": resourceSumologicInstalledCollector(),
6869
"sumologic_http_source": resourceSumologicHTTPSource(),

sumologic/resource_sumologic_cse_aggregation_rule.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ func resourceSumologicCSEAggregationRule() *schema.Resource {
5858
Type: schema.TypeList,
5959
Optional: true,
6060
Elem: &schema.Schema{
61-
Type: schema.TypeString,
61+
Type: schema.TypeString,
62+
ValidateFunc: validation.StringIsNotEmpty,
6263
},
6364
},
6465
"is_prototype": {

sumologic/resource_sumologic_cse_chain_rule.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ func resourceSumologicCSEChainRule() *schema.Resource {
4646
Type: schema.TypeList,
4747
Optional: true,
4848
Elem: &schema.Schema{
49-
Type: schema.TypeString,
49+
Type: schema.TypeString,
50+
ValidateFunc: validation.StringIsNotEmpty,
5051
},
5152
},
5253
"is_prototype": {

sumologic/resource_sumologic_cse_first_seen_rule.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ func resourceSumologicCSEFirstSeenRule() *schema.Resource {
4242
Type: schema.TypeList,
4343
Optional: true,
4444
Elem: &schema.Schema{
45-
Type: schema.TypeString,
45+
Type: schema.TypeString,
46+
ValidateFunc: validation.StringIsNotEmpty,
4647
},
4748
},
4849
"is_prototype": {

sumologic/resource_sumologic_cse_insights_configuration.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ func resourceSumologicCSEInsightsConfiguration() *schema.Resource {
2626
Optional: true,
2727
ForceNew: false,
2828
},
29+
"global_signal_suppression_window": {
30+
Type: schema.TypeFloat,
31+
Optional: true,
32+
ForceNew: false,
33+
},
2934
},
3035
}
3136
}
@@ -49,6 +54,7 @@ func resourceSumologicCSEInsightsConfigurationRead(d *schema.ResourceData, meta
4954

5055
d.Set("lookback_days", CSEInsightsConfiguration.LookbackDays)
5156
d.Set("threshold", CSEInsightsConfiguration.Threshold)
57+
d.Set("global_signal_suppression_window", CSEInsightsConfiguration.GlobalSignalSuppressionWindow)
5258

5359
return nil
5460
}
@@ -93,9 +99,11 @@ func resourceToCSEInsightsConfiguration(d *schema.ResourceData) (CSEInsightsConf
9399

94100
lookbackDays := d.Get("lookback_days").(float64)
95101
threshold := d.Get("threshold").(float64)
102+
globalSignalSuppressionWindow := d.Get("global_signal_suppression_window").(float64)
96103

97104
return CSEInsightsConfiguration{
98-
LookbackDays: &lookbackDays,
99-
Threshold: &threshold,
105+
LookbackDays: &lookbackDays,
106+
Threshold: &threshold,
107+
GlobalSignalSuppressionWindow: &globalSignalSuppressionWindow,
100108
}, nil
101109
}

sumologic/resource_sumologic_cse_insights_configuration_test.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,18 @@ func TestAccSumologicSCEInsightsConfiguration_create(t *testing.T) {
1414
var insightConfiguration CSEInsightsConfiguration
1515
nLookbackDays := 10.0
1616
nThreshold := 13.0
17+
nGlobalSignalSuppressionWindow := 48.0
1718
resourceName := "sumologic_cse_insights_configuration.insights_configuration"
1819
resource.Test(t, resource.TestCase{
1920
PreCheck: func() { testAccPreCheck(t) },
2021
Providers: testAccProviders,
2122
CheckDestroy: testAccCSEInsightsConfigurationDestroy,
2223
Steps: []resource.TestStep{
2324
{
24-
Config: testCreateCSEInsightsConfigurationConfig(nLookbackDays, nThreshold),
25+
Config: testCreateCSEInsightsConfigurationConfig(nLookbackDays, nThreshold, nGlobalSignalSuppressionWindow),
2526
Check: resource.ComposeTestCheckFunc(
2627
testCheckCSEInsightsConfigurationExists(resourceName, &insightConfiguration),
27-
testCheckInsightsConfigurationValues(&insightConfiguration, nLookbackDays, nThreshold),
28+
testCheckInsightsConfigurationValues(&insightConfiguration, nLookbackDays, nThreshold, nGlobalSignalSuppressionWindow),
2829
resource.TestCheckResourceAttrSet(resourceName, "id"),
2930
),
3031
},
@@ -49,21 +50,22 @@ func testAccCSEInsightsConfigurationDestroy(s *terraform.State) error {
4950
return fmt.Errorf("Encountered an error: " + err.Error())
5051
}
5152
if s != nil {
52-
if s.Threshold != nil && s.LookbackDays != nil {
53+
if s.Threshold != nil && s.LookbackDays != nil && s.GlobalSignalSuppressionWindow != nil {
5354
return fmt.Errorf("insight Configuration still exists")
5455
}
5556
}
5657
}
5758
return nil
5859
}
5960

60-
func testCreateCSEInsightsConfigurationConfig(nLookbackDays float64, nThreshold float64) string {
61+
func testCreateCSEInsightsConfigurationConfig(nLookbackDays float64, nThreshold float64, nGlobalSignalSuppressionWindow float64) string {
6162
return fmt.Sprintf(`
6263
resource "sumologic_cse_insights_configuration" "insights_configuration" {
6364
lookback_days = "%f"
6465
threshold = "%f"
66+
global_signal_suppression_window = "%f"
6567
}
66-
`, nLookbackDays, nThreshold)
68+
`, nLookbackDays, nThreshold, nGlobalSignalSuppressionWindow)
6769
}
6870

6971
func testCheckCSEInsightsConfigurationExists(n string, insightConfiguration *CSEInsightsConfiguration) resource.TestCheckFunc {
@@ -89,14 +91,17 @@ func testCheckCSEInsightsConfigurationExists(n string, insightConfiguration *CSE
8991
}
9092
}
9193

92-
func testCheckInsightsConfigurationValues(insightConfiguration *CSEInsightsConfiguration, nLookbackDays float64, nThreshold float64) resource.TestCheckFunc {
94+
func testCheckInsightsConfigurationValues(insightConfiguration *CSEInsightsConfiguration, nLookbackDays float64, nThreshold float64, nGlobalSignalSuppressionWindow float64) resource.TestCheckFunc {
9395
return func(s *terraform.State) error {
9496
if *insightConfiguration.LookbackDays != nLookbackDays {
9597
return fmt.Errorf("bad lookback days, expected \"%f\", got: %#v", nLookbackDays, insightConfiguration.LookbackDays)
9698
}
9799
if *insightConfiguration.Threshold != nThreshold {
98100
return fmt.Errorf("bad threshold, expected \"%f\", got: %#v", nThreshold, insightConfiguration.Threshold)
99101
}
102+
if *insightConfiguration.GlobalSignalSuppressionWindow != nGlobalSignalSuppressionWindow {
103+
return fmt.Errorf("bad global signal suppression window, expected \"%f\", got: %#v", nGlobalSignalSuppressionWindow, insightConfiguration.GlobalSignalSuppressionWindow)
104+
}
100105

101106
return nil
102107
}
Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
package sumologic
2+
3+
import (
4+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
5+
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
6+
"log"
7+
)
8+
9+
func resourceSumologicCSEOutlierRule() *schema.Resource {
10+
return &schema.Resource{
11+
Create: resourceSumologicCSEOutlierRuleCreate,
12+
Read: resourceSumologicCSEOutlierRuleRead,
13+
Delete: resourceSumologicCSEOutlierRuleDelete,
14+
Update: resourceSumologicCSEOutlierRuleUpdate,
15+
Importer: &schema.ResourceImporter{
16+
State: schema.ImportStatePassthrough,
17+
},
18+
19+
Schema: map[string]*schema.Schema{
20+
"aggregation_functions": {
21+
Type: schema.TypeList,
22+
Required: true,
23+
MaxItems: 1,
24+
Elem: &schema.Resource{
25+
Schema: map[string]*schema.Schema{
26+
"name": {
27+
Type: schema.TypeString,
28+
Required: true,
29+
},
30+
"function": {
31+
Type: schema.TypeString,
32+
Required: true,
33+
},
34+
"arguments": {
35+
Type: schema.TypeList,
36+
Required: true,
37+
Elem: &schema.Schema{
38+
Type: schema.TypeString,
39+
},
40+
},
41+
},
42+
},
43+
},
44+
45+
"baseline_window_size": {
46+
Type: schema.TypeString,
47+
Required: true,
48+
},
49+
"description_expression": {
50+
Type: schema.TypeString,
51+
Required: true,
52+
},
53+
"deviation_threshold": {
54+
Type: schema.TypeInt,
55+
Required: true,
56+
},
57+
"enabled": {
58+
Type: schema.TypeBool,
59+
Required: true,
60+
},
61+
"entity_selectors": getEntitySelectorsSchema(),
62+
"floor_value": {
63+
Type: schema.TypeInt,
64+
Required: true,
65+
},
66+
"group_by_fields": {
67+
Type: schema.TypeList,
68+
Optional: true,
69+
Elem: &schema.Schema{
70+
Type: schema.TypeString,
71+
ValidateFunc: validation.StringIsNotEmpty,
72+
},
73+
},
74+
"is_prototype": {
75+
Type: schema.TypeBool,
76+
Optional: true,
77+
},
78+
"match_expression": {
79+
Type: schema.TypeString,
80+
Required: true,
81+
},
82+
"name": {
83+
Type: schema.TypeString,
84+
Required: true,
85+
},
86+
"name_expression": {
87+
Type: schema.TypeString,
88+
Required: true,
89+
},
90+
"retention_window_size": {
91+
Type: schema.TypeString,
92+
Required: true,
93+
},
94+
"severity": {
95+
Type: schema.TypeInt,
96+
Required: true,
97+
},
98+
"summary_expression": {
99+
Type: schema.TypeString,
100+
Optional: true,
101+
},
102+
"tags": {
103+
Type: schema.TypeList,
104+
Optional: true,
105+
Elem: &schema.Schema{
106+
Type: schema.TypeString,
107+
ValidateFunc: validation.StringIsNotEmpty,
108+
},
109+
},
110+
"window_size": {
111+
Type: schema.TypeString,
112+
Required: true,
113+
},
114+
},
115+
}
116+
}
117+
118+
func resourceSumologicCSEOutlierRuleRead(d *schema.ResourceData, meta interface{}) error {
119+
c := meta.(*Client)
120+
121+
var CSEOutlierRuleGet *CSEOutlierRule
122+
id := d.Id()
123+
124+
CSEOutlierRuleGet, err := c.GetCSEOutlierRule(id)
125+
if err != nil {
126+
log.Printf("[WARN] CSE Outlier Rule not found when looking by id: %s, err: %v", id, err)
127+
}
128+
129+
if CSEOutlierRuleGet == nil {
130+
log.Printf("[WARN] CSE Outlier Rule not found, removing from state: %v - %v", id, err)
131+
d.SetId("")
132+
return nil
133+
}
134+
135+
d.Set("aggregate_function", aggregationFunctionsArrayToResource(CSEOutlierRuleGet.AggregationFunctions))
136+
d.Set("baseline_window_size", CSEOutlierRuleGet.BaselineWindowSize)
137+
d.Set("description_expression", CSEOutlierRuleGet.DescriptionExpression)
138+
d.Set("deviation_threshold", CSEOutlierRuleGet.DeviationThreshold)
139+
d.Set("enabled", CSEOutlierRuleGet.Enabled)
140+
d.Set("entity_selectors", entitySelectorArrayToResource(CSEOutlierRuleGet.EntitySelectors))
141+
d.Set("floor_value", CSEOutlierRuleGet.FloorValue)
142+
d.Set("group_by_fields", CSEOutlierRuleGet.GroupByFields)
143+
d.Set("is_prototype", CSEOutlierRuleGet.IsPrototype)
144+
d.Set("match_expression", CSEOutlierRuleGet.MatchExpression)
145+
d.Set("name", CSEOutlierRuleGet.Name)
146+
d.Set("name_expression", CSEOutlierRuleGet.NameExpression)
147+
d.Set("retention_window_size", CSEOutlierRuleGet.RetentionWindowSize)
148+
d.Set("severity", CSEOutlierRuleGet.Severity)
149+
d.Set("summary_expression", CSEOutlierRuleGet.SummaryExpression)
150+
d.Set("tags", CSEOutlierRuleGet.Tags)
151+
d.Set("window_size", CSEOutlierRuleGet.WindowSizeName)
152+
153+
return nil
154+
}
155+
156+
func resourceSumologicCSEOutlierRuleDelete(d *schema.ResourceData, meta interface{}) error {
157+
c := meta.(*Client)
158+
159+
return c.DeleteCSEOutlierRule(d.Id())
160+
161+
}
162+
163+
func resourceSumologicCSEOutlierRuleCreate(d *schema.ResourceData, meta interface{}) error {
164+
c := meta.(*Client)
165+
166+
if d.Id() == "" {
167+
id, err := c.CreateCSEOutlierRule(CSEOutlierRule{
168+
AggregationFunctions: resourceToAggregationFunctionsArray(d.Get("aggregation_functions").([]interface{})),
169+
BaselineWindowSize: d.Get("baseline_window_size").(string),
170+
DescriptionExpression: d.Get("description_expression").(string),
171+
DeviationThreshold: d.Get("deviation_threshold").(int),
172+
Enabled: d.Get("enabled").(bool),
173+
EntitySelectors: resourceToEntitySelectorArray(d.Get("entity_selectors").([]interface{})),
174+
FloorValue: d.Get("floor_value").(int),
175+
GroupByFields: resourceToStringArray(d.Get("group_by_fields").([]interface{})),
176+
IsPrototype: d.Get("is_prototype").(bool),
177+
MatchExpression: d.Get("match_expression").(string),
178+
Name: d.Get("name").(string),
179+
NameExpression: d.Get("name_expression").(string),
180+
RetentionWindowSize: d.Get("retention_window_size").(string),
181+
Severity: d.Get("severity").(int),
182+
SummaryExpression: d.Get("summary_expression").(string),
183+
Tags: resourceToStringArray(d.Get("tags").([]interface{})),
184+
WindowSize: windowSizeField(d.Get("window_size").(string)),
185+
})
186+
187+
if err != nil {
188+
return err
189+
}
190+
d.SetId(id)
191+
}
192+
193+
return resourceSumologicCSEOutlierRuleRead(d, meta)
194+
}
195+
196+
func resourceSumologicCSEOutlierRuleUpdate(d *schema.ResourceData, meta interface{}) error {
197+
CSEOutlierRule, err := resourceToCSEOutlierRule(d)
198+
if err != nil {
199+
return err
200+
}
201+
202+
c := meta.(*Client)
203+
if err = c.UpdateCSEOutlierRule(CSEOutlierRule); err != nil {
204+
return err
205+
}
206+
207+
return resourceSumologicCSEOutlierRuleRead(d, meta)
208+
}
209+
210+
func resourceToCSEOutlierRule(d *schema.ResourceData) (CSEOutlierRule, error) {
211+
id := d.Id()
212+
if id == "" {
213+
return CSEOutlierRule{}, nil
214+
}
215+
216+
return CSEOutlierRule{
217+
ID: id,
218+
AggregationFunctions: resourceToAggregationFunctionsArray(d.Get("aggregation_functions").([]interface{})),
219+
BaselineWindowSize: d.Get("baseline_window_size").(string),
220+
DescriptionExpression: d.Get("description_expression").(string),
221+
DeviationThreshold: d.Get("deviation_threshold").(int),
222+
Enabled: d.Get("enabled").(bool),
223+
EntitySelectors: resourceToEntitySelectorArray(d.Get("entity_selectors").([]interface{})),
224+
FloorValue: d.Get("floor_value").(int),
225+
GroupByFields: resourceToStringArray(d.Get("group_by_fields").([]interface{})),
226+
IsPrototype: d.Get("is_prototype").(bool),
227+
MatchExpression: d.Get("match_expression").(string),
228+
Name: d.Get("name").(string),
229+
NameExpression: d.Get("name_expression").(string),
230+
RetentionWindowSize: d.Get("retention_window_size").(string),
231+
Severity: d.Get("severity").(int),
232+
SummaryExpression: d.Get("summary_expression").(string),
233+
Tags: resourceToStringArray(d.Get("tags").([]interface{})),
234+
WindowSize: windowSizeField(d.Get("window_size").(string)),
235+
}, nil
236+
}

0 commit comments

Comments
 (0)