Skip to content

Commit 93bc871

Browse files
authored
Merge pull request #482 from SumoLogic/SUMO-207948-monitor-custom-resolution-payload-support
SUMO-207948, Add support to customize resolution payload on monitors
2 parents b59b0ce + 9a74b5a commit 93bc871

9 files changed

+228
-35
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
## 2.21.1 (Unreleased)
2+
FEATURES:
3+
* Add new optional `resolution_payload` field to connection resource and `resolution_payload_override` field to notifications section of monitor resource (GH-482)
24

35
## 2.21.0 (February 27, 2023)
46
FEATURES:

sumologic/resource_sumologic_connection.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ func resourceSumologicConnection() *schema.Resource {
8282
Optional: true,
8383
ValidateFunc: validation.StringInSlice([]string{"Incident", "Event"}, false),
8484
},
85+
"resolution_payload": {
86+
Type: schema.TypeString,
87+
Optional: true,
88+
ValidateFunc: validation.StringIsJSON,
89+
Computed: true,
90+
},
8591
},
8692
}
8793
}
@@ -137,6 +143,7 @@ func resourceSumologicConnectionRead(d *schema.ResourceData, meta interface{}) e
137143
return fmt.Errorf("error setting custom headers for resource %s: %s", d.Id(), err)
138144
}
139145
d.Set("default_payload", connection.DefaultPayload)
146+
d.Set("resolution_payload", connection.ResolutionPayload)
140147
d.Set("webhook_type", connection.WebhookType)
141148
d.Set("connection_subtype", connection.ConnectionSubtype)
142149
d.SetId(connection.ID)
@@ -203,6 +210,7 @@ func resourceToConnection(d *schema.ResourceData) Connection {
203210
connection.Headers = mapToHeaders(d.Get("headers").(map[string]interface{}))
204211
connection.CustomHeaders = mapToHeaders(d.Get("custom_headers").(map[string]interface{}))
205212
connection.DefaultPayload = d.Get("default_payload").(string)
213+
connection.ResolutionPayload = d.Get("resolution_payload").(string)
206214
connection.WebhookType = d.Get("webhook_type").(string)
207215
connection.ConnectionSubtype = d.Get("connection_subtype").(string)
208216

@@ -236,6 +244,7 @@ func printConnection(connection Connection) {
236244
log.Printf("Headers: %s", connection.Headers)
237245
log.Printf("CustomHeaders: %s", connection.CustomHeaders)
238246
log.Printf("DefaultPayload: %s", connection.DefaultPayload)
247+
log.Printf("ResolutionPayload: %s", connection.ResolutionPayload)
239248
log.Printf("WebhookType: %s", connection.WebhookType)
240249
log.Printf("ConnectionSubtype: %s", connection.ConnectionSubtype)
241250
}

sumologic/resource_sumologic_connection_test.go

Lines changed: 63 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ func TestAccConnection_create(t *testing.T) {
1616
description := acctest.RandomWithPrefix("tf-connection-test-description")
1717
url := "https://example.com"
1818
defaultPayload := "{\"eventType\" : \"{{Name}}\"}"
19+
resolutionPayload := "{\"eventType\" : \"{{Name}}\"}"
1920
webhookType := "Webhook"
2021

2122
var connection Connection
@@ -26,7 +27,7 @@ func TestAccConnection_create(t *testing.T) {
2627
CheckDestroy: testAccCheckConnectionDestroy,
2728
Steps: []resource.TestStep{
2829
{
29-
Config: createConnectionConfig(name, connectionType, description, url, webhookType, defaultPayload),
30+
Config: createConnectionConfig(name, connectionType, description, url, webhookType, defaultPayload, resolutionPayload),
3031
Check: resource.ComposeTestCheckFunc(
3132
testAccCheckConnectionExists("sumologic_connection.test", &connection, t),
3233
testAccCheckConnectionAttributes("sumologic_connection.test"),
@@ -35,6 +36,7 @@ func TestAccConnection_create(t *testing.T) {
3536
resource.TestCheckResourceAttr("sumologic_connection.test", "description", description),
3637
resource.TestCheckResourceAttr("sumologic_connection.test", "url", url),
3738
resource.TestCheckResourceAttr("sumologic_connection.test", "default_payload", defaultPayload+"\n"),
39+
resource.TestCheckResourceAttr("sumologic_connection.test", "resolution_payload", resolutionPayload+"\n"),
3840
resource.TestCheckResourceAttr("sumologic_connection.test", "webhook_type", webhookType),
3941
),
4042
},
@@ -48,6 +50,7 @@ func TestAccConnection_createServiceNowWebhook(t *testing.T) {
4850
description := acctest.RandomWithPrefix("tf-servicenow-webhook-connection-test-description")
4951
url := "https://example.com"
5052
defaultPayload := "{\"eventType\" : \"{{Name}}\"}"
53+
resolutionPayload := "{\n \"sys_id\": \"{{SysId}}\",\n \"state\": \"6\",\n \"incident_state\": \"6\",\n \"work_notes\": \"Resolved value - Test\"\n}"
5154
webhookType := "ServiceNow"
5255
connectionSubtype := "Incident"
5356

@@ -59,7 +62,8 @@ func TestAccConnection_createServiceNowWebhook(t *testing.T) {
5962
CheckDestroy: testAccCheckConnectionDestroy,
6063
Steps: []resource.TestStep{
6164
{
62-
Config: createServiceNowWebhookConnectionConfig(name, connectionType, description, url, connectionSubtype, defaultPayload),
65+
Config: createServiceNowWebhookConnectionConfigWithResolutionPayload(name, connectionType, description, url,
66+
connectionSubtype, defaultPayload, resolutionPayload),
6367
Check: resource.ComposeTestCheckFunc(
6468
testAccCheckConnectionExists("sumologic_connection.serviceNowTest", &connection, t),
6569
testAccCheckConnectionAttributes("sumologic_connection.serviceNowTest"),
@@ -68,6 +72,7 @@ func TestAccConnection_createServiceNowWebhook(t *testing.T) {
6872
resource.TestCheckResourceAttr("sumologic_connection.serviceNowTest", "description", description),
6973
resource.TestCheckResourceAttr("sumologic_connection.serviceNowTest", "url", url),
7074
resource.TestCheckResourceAttr("sumologic_connection.serviceNowTest", "default_payload", defaultPayload+"\n"),
75+
resource.TestCheckResourceAttr("sumologic_connection.serviceNowTest", "resolution_payload", resolutionPayload+"\n"),
7176
resource.TestCheckResourceAttr("sumologic_connection.serviceNowTest", "webhook_type", webhookType),
7277
resource.TestCheckResourceAttr("sumologic_connection.serviceNowTest", "connection_subtype", connectionSubtype),
7378
),
@@ -79,41 +84,48 @@ func TestAccConnection_createServiceNowWebhook(t *testing.T) {
7984
func TestAccConnection_update(t *testing.T) {
8085
var connection Connection
8186
connectionType := "WebhookConnection"
82-
name := acctest.RandomWithPrefix("tf-connection-test-name")
87+
name := acctest.RandomWithPrefix("tf-servicenow-webhook-connection-test-name")
88+
description := acctest.RandomWithPrefix("tf-connection-test-description")
8389
url := "https://example.com"
84-
defaultPayload := `{"eventType" : "{{Name}}"}`
85-
webhookType := "Webhook"
86-
fDescription := acctest.RandomWithPrefix("tf-connection-test-description")
87-
sDescription := acctest.RandomWithPrefix("tf-connection-test-description")
90+
defaultPayload := "{\"eventType\" : \"{{Name}}\"}"
91+
webhookType := "ServiceNow"
92+
connectionSubtype := "Incident"
93+
94+
updatedDefaultPayload := `{"eventType" : "{{Name}} default updated"}`
95+
updatedResolutionPayload := "{\n \"sys_id\": \"{{SysId}}\",\n \"state\": \"6\",\n \"incident_state\": \"6\",\n \"work_notes\": \"Resolved value - Test\"\n}"
8896

8997
resource.Test(t, resource.TestCase{
9098
PreCheck: func() { testAccPreCheck(t) },
9199
Providers: testAccProviders,
92100
CheckDestroy: testAccCheckConnectionDestroy,
93101
Steps: []resource.TestStep{
94102
{
95-
Config: createConnectionConfig(name, connectionType, fDescription, url, webhookType, defaultPayload),
103+
Config: createServiceNowWebhookConnectionConfig(name, connectionType, description, url, connectionSubtype, defaultPayload),
96104
Check: resource.ComposeTestCheckFunc(
97-
testAccCheckConnectionExists("sumologic_connection.test", &connection, t),
98-
testAccCheckConnectionAttributes("sumologic_connection.test"),
99-
resource.TestCheckResourceAttr("sumologic_connection.test", "type", connectionType),
100-
resource.TestCheckResourceAttr("sumologic_connection.test", "name", name),
101-
resource.TestCheckResourceAttr("sumologic_connection.test", "description", fDescription),
102-
resource.TestCheckResourceAttr("sumologic_connection.test", "url", url),
103-
resource.TestCheckResourceAttr("sumologic_connection.test", "default_payload", defaultPayload+"\n"),
104-
resource.TestCheckResourceAttr("sumologic_connection.test", "webhook_type", webhookType),
105+
testAccCheckConnectionExists("sumologic_connection.serviceNowTest", &connection, t),
106+
testAccCheckConnectionAttributes("sumologic_connection.serviceNowTest"),
107+
resource.TestCheckResourceAttr("sumologic_connection.serviceNowTest", "type", connectionType),
108+
resource.TestCheckResourceAttr("sumologic_connection.serviceNowTest", "name", name),
109+
resource.TestCheckResourceAttr("sumologic_connection.serviceNowTest", "description", description),
110+
resource.TestCheckResourceAttr("sumologic_connection.serviceNowTest", "url", url),
111+
resource.TestCheckResourceAttr("sumologic_connection.serviceNowTest", "default_payload", defaultPayload+"\n"),
112+
resource.TestCheckResourceAttr("sumologic_connection.serviceNowTest", "webhook_type", webhookType),
113+
resource.TestCheckResourceAttr("sumologic_connection.serviceNowTest", "connection_subtype", connectionSubtype),
105114
),
106115
}, {
107-
Config: createConnectionConfig(name, connectionType, sDescription, url, webhookType, defaultPayload),
116+
Config: createServiceNowWebhookConnectionConfigWithResolutionPayload(name, connectionType, description, url, connectionSubtype,
117+
updatedDefaultPayload, updatedResolutionPayload),
108118
Check: resource.ComposeTestCheckFunc(
109-
testAccCheckConnectionExists("sumologic_connection.test", &connection, t),
110-
testAccCheckConnectionAttributes("sumologic_connection.test"),
111-
resource.TestCheckResourceAttr("sumologic_connection.test", "type", connectionType),
112-
resource.TestCheckResourceAttr("sumologic_connection.test", "name", name),
113-
resource.TestCheckResourceAttr("sumologic_connection.test", "description", sDescription),
114-
resource.TestCheckResourceAttr("sumologic_connection.test", "url", url),
115-
resource.TestCheckResourceAttr("sumologic_connection.test", "default_payload", defaultPayload+"\n"),
116-
resource.TestCheckResourceAttr("sumologic_connection.test", "webhook_type", webhookType),
119+
testAccCheckConnectionExists("sumologic_connection.serviceNowTest", &connection, t),
120+
testAccCheckConnectionAttributes("sumologic_connection.serviceNowTest"),
121+
resource.TestCheckResourceAttr("sumologic_connection.serviceNowTest", "type", connectionType),
122+
resource.TestCheckResourceAttr("sumologic_connection.serviceNowTest", "name", name),
123+
resource.TestCheckResourceAttr("sumologic_connection.serviceNowTest", "description", description),
124+
resource.TestCheckResourceAttr("sumologic_connection.serviceNowTest", "url", url),
125+
resource.TestCheckResourceAttr("sumologic_connection.serviceNowTest", "default_payload", updatedDefaultPayload+"\n"),
126+
resource.TestCheckResourceAttr("sumologic_connection.serviceNowTest", "resolution_payload", updatedResolutionPayload+"\n"),
127+
resource.TestCheckResourceAttr("sumologic_connection.serviceNowTest", "webhook_type", webhookType),
128+
resource.TestCheckResourceAttr("sumologic_connection.serviceNowTest", "connection_subtype", connectionSubtype),
117129
),
118130
},
119131
},
@@ -171,7 +183,7 @@ func testAccCheckConnectionDestroy(s *terraform.State) error {
171183
return nil
172184
}
173185

174-
func createConnectionConfig(name, connectionType, desc, url, webhookType, defaultPayload string) string {
186+
func createConnectionConfig(name, connectionType, desc, url, webhookType, defaultPayload string, resolutionPayload string) string {
175187
return fmt.Sprintf(`
176188
resource "sumologic_connection" "test" {
177189
name = "%s"
@@ -181,9 +193,12 @@ resource "sumologic_connection" "test" {
181193
webhook_type = "%s"
182194
default_payload = <<JSON
183195
%s
196+
JSON
197+
resolution_payload = <<JSON
198+
%s
184199
JSON
185200
}
186-
`, name, connectionType, desc, url, webhookType, defaultPayload)
201+
`, name, connectionType, desc, url, webhookType, defaultPayload, resolutionPayload)
187202
}
188203

189204
func createServiceNowWebhookConnectionConfig(name, connectionType, desc, url, connectionSubtype, defaultPayload string) string {
@@ -204,3 +219,24 @@ JSON
204219
}
205220
`, name, connectionType, desc, url, connectionSubtype, defaultPayload)
206221
}
222+
func createServiceNowWebhookConnectionConfigWithResolutionPayload(name, connectionType, desc, url, connectionSubtype, defaultPayload string, resolutionPayload string) string {
223+
return fmt.Sprintf(`
224+
resource "sumologic_connection" "serviceNowTest" {
225+
name = "%s"
226+
type = "%s"
227+
description = "%s"
228+
url = "%s"
229+
headers = {
230+
"Authorization": "Basic SOMERANDOMAUTHSTRING"
231+
}
232+
webhook_type = "ServiceNow"
233+
connection_subtype = "%s"
234+
default_payload = <<JSON
235+
%s
236+
JSON
237+
resolution_payload = <<JSON
238+
%s
239+
JSON
240+
}
241+
`, name, connectionType, desc, url, connectionSubtype, defaultPayload, resolutionPayload)
242+
}

sumologic/resource_sumologic_monitors_library_monitor.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,11 @@ func resourceSumologicMonitorsLibraryMonitor() *schema.Resource {
267267
Optional: true,
268268
ValidateFunc: validation.StringIsJSON,
269269
},
270+
"resolution_payload_override": {
271+
Type: schema.TypeString,
272+
Optional: true,
273+
ValidateFunc: validation.StringIsJSON,
274+
},
270275
},
271276
},
272277
},
@@ -744,6 +749,9 @@ func resourceSumologicMonitorsLibraryMonitorRead(d *schema.ResourceData, meta in
744749
if internalNotificationDict["payloadOverride"] != nil {
745750
internalNotification["payload_override"] = internalNotificationDict["payloadOverride"].(string)
746751
}
752+
if internalNotificationDict["resolutionPayloadOverride"] != nil {
753+
internalNotification["resolution_payload_override"] = internalNotificationDict["resolutionPayloadOverride"].(string)
754+
}
747755
}
748756

749757
schemaInternalNotification := []interface{}{
@@ -911,10 +919,11 @@ func getNotifications(d *schema.ResourceData) []MonitorNotification {
911919
}
912920
} else {
913921
n.Notification = WebhookNotificiation{
914-
ActionType: "NamedConnectionAction",
915-
ConnectionType: connectionType,
916-
ConnectionID: notificationActionDict["connection_id"].(string),
917-
PayloadOverride: notificationActionDict["payload_override"].(string),
922+
ActionType: "NamedConnectionAction",
923+
ConnectionType: connectionType,
924+
ConnectionID: notificationActionDict["connection_id"].(string),
925+
PayloadOverride: notificationActionDict["payload_override"].(string),
926+
ResolutionPayloadOverride: notificationActionDict["resolution_payload_override"].(string),
918927
}
919928
}
920929
n.RunForTriggerTypes = notificationDict["run_for_trigger_types"].([]interface{})

sumologic/resource_sumologic_monitors_library_monitor_test.go

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,42 @@ func TestAccSumologicMonitorsLibraryMonitor_folder_update(t *testing.T) {
612612
})
613613
}
614614

615+
func TestAccSumologicMonitorsLibraryMonitor_override_payload(t *testing.T) {
616+
var monitorsLibraryMonitor MonitorsLibraryMonitor
617+
testNameSuffix := acctest.RandString(16)
618+
619+
testName := "terraform_test_monitor_connection_" + testNameSuffix
620+
testType := "MonitorsLibraryMonitor"
621+
testMonitorType := "Logs"
622+
defaultPayload := "{\"eventType\" : \"{{Name}}\"}"
623+
resolutionPayload := "{\"eventType\" : \"{{Name}}\"}"
624+
625+
overrideDefaultPayload := "{\"eventType\" : \"{{Name}}-update\"}"
626+
overrideResolutionPayload := "{\"eventType\" : \"{{Name}}-update\"}"
627+
628+
resource.Test(t, resource.TestCase{
629+
PreCheck: func() { testAccPreCheck(t) },
630+
Providers: testAccProviders,
631+
CheckDestroy: testAccCheckMonitorsLibraryMonitorDestroy(monitorsLibraryMonitor),
632+
//destroy conection too
633+
Steps: []resource.TestStep{
634+
{
635+
Config: testAccSumologicMonitorsLibraryMonitorUpdateConection(testNameSuffix, defaultPayload, resolutionPayload,
636+
overrideDefaultPayload, overrideResolutionPayload),
637+
Check: resource.ComposeTestCheckFunc(
638+
testAccCheckMonitorsLibraryMonitorExists("sumologic_monitor.test_monitor_connection", &monitorsLibraryMonitor, t),
639+
testAccCheckMonitorsLibraryMonitorAttributes("sumologic_monitor.test_monitor_connection"),
640+
resource.TestCheckResourceAttr("sumologic_monitor.test_monitor_connection", "monitor_type", testMonitorType),
641+
resource.TestCheckResourceAttr("sumologic_monitor.test_monitor_connection", "name", testName),
642+
resource.TestCheckResourceAttr("sumologic_monitor.test_monitor_connection", "type", testType),
643+
resource.TestCheckResourceAttr("sumologic_monitor.test_monitor_connection", "notifications.0.notification.0.payload_override", overrideDefaultPayload+"\n"),
644+
resource.TestCheckResourceAttr("sumologic_monitor.test_monitor_connection", "notifications.0.notification.0.resolution_payload_override", overrideResolutionPayload+"\n"),
645+
),
646+
},
647+
},
648+
})
649+
}
650+
615651
func testAccCheckMonitorsLibraryMonitorFolderMatch(monitorName string, folderName string, t *testing.T) resource.TestCheckFunc {
616652
return func(s *terraform.State) error {
617653
//fetching monitor information
@@ -913,6 +949,87 @@ resource "sumologic_role" "tf_test_role_01" {
913949
}`, testName, testName)
914950
}
915951

952+
func testAccSumologicMonitorsLibraryMonitorUpdateConection(testName string, defaultPayload string, resolutionPayload string,
953+
overrideDefaultPayload string, overrideResolutionPayload string) string {
954+
return fmt.Sprintf(`
955+
resource "sumologic_connection" "connection_01" {
956+
name = "%s"
957+
type = "WebhookConnection"
958+
description = "WebhookConnection"
959+
url = "https://example.com"
960+
webhook_type = "Webhook"
961+
default_payload = <<JSON
962+
%s
963+
JSON
964+
resolution_payload = <<JSON
965+
%s
966+
JSON
967+
}
968+
969+
resource "sumologic_monitor" "test_monitor_connection" {
970+
name = "terraform_test_monitor_connection_%s"
971+
description = "terraform_test_monitor_connection"
972+
type = "MonitorsLibraryMonitor"
973+
is_disabled = true
974+
content_type = "Monitor"
975+
monitor_type = "Logs"
976+
evaluation_delay = "8m"
977+
queries {
978+
row_id = "A"
979+
query = "_sourceCategory=monitor-manager info"
980+
}
981+
triggers {
982+
threshold_type = "GreaterThan"
983+
threshold = 40.0
984+
time_range = "30m"
985+
occurrence_type = "ResultCount"
986+
trigger_source = "AllResults"
987+
trigger_type = "Critical"
988+
detection_method = "StaticCondition"
989+
}
990+
triggers {
991+
threshold_type = "LessThanOrEqual"
992+
threshold = 40.0
993+
time_range = "30m"
994+
occurrence_type = "ResultCount"
995+
trigger_source = "AllResults"
996+
trigger_type = "ResolvedCritical"
997+
detection_method = "StaticCondition"
998+
resolution_window = "15m"
999+
}
1000+
notifications {
1001+
notification {
1002+
connection_type = "Webhook"
1003+
connection_id = sumologic_connection.connection_01.id
1004+
payload_override = <<JSON
1005+
%s
1006+
JSON
1007+
resolution_payload_override = <<JSON
1008+
%s
1009+
JSON
1010+
}
1011+
run_for_trigger_types = ["Critical", "ResolvedCritical"]
1012+
}
1013+
playbook = "This is an updated test playbook"
1014+
alert_name = "Updated Alert from {{Name}}"
1015+
1016+
obj_permission {
1017+
subject_type = "role"
1018+
subject_id = sumologic_role.tf_test_role_01.id
1019+
permissions = ["Read","Update"]
1020+
}
1021+
}
1022+
resource "sumologic_role" "tf_test_role_01" {
1023+
name = "tf_test_role_01_%s"
1024+
description = "Testing resource sumologic_role"
1025+
capabilities = [
1026+
"viewAlerts",
1027+
"viewMonitorsV2",
1028+
"manageMonitorsV2"
1029+
]
1030+
}`, testName, defaultPayload, resolutionPayload, testName, overrideDefaultPayload, overrideResolutionPayload, testName)
1031+
}
1032+
9161033
func testAccEmulateFGPDriftingMonitor(
9171034
t *testing.T,
9181035
// expectedFGPFunc func(*terraform.State, string) ([]CmfFgpPermStatement, error),

sumologic/sumologic_client.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,7 @@ type Connection struct {
447447
DefaultPayload string `json:"defaultPayload"`
448448
WebhookType string `json:"webhookType"`
449449
ConnectionSubtype string `json:"connectionSubtype,omitempty"`
450+
ResolutionPayload string `json:"resolutionPayload,omitempty"`
450451
}
451452

452453
// Headers is used to describe headers for http requests.

0 commit comments

Comments
 (0)