Skip to content

Commit 79dfb10

Browse files
committed
Merge branch 'master' into vishal-folder-data-source-163889
2 parents bfd7eaf + 97f1a54 commit 79dfb10

11 files changed

+1725
-30
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
FEATURES:
44
* Add new optional `alert_name` field to resource/sumologic_monitor.
5+
* **New Resource:** `sumologic_slo` ([GH-362](https://github.com/SumoLogic/terraform-provider-sumologic/pull/362/files))
6+
* **New Resource:** `sumologic_slo_folder` ([GH-362](https://github.com/SumoLogic/terraform-provider-sumologic/pull/362/files))
7+
* Add support for slo based monitors ([GH-363](https://github.com/SumoLogic/terraform-provider-sumologic/pull/363/files))
8+
59

610
BUG FIXES:
711
* Add CRITICAL as a valid value for cse_custom_insight severity field (GH-367)

sumologic/provider.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ func Provider() terraform.ResourceProvider {
8585
"sumologic_connection": resourceSumologicConnection(),
8686
"sumologic_monitor": resourceSumologicMonitorsLibraryMonitor(),
8787
"sumologic_monitor_folder": resourceSumologicMonitorsLibraryFolder(),
88+
"sumologic_slo": resourceSumologicSLO(),
89+
"sumologic_slo_folder": resourceSumologicSLOLibraryFolder(),
8890
"sumologic_ingest_budget_v2": resourceSumologicIngestBudgetV2(),
8991
"sumologic_field": resourceSumologicField(),
9092
"sumologic_lookup_table": resourceSumologicLookupTable(),

sumologic/resource_sumologic_monitors_library_monitor.go

Lines changed: 189 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,12 @@ func resourceSumologicMonitorsLibraryMonitor() *schema.Resource {
120120
ValidateFunc: validation.StringInSlice([]string{"AtLeastOnce", "Always", "ResultCount", "MissingData"}, false),
121121
},
122122
"detection_method": {
123-
Type: schema.TypeString,
124-
Optional: true,
125-
ValidateFunc: validation.StringInSlice([]string{"StaticCondition", "LogsStaticCondition", "MetricsStaticCondition", "LogsOutlierCondition", "MetricsOutlierCondition", "LogsMissingDataCondition", "MetricsMissingDataCondition"}, false),
123+
Type: schema.TypeString,
124+
Optional: true,
125+
ValidateFunc: validation.StringInSlice([]string{"StaticCondition", "LogsStaticCondition",
126+
"MetricsStaticCondition", "LogsOutlierCondition", "MetricsOutlierCondition",
127+
"LogsMissingDataCondition", "MetricsMissingDataCondition", "SloSliCondition",
128+
"SloBurnRateCondition"}, false),
126129
},
127130
},
128131
},
@@ -182,6 +185,22 @@ func resourceSumologicMonitorsLibraryMonitor() *schema.Resource {
182185
Schema: metricsMissingDataTriggerConditionSchema,
183186
},
184187
},
188+
sloSLIConditionFieldName: {
189+
Type: schema.TypeList,
190+
MaxItems: 1,
191+
Optional: true,
192+
Elem: &schema.Resource{
193+
Schema: sloSLITriggerConditionSchema,
194+
},
195+
},
196+
sloBurnRateConditionFieldName: {
197+
Type: schema.TypeList,
198+
MaxItems: 1,
199+
Optional: true,
200+
Elem: &schema.Resource{
201+
Schema: sloBurnRateTriggerConditionSchema,
202+
},
203+
},
185204
},
186205
},
187206
},
@@ -266,7 +285,7 @@ func resourceSumologicMonitorsLibraryMonitor() *schema.Resource {
266285
"monitor_type": {
267286
Type: schema.TypeString,
268287
Required: true,
269-
ValidateFunc: validation.StringInSlice([]string{"Logs", "Metrics"}, false),
288+
ValidateFunc: validation.StringInSlice([]string{"Logs", "Metrics", "Slo"}, false),
270289
},
271290

272291
"evaluation_delay": {
@@ -325,7 +344,10 @@ func resourceSumologicMonitorsLibraryMonitor() *schema.Resource {
325344
Type: schema.TypeString,
326345
Optional: true,
327346
},
328-
347+
"slo_id": {
348+
Type: schema.TypeString,
349+
Optional: true,
350+
},
329351
"alert_name": {
330352
Type: schema.TypeString,
331353
Optional: true,
@@ -445,6 +467,42 @@ var metricsMissingDataTriggerConditionSchema = map[string]*schema.Schema{
445467
},
446468
}
447469

470+
var sloSLITriggerConditionSchema = map[string]*schema.Schema{
471+
"critical": nested(true, schemaMap{
472+
"sli_threshold": {
473+
Type: schema.TypeFloat,
474+
Required: true,
475+
ValidateFunc: validation.FloatBetween(0, 100),
476+
},
477+
}),
478+
"warning": nested(true, schemaMap{
479+
"sli_threshold": {
480+
Type: schema.TypeFloat,
481+
Required: true,
482+
ValidateFunc: validation.FloatBetween(0, 100),
483+
},
484+
}),
485+
}
486+
487+
var sloBurnRateTriggerConditionSchema = map[string]*schema.Schema{
488+
"critical": nested(true, schemaMap{
489+
"time_range": &timeRangeSchema,
490+
"burn_rate_threshold": {
491+
Type: schema.TypeFloat,
492+
Required: true,
493+
ValidateFunc: validation.FloatAtLeast(0),
494+
},
495+
}),
496+
"warning": nested(true, schemaMap{
497+
"time_range": &timeRangeSchema,
498+
"burn_rate_threshold": {
499+
Type: schema.TypeFloat,
500+
Required: true,
501+
ValidateFunc: validation.FloatAtLeast(0),
502+
},
503+
}),
504+
}
505+
448506
var occurrenceTypeSchema = schema.Schema{
449507
Type: schema.TypeString,
450508
Required: true,
@@ -549,6 +607,7 @@ func resourceSumologicMonitorsLibraryMonitorRead(d *schema.ResourceData, meta in
549607
d.Set("group_notifications", monitor.GroupNotifications)
550608
d.Set("playbook", monitor.Playbook)
551609
d.Set("alert_name", monitor.AlertName)
610+
d.Set("slo_id", monitor.SloID)
552611
// set notifications
553612
notifications := make([]interface{}, len(monitor.Notifications))
554613
for i, n := range monitor.Notifications {
@@ -765,6 +824,13 @@ func triggerConditionsBlockToJson(block map[string]interface{}) []TriggerConditi
765824
if sc, ok := fromSingletonArray(block, metricsMissingDataConditionFieldName); ok {
766825
conditions = append(conditions, metricsMissingDataConditionBlockToJson(sc)...)
767826
}
827+
if sc, ok := fromSingletonArray(block, sloSLIConditionFieldName); ok {
828+
conditions = append(conditions, sloSLIConditionBlockToJson(sc)...)
829+
}
830+
if sc, ok := fromSingletonArray(block, sloBurnRateConditionFieldName); ok {
831+
conditions = append(conditions, sloBurnConditionBlockToJson(sc)...)
832+
}
833+
768834
return conditions
769835
}
770836

@@ -846,6 +912,7 @@ func metricsMissingDataConditionBlockToJson(block map[string]interface{}) []Trig
846912
DetectionMethod: metricsMissingDataConditionDetectionMethod,
847913
TriggerType: "MissingData",
848914
}
915+
849916
resolution := TriggerCondition{
850917
TimeRange: block["time_range"].(string),
851918
TriggerSource: block["trigger_source"].(string),
@@ -855,6 +922,22 @@ func metricsMissingDataConditionBlockToJson(block map[string]interface{}) []Trig
855922
return []TriggerCondition{alert, resolution}
856923
}
857924

925+
func sloSLIConditionBlockToJson(block map[string]interface{}) []TriggerCondition {
926+
base := TriggerCondition{
927+
DetectionMethod: sloSLIConditionDetectionMethod,
928+
}
929+
930+
return base.sloCloneReadingFromNestedBlocks(block)
931+
}
932+
933+
func sloBurnConditionBlockToJson(block map[string]interface{}) []TriggerCondition {
934+
base := TriggerCondition{
935+
DetectionMethod: sloBurnRateConditionDetectionMethod,
936+
}
937+
938+
return base.sloCloneReadingFromNestedBlocks(block)
939+
}
940+
858941
// TriggerCondition JSON model to 'trigger_conditions' block
859942
func jsonToTriggerConditionsBlock(conditions []TriggerCondition) map[string]interface{} {
860943
missingDataConditions := make([]TriggerCondition, 0)
@@ -877,6 +960,10 @@ func jsonToTriggerConditionsBlock(conditions []TriggerCondition) map[string]inte
877960
triggerConditionsBlock[logsOutlierConditionFieldName] = toSingletonArray(jsonToLogsOutlierConditionBlock(dataConditions))
878961
case metricsOutlierConditionDetectionMethod:
879962
triggerConditionsBlock[metricsOutlierConditionFieldName] = toSingletonArray(jsonToMetricsOutlierConditionBlock(dataConditions))
963+
case sloSLIConditionDetectionMethod:
964+
triggerConditionsBlock[sloSLIConditionFieldName] = toSingletonArray(jsonToSloSliConditionBlock(dataConditions))
965+
case sloBurnRateConditionDetectionMethod:
966+
triggerConditionsBlock[sloBurnRateConditionFieldName] = toSingletonArray(jsonToSloBurnRateConditionBlock(dataConditions))
880967
}
881968
}
882969
if len(missingDataConditions) > 0 {
@@ -1072,6 +1159,63 @@ func jsonToMetricsOutlierConditionBlock(conditions []TriggerCondition) map[strin
10721159
return block
10731160
}
10741161

1162+
func jsonToSloSliConditionBlock(conditions []TriggerCondition) map[string]interface{} {
1163+
var criticalAlrt, warningAlrt = dict{}, dict{}
1164+
block := map[string]interface{}{}
1165+
1166+
block["critical"] = toSingletonArray(criticalAlrt)
1167+
block["warning"] = toSingletonArray(warningAlrt)
1168+
1169+
var hasCritical, hasWarning = false, false
1170+
for _, condition := range conditions {
1171+
switch condition.TriggerType {
1172+
case "Critical":
1173+
hasCritical = true
1174+
criticalAlrt["sli_threshold"] = condition.SLIThreshold
1175+
case "Warning":
1176+
hasWarning = true
1177+
warningAlrt["sli_threshold"] = condition.SLIThreshold
1178+
}
1179+
}
1180+
if !hasCritical {
1181+
delete(block, "critical")
1182+
}
1183+
if !hasWarning {
1184+
delete(block, "warning")
1185+
}
1186+
return block
1187+
}
1188+
1189+
func jsonToSloBurnRateConditionBlock(conditions []TriggerCondition) map[string]interface{} {
1190+
1191+
var criticalAlrt, warningAlrt = dict{}, dict{}
1192+
block := map[string]interface{}{}
1193+
1194+
block["critical"] = toSingletonArray(criticalAlrt)
1195+
block["warning"] = toSingletonArray(warningAlrt)
1196+
1197+
var hasCritical, hasWarning = false, false
1198+
for _, condition := range conditions {
1199+
switch condition.TriggerType {
1200+
case "Critical":
1201+
hasCritical = true
1202+
criticalAlrt["time_range"] = condition.TimeRange
1203+
criticalAlrt["burn_rate_threshold"] = condition.BurnRateThreshold
1204+
case "Warning":
1205+
hasWarning = true
1206+
warningAlrt["time_range"] = condition.TimeRange
1207+
warningAlrt["burn_rate_threshold"] = condition.BurnRateThreshold
1208+
}
1209+
}
1210+
if !hasCritical {
1211+
delete(block, "critical")
1212+
}
1213+
if !hasWarning {
1214+
delete(block, "warning")
1215+
}
1216+
return block
1217+
}
1218+
10751219
func jsonToLogsMissingDataConditionBlock(conditions []TriggerCondition) map[string]interface{} {
10761220
block := map[string]interface{}{}
10771221
firstCondition := conditions[0]
@@ -1087,19 +1231,23 @@ func jsonToMetricsMissingDataConditionBlock(conditions []TriggerCondition) map[s
10871231
return block
10881232
}
10891233

1090-
var logsStaticConditionFieldName = "logs_static_condition"
1091-
var metricsStaticConditionFieldName = "metrics_static_condition"
1092-
var logsOutlierConditionFieldName = "logs_outlier_condition"
1093-
var metricsOutlierConditionFieldName = "metrics_outlier_condition"
1094-
var logsMissingDataConditionFieldName = "logs_missing_data_condition"
1095-
var metricsMissingDataConditionFieldName = "metrics_missing_data_condition"
1096-
1097-
var logsStaticConditionDetectionMethod = "LogsStaticCondition"
1098-
var metricsStaticConditionDetectionMethod = "MetricsStaticCondition"
1099-
var logsOutlierConditionDetectionMethod = "LogsOutlierCondition"
1100-
var metricsOutlierConditionDetectionMethod = "MetricsOutlierCondition"
1101-
var logsMissingDataConditionDetectionMethod = "LogsMissingDataCondition"
1102-
var metricsMissingDataConditionDetectionMethod = "MetricsMissingDataCondition"
1234+
const logsStaticConditionFieldName = "logs_static_condition"
1235+
const metricsStaticConditionFieldName = "metrics_static_condition"
1236+
const logsOutlierConditionFieldName = "logs_outlier_condition"
1237+
const metricsOutlierConditionFieldName = "metrics_outlier_condition"
1238+
const logsMissingDataConditionFieldName = "logs_missing_data_condition"
1239+
const metricsMissingDataConditionFieldName = "metrics_missing_data_condition"
1240+
const sloSLIConditionFieldName = "slo_sli_condition"
1241+
const sloBurnRateConditionFieldName = "slo_burn_rate_condition"
1242+
1243+
const logsStaticConditionDetectionMethod = "LogsStaticCondition"
1244+
const metricsStaticConditionDetectionMethod = "MetricsStaticCondition"
1245+
const logsOutlierConditionDetectionMethod = "LogsOutlierCondition"
1246+
const metricsOutlierConditionDetectionMethod = "MetricsOutlierCondition"
1247+
const logsMissingDataConditionDetectionMethod = "LogsMissingDataCondition"
1248+
const metricsMissingDataConditionDetectionMethod = "MetricsMissingDataCondition"
1249+
const sloSLIConditionDetectionMethod = "SloSliCondition"
1250+
const sloBurnRateConditionDetectionMethod = "SloBurnRateCondition"
11031251

11041252
func getQueries(d *schema.ResourceData) []MonitorQuery {
11051253
rawQueries := d.Get("queries").([]interface{})
@@ -1149,6 +1297,7 @@ func resourceToMonitorsLibraryMonitor(d *schema.ResourceData) MonitorsLibraryMon
11491297
GroupNotifications: d.Get("group_notifications").(bool),
11501298
Playbook: d.Get("playbook").(string),
11511299
AlertName: d.Get("alert_name").(string),
1300+
SloID: d.Get("slo_id").(string),
11521301
}
11531302
}
11541303

@@ -1212,6 +1361,10 @@ func (condition *TriggerCondition) readFrom(block map[string]interface{}) {
12121361
condition.Consecutive = v.(int)
12131362
case "direction":
12141363
condition.Direction = v.(string)
1364+
case "sli_threshold":
1365+
condition.SLIThreshold = v.(float64)
1366+
case "burn_rate_threshold":
1367+
condition.BurnRateThreshold = v.(float64)
12151368
default:
12161369
}
12171370
}
@@ -1269,6 +1422,24 @@ func (base TriggerCondition) cloneReadingFromNestedBlocks(block map[string]inter
12691422
return conditions
12701423
}
12711424

1425+
// adapted version of cloneReadingFromNestedBlocks for slo conditions
1426+
func (base TriggerCondition) sloCloneReadingFromNestedBlocks(block map[string]interface{}) []TriggerCondition {
1427+
var conditions = []TriggerCondition{}
1428+
var criticalCondition, warningCondition = base, base
1429+
criticalCondition.TriggerType = "Critical"
1430+
warningCondition.TriggerType = "Warning"
1431+
1432+
if critical, ok := fromSingletonArray(block, "critical"); ok {
1433+
criticalCondition.readFrom(critical)
1434+
conditions = append(conditions, criticalCondition)
1435+
}
1436+
if warning, ok := fromSingletonArray(block, "warning"); ok {
1437+
warningCondition.readFrom(warning)
1438+
conditions = append(conditions, warningCondition)
1439+
}
1440+
return conditions
1441+
}
1442+
12721443
func toSingletonArray(m map[string]interface{}) []map[string]interface{} {
12731444
return []map[string]interface{}{m}
12741445
}

0 commit comments

Comments
 (0)