|
| 1 | +package notifications_test |
| 2 | + |
| 3 | +import ( |
| 4 | + "encoding/json" |
| 5 | + "github.com/icinga/icinga-notifications/pkg/plugin" |
| 6 | + "github.com/icinga/icinga-testing/utils/eventually" |
| 7 | + "github.com/jmoiron/sqlx" |
| 8 | + "github.com/stretchr/testify/require" |
| 9 | + "net/http" |
| 10 | + "testing" |
| 11 | + "time" |
| 12 | +) |
| 13 | + |
| 14 | +// TestNotificationRoundTrip instructs an Icinga 2 node to send a notification back for further inspection. |
| 15 | +func TestNotificationRoundTrip(t *testing.T) { |
| 16 | + rdb := getDatabase(t) |
| 17 | + notifications := it.IcingaNotificationsInstanceT(t, rdb) |
| 18 | + icinga := it.Icinga2NodeT(t, "master") |
| 19 | + icinga.EnableIcingaNotifications(notifications) |
| 20 | + require.NoError(t, icinga.Reload(), "icinga.Reload()") |
| 21 | + |
| 22 | + db, err := sqlx.Open(rdb.Driver(), rdb.DSN()) |
| 23 | + require.NoError(t, err, "SQL database open") |
| 24 | + defer func() { require.NoError(t, db.Close(), "db.Cleanup") }() |
| 25 | + |
| 26 | + webhookRec := it.IcingaNotificationsWebhookReceiverInstanceT(t) |
| 27 | + webhookRecReqCh := make(chan plugin.NotificationRequest) |
| 28 | + webhookRec.Handler = func(writer http.ResponseWriter, request *http.Request) { |
| 29 | + var notReq plugin.NotificationRequest |
| 30 | + require.NoError(t, json.NewDecoder(request.Body).Decode(¬Req), "decoding NotificationRequest from request body") |
| 31 | + require.NoError(t, request.Body.Close(), "closing request body") |
| 32 | + webhookRecReqCh <- notReq |
| 33 | + http.Error(writer, "forwarded", http.StatusOK) |
| 34 | + } |
| 35 | + |
| 36 | + t.Run("configure channel in database", func(t *testing.T) { |
| 37 | + eventually.Require(t, func(t require.TestingT) { |
| 38 | + var channelCount int |
| 39 | + err := db.QueryRow(`SELECT COUNT(*) FROM available_channel_type WHERE type = 'webhook'`).Scan(&channelCount) |
| 40 | + require.NoError(t, err, "SQL SELECT FROM available_channel_type query") |
| 41 | + require.Equal(t, 1, channelCount, "webhook type missing from available_channel_type") |
| 42 | + }, 10*time.Second, time.Second) |
| 43 | + |
| 44 | + _, err := db.Exec(` |
| 45 | + INSERT INTO channel (id, name, type, config) |
| 46 | + VALUES (1, 'webhook', 'webhook', '{"method":"POST","url_template":"http:\/\/` + webhookRec.ListenAddr + `\/","request_body_template":"{{json .}}"}'); |
| 47 | +
|
| 48 | + INSERT INTO contact (id, full_name, username, default_channel_id, color) |
| 49 | + VALUES (1, 'icingaadmin', 'icingaadmin', 1, '#000000'); |
| 50 | +
|
| 51 | + INSERT INTO rule (id, name, is_active) VALUES (1, 'webhook', 'y'); |
| 52 | + INSERT INTO rule_escalation (id, rule_id, position) VALUES (1, 1, 1); |
| 53 | + INSERT INTO rule_escalation_recipient (id, rule_escalation_id, contact_id, channel_id) VALUES (1, 1, 1, 1);`) |
| 54 | + require.NoError(t, err, "populating tables failed") |
| 55 | + }) |
| 56 | + |
| 57 | + t.Run("create icinga objects", func(t *testing.T) { |
| 58 | + client := icinga.ApiClient() |
| 59 | + client.CreateObject(t, "checkcommands", "failure-check", map[string]any{ |
| 60 | + "templates": []any{"plugin-check-command"}, |
| 61 | + "attrs": map[string]any{"command": []string{"/bin/false"}}, |
| 62 | + }) |
| 63 | + client.CreateHost(t, "test-host", map[string]any{ |
| 64 | + "attrs": map[string]any{"check_command": "failure-check"}, |
| 65 | + }) |
| 66 | + client.CreateService(t, "test-host", "test-service", map[string]any{ |
| 67 | + "attrs": map[string]any{"check_command": "failure-check"}, |
| 68 | + }) |
| 69 | + }) |
| 70 | + |
| 71 | + t.Run("read notification back from channel", func(t *testing.T) { |
| 72 | + select { |
| 73 | + case notReq := <-webhookRecReqCh: |
| 74 | + require.Contains(t, notReq.Object.Name, "test-", "object name must contain test prefix") |
| 75 | + |
| 76 | + case <-time.After(5 * time.Minute): |
| 77 | + require.Fail(t, "no notification was received") |
| 78 | + } |
| 79 | + }) |
| 80 | +} |
0 commit comments