|
| 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 | + "golang.org/x/sys/unix" |
| 10 | + "os" |
| 11 | + "testing" |
| 12 | + "time" |
| 13 | +) |
| 14 | + |
| 15 | +// TestNotificationRoundTrip instructs an Icinga 2 node to send a notification back for further inspection. |
| 16 | +func TestNotificationRoundTrip(t *testing.T) { |
| 17 | + fileChFifo := "./tmp/file-fifo" |
| 18 | + oldUmask := unix.Umask(0) |
| 19 | + require.NoError(t, unix.Mkfifo(fileChFifo, 0666), "mkfifo") |
| 20 | + unix.Umask(oldUmask) |
| 21 | + |
| 22 | + rdb := getDatabase(t) |
| 23 | + notifications := it.IcingaNotificationsInstanceT(t, rdb) |
| 24 | + icinga := it.Icinga2NodeT(t, "master") |
| 25 | + icinga.EnableIcingaNotifications(notifications) |
| 26 | + require.NoError(t, icinga.Reload(), "icinga.Reload()") |
| 27 | + |
| 28 | + db, err := sqlx.Open(rdb.Driver(), rdb.DSN()) |
| 29 | + require.NoError(t, err, "SQL database open") |
| 30 | + defer func() { require.NoError(t, db.Close(), "db.Close") }() |
| 31 | + |
| 32 | + t.Run("configure channel in database", func(t *testing.T) { |
| 33 | + eventually.Require(t, func(t require.TestingT) { |
| 34 | + var channelCount int |
| 35 | + err := db.QueryRow(`SELECT COUNT(*) FROM available_channel_type WHERE type = 'file'`).Scan(&channelCount) |
| 36 | + require.NoError(t, err, "SQL SELECT FROM available_channel_type query") |
| 37 | + require.Equal(t, channelCount, 1, "file type missing from available_channel_type") |
| 38 | + }, 10*time.Second, time.Second) |
| 39 | + |
| 40 | + _, err := db.Exec(` |
| 41 | + INSERT INTO channel (id, name, type, config) |
| 42 | + VALUES (1, 'file-fifo', 'file', '{"path":"\/shared\/file-fifo"}'); |
| 43 | +
|
| 44 | + INSERT INTO contact (id, full_name, username, default_channel_id, color) |
| 45 | + VALUES (1, 'icingaadmin', 'icingaadmin', 1, '#000000'); |
| 46 | +
|
| 47 | + INSERT INTO rule (id, name, is_active) VALUES (1, 'file-fifo', 'y'); |
| 48 | + INSERT INTO rule_escalation (id, rule_id, position) VALUES (1, 1, 1); |
| 49 | + INSERT INTO rule_escalation_recipient (id, rule_escalation_id, contact_id, channel_id) VALUES (1, 1, 1, 1);`) |
| 50 | + require.NoError(t, err, "populating tables failed") |
| 51 | + }) |
| 52 | + |
| 53 | + t.Run("create icinga objects", func(t *testing.T) { |
| 54 | + client := icinga.ApiClient() |
| 55 | + client.CreateObject(t, "checkcommands", "failure-check", map[string]any{ |
| 56 | + "templates": []any{"plugin-check-command"}, |
| 57 | + "attrs": map[string]any{"command": []string{"/bin/false"}}, |
| 58 | + }) |
| 59 | + client.CreateHost(t, "test-host", map[string]any{ |
| 60 | + "attrs": map[string]any{"check_command": "failure-check"}, |
| 61 | + }) |
| 62 | + client.CreateService(t, "test-host", "test-service", map[string]any{ |
| 63 | + "attrs": map[string]any{"check_command": "failure-check"}, |
| 64 | + }) |
| 65 | + }) |
| 66 | + |
| 67 | + t.Run("read notification back from channel", func(t *testing.T) { |
| 68 | + f, err := os.Open(fileChFifo) |
| 69 | + require.NoErrorf(t, err, "opening %s for reading", fileChFifo) |
| 70 | + defer f.Close() |
| 71 | + |
| 72 | + notificationReqCh := make(chan *plugin.NotificationRequest) |
| 73 | + go func() { |
| 74 | + var req plugin.NotificationRequest |
| 75 | + require.NoError(t, json.NewDecoder(f).Decode(&req), "JSON decoding") |
| 76 | + notificationReqCh <- &req |
| 77 | + }() |
| 78 | + |
| 79 | + select { |
| 80 | + case req := <-notificationReqCh: |
| 81 | + require.Contains(t, req.Object.Name, "test-", "name must contain test prefix") |
| 82 | + |
| 83 | + case <-time.After(5 * time.Minute): |
| 84 | + require.Fail(t, "no notification was received") |
| 85 | + } |
| 86 | + }) |
| 87 | +} |
0 commit comments