mirror of
https://github.com/google/alertmanager-irc-relay.git
synced 2025-02-17 06:00:44 +01:00
s/notice/msg/
Use a more generic name as there is soon going to be support for PRIVMSG (see https://github.com/google/alertmanager-irc-relay/pull/1 for background). This introduces a backward-incompatible change in the config file for these two parameters: - notice_template -> msg_template - notice_once_per_alert_group -> msg_once_per_alert_group I am not introducing the new parameters with a deprecation plan since both parameters are relatively secondary to the core functioning of the bot (and this is a free time project after all). Signed-off-by: Luca Bigliardi <shammash@google.com>
This commit is contained in:
parent
581677b635
commit
4e1aeaf931
14
README.md
14
README.md
@ -36,7 +36,7 @@ irc_realname: myrealname
|
|||||||
# Optionally pre-join certain channels.
|
# Optionally pre-join certain channels.
|
||||||
#
|
#
|
||||||
# Note: If an alert is sent to a non # pre-joined channel the bot will join
|
# Note: If an alert is sent to a non # pre-joined channel the bot will join
|
||||||
# that channel anyway before sending the notice. Of course this cannot work
|
# that channel anyway before sending the message. Of course this cannot work
|
||||||
# with password-protected channels.
|
# with password-protected channels.
|
||||||
irc_channels:
|
irc_channels:
|
||||||
- name: "#mychannel"
|
- name: "#mychannel"
|
||||||
@ -45,16 +45,16 @@ irc_channels:
|
|||||||
|
|
||||||
# Define how IRC messages should be sent.
|
# Define how IRC messages should be sent.
|
||||||
#
|
#
|
||||||
# Send only one notice when webhook data is received.
|
# Send only one message when webhook data is received.
|
||||||
# Note: By default a notice is sent for each alert in the webhook data.
|
# Note: By default a message is sent for each alert in the webhook data.
|
||||||
notice_once_per_alert_group: no
|
msg_once_per_alert_group: no
|
||||||
|
|
||||||
# Define how IRC messages should be formatted.
|
# Define how IRC messages should be formatted.
|
||||||
#
|
#
|
||||||
# The formatting is based on golang's text/template .
|
# The formatting is based on golang's text/template .
|
||||||
notice_template: "Alert {{ .Labels.alertname }} on {{ .Labels.instance }} is {{ .Status }}"
|
msg_template: "Alert {{ .Labels.alertname }} on {{ .Labels.instance }} is {{ .Status }}"
|
||||||
# Note: When sending only one notice per alert group the default
|
# Note: When sending only one message per alert group the default
|
||||||
# notice_template is set to
|
# msg_template is set to
|
||||||
# "Alert {{ .GroupLabels.alertname }} for {{ .GroupLabels.job }} is {{ .Status }}"
|
# "Alert {{ .GroupLabels.alertname }} for {{ .GroupLabels.job }} is {{ .Status }}"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
36
config.go
36
config.go
@ -20,8 +20,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultNoticeOnceTemplate = "Alert {{ .GroupLabels.alertname }} for {{ .GroupLabels.job }} is {{ .Status }}"
|
defaultMsgOnceTemplate = "Alert {{ .GroupLabels.alertname }} for {{ .GroupLabels.job }} is {{ .Status }}"
|
||||||
defaultNoticeTemplate = "Alert {{ .Labels.alertname }} on {{ .Labels.instance }} is {{ .Status }}"
|
defaultMsgTemplate = "Alert {{ .Labels.alertname }} on {{ .Labels.instance }} is {{ .Status }}"
|
||||||
)
|
)
|
||||||
|
|
||||||
type IRCChannel struct {
|
type IRCChannel struct {
|
||||||
@ -30,17 +30,17 @@ type IRCChannel struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
HTTPHost string `yaml:"http_host"`
|
HTTPHost string `yaml:"http_host"`
|
||||||
HTTPPort int `yaml:"http_port"`
|
HTTPPort int `yaml:"http_port"`
|
||||||
IRCNick string `yaml:"irc_nickname"`
|
IRCNick string `yaml:"irc_nickname"`
|
||||||
IRCNickPass string `yaml:"irc_nickname_password"`
|
IRCNickPass string `yaml:"irc_nickname_password"`
|
||||||
IRCRealName string `yaml:"irc_realname"`
|
IRCRealName string `yaml:"irc_realname"`
|
||||||
IRCHost string `yaml:"irc_host"`
|
IRCHost string `yaml:"irc_host"`
|
||||||
IRCPort int `yaml:"irc_port"`
|
IRCPort int `yaml:"irc_port"`
|
||||||
IRCUseSSL bool `yaml:"irc_use_ssl"`
|
IRCUseSSL bool `yaml:"irc_use_ssl"`
|
||||||
IRCChannels []IRCChannel `yaml:"irc_channels"`
|
IRCChannels []IRCChannel `yaml:"irc_channels"`
|
||||||
NoticeTemplate string `yaml:"notice_template"`
|
MsgTemplate string `yaml:"msg_template"`
|
||||||
NoticeOnce bool `yaml:"notice_once_per_alert_group"`
|
MsgOnce bool `yaml:"msg_once_per_alert_group"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadConfig(configFile string) (*Config, error) {
|
func LoadConfig(configFile string) (*Config, error) {
|
||||||
@ -54,7 +54,7 @@ func LoadConfig(configFile string) (*Config, error) {
|
|||||||
IRCPort: 7000,
|
IRCPort: 7000,
|
||||||
IRCUseSSL: true,
|
IRCUseSSL: true,
|
||||||
IRCChannels: []IRCChannel{IRCChannel{Name: "#airtest"}},
|
IRCChannels: []IRCChannel{IRCChannel{Name: "#airtest"}},
|
||||||
NoticeOnce: false,
|
MsgOnce: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
if configFile != "" {
|
if configFile != "" {
|
||||||
@ -68,11 +68,11 @@ func LoadConfig(configFile string) (*Config, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set default template if config does not have one.
|
// Set default template if config does not have one.
|
||||||
if config.NoticeTemplate == "" {
|
if config.MsgTemplate == "" {
|
||||||
if config.NoticeOnce {
|
if config.MsgOnce {
|
||||||
config.NoticeTemplate = defaultNoticeOnceTemplate
|
config.MsgTemplate = defaultMsgOnceTemplate
|
||||||
} else {
|
} else {
|
||||||
config.NoticeTemplate = defaultNoticeTemplate
|
config.MsgTemplate = defaultMsgTemplate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,15 +34,15 @@ func TestNoConfig(t *testing.T) {
|
|||||||
|
|
||||||
func TestLoadGoodConfig(t *testing.T) {
|
func TestLoadGoodConfig(t *testing.T) {
|
||||||
expectedConfig := &Config{
|
expectedConfig := &Config{
|
||||||
HTTPHost: "test.web",
|
HTTPHost: "test.web",
|
||||||
HTTPPort: 8888,
|
HTTPPort: 8888,
|
||||||
IRCNick: "foo",
|
IRCNick: "foo",
|
||||||
IRCHost: "irc.example.com",
|
IRCHost: "irc.example.com",
|
||||||
IRCPort: 1234,
|
IRCPort: 1234,
|
||||||
IRCUseSSL: true,
|
IRCUseSSL: true,
|
||||||
IRCChannels: []IRCChannel{IRCChannel{Name: "#foobar"}},
|
IRCChannels: []IRCChannel{IRCChannel{Name: "#foobar"}},
|
||||||
NoticeTemplate: defaultNoticeTemplate,
|
MsgTemplate: defaultMsgTemplate,
|
||||||
NoticeOnce: false,
|
MsgOnce: false,
|
||||||
}
|
}
|
||||||
expectedData, err := yaml.Marshal(expectedConfig)
|
expectedData, err := yaml.Marshal(expectedConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -110,15 +110,15 @@ func TestLoadBadConfig(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNoticeOnceDefaultTemplate(t *testing.T) {
|
func TestMsgOnceDefaultTemplate(t *testing.T) {
|
||||||
tmpfile, err := ioutil.TempFile("", "airtesttemmplateonceconfig")
|
tmpfile, err := ioutil.TempFile("", "airtesttemmplateonceconfig")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Could not create tmpfile for testing: %s", err)
|
t.Errorf("Could not create tmpfile for testing: %s", err)
|
||||||
}
|
}
|
||||||
defer os.Remove(tmpfile.Name())
|
defer os.Remove(tmpfile.Name())
|
||||||
|
|
||||||
noticeOnceConfigData := []byte("notice_once_per_alert_group: yes")
|
msgOnceConfigData := []byte("msg_once_per_alert_group: yes")
|
||||||
if _, err := tmpfile.Write(noticeOnceConfigData); err != nil {
|
if _, err := tmpfile.Write(msgOnceConfigData); err != nil {
|
||||||
t.Errorf("Could not write test data in tmpfile: %s", err)
|
t.Errorf("Could not write test data in tmpfile: %s", err)
|
||||||
}
|
}
|
||||||
tmpfile.Close()
|
tmpfile.Close()
|
||||||
@ -128,12 +128,12 @@ func TestNoticeOnceDefaultTemplate(t *testing.T) {
|
|||||||
t.Errorf("Expected a config, got: %s", err)
|
t.Errorf("Expected a config, got: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.NoticeTemplate != defaultNoticeOnceTemplate {
|
if config.MsgTemplate != defaultMsgOnceTemplate {
|
||||||
t.Errorf("Expecting defaultNoticeOnceTemplate when NoticeOnce is true")
|
t.Errorf("Expecting defaultMsgOnceTemplate when MsgOnce is true")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNoticeDefaultTemplate(t *testing.T) {
|
func TestMsgDefaultTemplate(t *testing.T) {
|
||||||
tmpfile, err := ioutil.TempFile("", "airtesttemmplateconfig")
|
tmpfile, err := ioutil.TempFile("", "airtesttemmplateconfig")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Could not create tmpfile for testing: %s", err)
|
t.Errorf("Could not create tmpfile for testing: %s", err)
|
||||||
@ -150,8 +150,8 @@ func TestNoticeDefaultTemplate(t *testing.T) {
|
|||||||
t.Errorf("Expected a config, got: %s", err)
|
t.Errorf("Expected a config, got: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.NoticeTemplate != defaultNoticeTemplate {
|
if config.MsgTemplate != defaultMsgTemplate {
|
||||||
t.Errorf("Expecting defaultNoticeTemplate when NoticeOnce is false")
|
t.Errorf("Expecting defaultMsgTemplate when MsgOnce is false")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,7 +163,7 @@ func TestGivenTemplateNotOverwritten(t *testing.T) {
|
|||||||
defer os.Remove(tmpfile.Name())
|
defer os.Remove(tmpfile.Name())
|
||||||
|
|
||||||
expectedTemplate := "Alert {{ .Status }}: {{ .Annotations.SUMMARY }}"
|
expectedTemplate := "Alert {{ .Status }}: {{ .Annotations.SUMMARY }}"
|
||||||
configData := []byte(fmt.Sprintf("notice_template: \"%s\"", expectedTemplate))
|
configData := []byte(fmt.Sprintf("msg_template: \"%s\"", expectedTemplate))
|
||||||
if _, err := tmpfile.Write(configData); err != nil {
|
if _, err := tmpfile.Write(configData); err != nil {
|
||||||
t.Errorf("Could not write test data in tmpfile: %s", err)
|
t.Errorf("Could not write test data in tmpfile: %s", err)
|
||||||
}
|
}
|
||||||
@ -174,7 +174,7 @@ func TestGivenTemplateNotOverwritten(t *testing.T) {
|
|||||||
t.Errorf("Expected a config, got: %s", err)
|
t.Errorf("Expected a config, got: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.NoticeTemplate != expectedTemplate {
|
if config.MsgTemplate != expectedTemplate {
|
||||||
t.Errorf("Template does not match configuration")
|
t.Errorf("Template does not match configuration")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2
data.go
2
data.go
@ -14,6 +14,6 @@
|
|||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
type AlertNotice struct {
|
type AlertMsg struct {
|
||||||
Channel, Alert string
|
Channel, Alert string
|
||||||
}
|
}
|
||||||
|
54
http.go
54
http.go
@ -35,20 +35,20 @@ type HTTPServer struct {
|
|||||||
StoppedRunning chan bool
|
StoppedRunning chan bool
|
||||||
Addr string
|
Addr string
|
||||||
Port int
|
Port int
|
||||||
NoticeTemplate *template.Template
|
MsgTemplate *template.Template
|
||||||
NoticeOnce bool
|
MsgOnce bool
|
||||||
AlertNotices chan AlertNotice
|
AlertMsgs chan AlertMsg
|
||||||
httpListener HTTPListener
|
httpListener HTTPListener
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHTTPServer(config *Config, alertNotices chan AlertNotice) (
|
func NewHTTPServer(config *Config, alertMsgs chan AlertMsg) (
|
||||||
*HTTPServer, error) {
|
*HTTPServer, error) {
|
||||||
return NewHTTPServerForTesting(config, alertNotices, http.ListenAndServe)
|
return NewHTTPServerForTesting(config, alertMsgs, http.ListenAndServe)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHTTPServerForTesting(config *Config, alertNotices chan AlertNotice,
|
func NewHTTPServerForTesting(config *Config, alertMsgs chan AlertMsg,
|
||||||
httpListener HTTPListener) (*HTTPServer, error) {
|
httpListener HTTPListener) (*HTTPServer, error) {
|
||||||
tmpl, err := template.New("notice").Parse(config.NoticeTemplate)
|
tmpl, err := template.New("msg").Parse(config.MsgTemplate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -56,22 +56,22 @@ func NewHTTPServerForTesting(config *Config, alertNotices chan AlertNotice,
|
|||||||
StoppedRunning: make(chan bool),
|
StoppedRunning: make(chan bool),
|
||||||
Addr: config.HTTPHost,
|
Addr: config.HTTPHost,
|
||||||
Port: config.HTTPPort,
|
Port: config.HTTPPort,
|
||||||
NoticeTemplate: tmpl,
|
MsgTemplate: tmpl,
|
||||||
NoticeOnce: config.NoticeOnce,
|
MsgOnce: config.MsgOnce,
|
||||||
AlertNotices: alertNotices,
|
AlertMsgs: alertMsgs,
|
||||||
httpListener: httpListener,
|
httpListener: httpListener,
|
||||||
}
|
}
|
||||||
|
|
||||||
return server, nil
|
return server, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *HTTPServer) FormatNotice(data interface{}) string {
|
func (server *HTTPServer) FormatMsg(data interface{}) string {
|
||||||
output := bytes.Buffer{}
|
output := bytes.Buffer{}
|
||||||
var msg string
|
var msg string
|
||||||
if err := server.NoticeTemplate.Execute(&output, data); err != nil {
|
if err := server.MsgTemplate.Execute(&output, data); err != nil {
|
||||||
msg_bytes, _ := json.Marshal(data)
|
msg_bytes, _ := json.Marshal(data)
|
||||||
msg = string(msg_bytes)
|
msg = string(msg_bytes)
|
||||||
log.Printf("Could not apply notice template on alert (%s): %s",
|
log.Printf("Could not apply msg template on alert (%s): %s",
|
||||||
err, msg)
|
err, msg)
|
||||||
log.Printf("Sending raw alert")
|
log.Printf("Sending raw alert")
|
||||||
} else {
|
} else {
|
||||||
@ -80,21 +80,21 @@ func (server *HTTPServer) FormatNotice(data interface{}) string {
|
|||||||
return msg
|
return msg
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *HTTPServer) GetNoticesFromAlertMessage(ircChannel string,
|
func (server *HTTPServer) GetMsgsFromAlertMessage(ircChannel string,
|
||||||
data *promtmpl.Data) []AlertNotice {
|
data *promtmpl.Data) []AlertMsg {
|
||||||
notices := []AlertNotice{}
|
msgs := []AlertMsg{}
|
||||||
if server.NoticeOnce {
|
if server.MsgOnce {
|
||||||
msg := server.FormatNotice(data)
|
msg := server.FormatMsg(data)
|
||||||
notices = append(notices,
|
msgs = append(msgs,
|
||||||
AlertNotice{Channel: ircChannel, Alert: msg})
|
AlertMsg{Channel: ircChannel, Alert: msg})
|
||||||
} else {
|
} else {
|
||||||
for _, alert := range data.Alerts {
|
for _, alert := range data.Alerts {
|
||||||
msg := server.FormatNotice(alert)
|
msg := server.FormatMsg(alert)
|
||||||
notices = append(notices,
|
msgs = append(msgs,
|
||||||
AlertNotice{Channel: ircChannel, Alert: msg})
|
AlertMsg{Channel: ircChannel, Alert: msg})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return notices
|
return msgs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *HTTPServer) RelayAlert(w http.ResponseWriter, r *http.Request) {
|
func (server *HTTPServer) RelayAlert(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -119,13 +119,13 @@ func (server *HTTPServer) RelayAlert(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, alertNotice := range server.GetNoticesFromAlertMessage(
|
for _, alertMsg := range server.GetMsgsFromAlertMessage(
|
||||||
ircChannel, &alertMessage) {
|
ircChannel, &alertMessage) {
|
||||||
select {
|
select {
|
||||||
case server.AlertNotices <- alertNotice:
|
case server.AlertMsgs <- alertMsg:
|
||||||
default:
|
default:
|
||||||
log.Printf("Could not send this alert to the IRC routine: %s",
|
log.Printf("Could not send this alert to the IRC routine: %s",
|
||||||
alertNotice)
|
alertMsg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
66
http_test.go
66
http_test.go
@ -26,7 +26,7 @@ import (
|
|||||||
type FakeHTTPListener struct {
|
type FakeHTTPListener struct {
|
||||||
StartedServing chan bool
|
StartedServing chan bool
|
||||||
StopServing chan bool
|
StopServing chan bool
|
||||||
AlertNotices chan AlertNotice // kinda ugly putting it here, but convenient
|
AlertMsgs chan AlertMsg // kinda ugly putting it here, but convenient
|
||||||
router http.Handler
|
router http.Handler
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,15 +42,15 @@ func NewFakeHTTPListener() *FakeHTTPListener {
|
|||||||
return &FakeHTTPListener{
|
return &FakeHTTPListener{
|
||||||
StartedServing: make(chan bool),
|
StartedServing: make(chan bool),
|
||||||
StopServing: make(chan bool),
|
StopServing: make(chan bool),
|
||||||
AlertNotices: make(chan AlertNotice, 10),
|
AlertMsgs: make(chan AlertMsg, 10),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeHTTPTestingConfig() *Config {
|
func MakeHTTPTestingConfig() *Config {
|
||||||
return &Config{
|
return &Config{
|
||||||
HTTPHost: "test.web",
|
HTTPHost: "test.web",
|
||||||
HTTPPort: 8888,
|
HTTPPort: 8888,
|
||||||
NoticeTemplate: "Alert {{ .Labels.alertname }} on {{ .Labels.instance }} is {{ .Status }}",
|
MsgTemplate: "Alert {{ .Labels.alertname }} on {{ .Labels.instance }} is {{ .Status }}",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ func RunHTTPTest(t *testing.T,
|
|||||||
alertData string, url string,
|
alertData string, url string,
|
||||||
testingConfig *Config, listener *FakeHTTPListener) *http.Response {
|
testingConfig *Config, listener *FakeHTTPListener) *http.Response {
|
||||||
httpServer, err := NewHTTPServerForTesting(testingConfig,
|
httpServer, err := NewHTTPServerForTesting(testingConfig,
|
||||||
listener.AlertNotices, listener.Serve)
|
listener.AlertMsgs, listener.Serve)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(fmt.Sprintf("Could not create HTTP server: %s", err))
|
t.Fatal(fmt.Sprintf("Could not create HTTP server: %s", err))
|
||||||
}
|
}
|
||||||
@ -85,12 +85,12 @@ func TestAlertsDispatched(t *testing.T) {
|
|||||||
listener := NewFakeHTTPListener()
|
listener := NewFakeHTTPListener()
|
||||||
testingConfig := MakeHTTPTestingConfig()
|
testingConfig := MakeHTTPTestingConfig()
|
||||||
|
|
||||||
expectedAlertNotices := []AlertNotice{
|
expectedAlertMsgs := []AlertMsg{
|
||||||
AlertNotice{
|
AlertMsg{
|
||||||
Channel: "#somechannel",
|
Channel: "#somechannel",
|
||||||
Alert: "Alert airDown on instance1:3456 is resolved",
|
Alert: "Alert airDown on instance1:3456 is resolved",
|
||||||
},
|
},
|
||||||
AlertNotice{
|
AlertMsg{
|
||||||
Channel: "#somechannel",
|
Channel: "#somechannel",
|
||||||
Alert: "Alert airDown on instance2:7890 is resolved",
|
Alert: "Alert airDown on instance2:7890 is resolved",
|
||||||
},
|
},
|
||||||
@ -106,12 +106,12 @@ func TestAlertsDispatched(t *testing.T) {
|
|||||||
expectedStatusCode, response.StatusCode))
|
expectedStatusCode, response.StatusCode))
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, expectedAlertNotice := range expectedAlertNotices {
|
for _, expectedAlertMsg := range expectedAlertMsgs {
|
||||||
alertNotice := <-listener.AlertNotices
|
alertMsg := <-listener.AlertMsgs
|
||||||
if !reflect.DeepEqual(expectedAlertNotice, alertNotice) {
|
if !reflect.DeepEqual(expectedAlertMsg, alertMsg) {
|
||||||
t.Error(fmt.Sprintf(
|
t.Error(fmt.Sprintf(
|
||||||
"Unexpected alert notice.\nExpected: %s\nActual: %s",
|
"Unexpected alert msg.\nExpected: %s\nActual: %s",
|
||||||
expectedAlertNotice, alertNotice))
|
expectedAlertMsg, alertMsg))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,11 +119,11 @@ func TestAlertsDispatched(t *testing.T) {
|
|||||||
func TestAlertsDispatchedOnce(t *testing.T) {
|
func TestAlertsDispatchedOnce(t *testing.T) {
|
||||||
listener := NewFakeHTTPListener()
|
listener := NewFakeHTTPListener()
|
||||||
testingConfig := MakeHTTPTestingConfig()
|
testingConfig := MakeHTTPTestingConfig()
|
||||||
testingConfig.NoticeOnce = true
|
testingConfig.MsgOnce = true
|
||||||
testingConfig.NoticeTemplate = "Alert {{ .GroupLabels.alertname }} is {{ .Status }}"
|
testingConfig.MsgTemplate = "Alert {{ .GroupLabels.alertname }} is {{ .Status }}"
|
||||||
|
|
||||||
expectedAlertNotices := []AlertNotice{
|
expectedAlertMsgs := []AlertMsg{
|
||||||
AlertNotice{
|
AlertMsg{
|
||||||
Channel: "#somechannel",
|
Channel: "#somechannel",
|
||||||
Alert: "Alert airDown is resolved",
|
Alert: "Alert airDown is resolved",
|
||||||
},
|
},
|
||||||
@ -139,12 +139,12 @@ func TestAlertsDispatchedOnce(t *testing.T) {
|
|||||||
expectedStatusCode, response.StatusCode))
|
expectedStatusCode, response.StatusCode))
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, expectedAlertNotice := range expectedAlertNotices {
|
for _, expectedAlertMsg := range expectedAlertMsgs {
|
||||||
alertNotice := <-listener.AlertNotices
|
alertMsg := <-listener.AlertMsgs
|
||||||
if !reflect.DeepEqual(expectedAlertNotice, alertNotice) {
|
if !reflect.DeepEqual(expectedAlertMsg, alertMsg) {
|
||||||
t.Error(fmt.Sprintf(
|
t.Error(fmt.Sprintf(
|
||||||
"Unexpected alert notice.\nExpected: %s\nActual: %s",
|
"Unexpected alert msg.\nExpected: %s\nActual: %s",
|
||||||
expectedAlertNotice, alertNotice))
|
expectedAlertMsg, alertMsg))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -181,17 +181,17 @@ func TestInvalidDataReturnsError(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTemplateErrorsCreateRawAlertNotice(t *testing.T) {
|
func TestTemplateErrorsCreateRawAlertMsg(t *testing.T) {
|
||||||
listener := NewFakeHTTPListener()
|
listener := NewFakeHTTPListener()
|
||||||
testingConfig := MakeHTTPTestingConfig()
|
testingConfig := MakeHTTPTestingConfig()
|
||||||
testingConfig.NoticeTemplate = "Bogus template {{ nil }}"
|
testingConfig.MsgTemplate = "Bogus template {{ nil }}"
|
||||||
|
|
||||||
expectedAlertNotices := []AlertNotice{
|
expectedAlertMsgs := []AlertMsg{
|
||||||
AlertNotice{
|
AlertMsg{
|
||||||
Channel: "#somechannel",
|
Channel: "#somechannel",
|
||||||
Alert: `{"status":"resolved","labels":{"alertname":"airDown","instance":"instance1:3456","job":"air","service":"prometheus","severity":"ticket","zone":"global"},"annotations":{"DESCRIPTION":"service /prometheus has irc gateway down on instance1","SUMMARY":"service /prometheus air down on instance1"},"startsAt":"2017-05-15T13:49:37.834Z","endsAt":"2017-05-15T13:50:37.835Z","generatorURL":"https://prometheus.example.com/prometheus/...","fingerprint":"66214a361160fb6f"}`,
|
Alert: `{"status":"resolved","labels":{"alertname":"airDown","instance":"instance1:3456","job":"air","service":"prometheus","severity":"ticket","zone":"global"},"annotations":{"DESCRIPTION":"service /prometheus has irc gateway down on instance1","SUMMARY":"service /prometheus air down on instance1"},"startsAt":"2017-05-15T13:49:37.834Z","endsAt":"2017-05-15T13:50:37.835Z","generatorURL":"https://prometheus.example.com/prometheus/...","fingerprint":"66214a361160fb6f"}`,
|
||||||
},
|
},
|
||||||
AlertNotice{
|
AlertMsg{
|
||||||
Channel: "#somechannel",
|
Channel: "#somechannel",
|
||||||
Alert: `{"status":"resolved","labels":{"alertname":"airDown","instance":"instance2:7890","job":"air","service":"prometheus","severity":"ticket","zone":"global"},"annotations":{"DESCRIPTION":"service /prometheus has irc gateway down on instance2","SUMMARY":"service /prometheus air down on instance2"},"startsAt":"2017-05-15T11:47:37.834Z","endsAt":"2017-05-15T11:48:37.834Z","generatorURL":"https://prometheus.example.com/prometheus/...","fingerprint":"25a874c99325d1ce"}`,
|
Alert: `{"status":"resolved","labels":{"alertname":"airDown","instance":"instance2:7890","job":"air","service":"prometheus","severity":"ticket","zone":"global"},"annotations":{"DESCRIPTION":"service /prometheus has irc gateway down on instance2","SUMMARY":"service /prometheus air down on instance2"},"startsAt":"2017-05-15T11:47:37.834Z","endsAt":"2017-05-15T11:48:37.834Z","generatorURL":"https://prometheus.example.com/prometheus/...","fingerprint":"25a874c99325d1ce"}`,
|
||||||
},
|
},
|
||||||
@ -207,12 +207,12 @@ func TestTemplateErrorsCreateRawAlertNotice(t *testing.T) {
|
|||||||
expectedStatusCode, response.StatusCode))
|
expectedStatusCode, response.StatusCode))
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, expectedAlertNotice := range expectedAlertNotices {
|
for _, expectedAlertMsg := range expectedAlertMsgs {
|
||||||
alertNotice := <-listener.AlertNotices
|
alertMsg := <-listener.AlertMsgs
|
||||||
if !reflect.DeepEqual(expectedAlertNotice, alertNotice) {
|
if !reflect.DeepEqual(expectedAlertMsg, alertMsg) {
|
||||||
t.Error(fmt.Sprintf(
|
t.Error(fmt.Sprintf(
|
||||||
"Unexpected alert notice.\nExpected: %s\nActual: %s",
|
"Unexpected alert msg.\nExpected: %s\nActual: %s",
|
||||||
expectedAlertNotice, alertNotice))
|
expectedAlertMsg, alertMsg))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
18
irc.go
18
irc.go
@ -48,7 +48,7 @@ type IRCNotifier struct {
|
|||||||
Client *irc.Conn
|
Client *irc.Conn
|
||||||
StopRunning chan bool
|
StopRunning chan bool
|
||||||
StoppedRunning chan bool
|
StoppedRunning chan bool
|
||||||
AlertNotices chan AlertNotice
|
AlertMsgs chan AlertMsg
|
||||||
|
|
||||||
// irc.Conn has a Connected() method that can tell us wether the TCP
|
// irc.Conn has a Connected() method that can tell us wether the TCP
|
||||||
// connection is up, and thus if we should trigger connect/disconnect.
|
// connection is up, and thus if we should trigger connect/disconnect.
|
||||||
@ -66,7 +66,7 @@ type IRCNotifier struct {
|
|||||||
BackoffCounter Delayer
|
BackoffCounter Delayer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewIRCNotifier(config *Config, alertNotices chan AlertNotice) (*IRCNotifier, error) {
|
func NewIRCNotifier(config *Config, alertMsgs chan AlertMsg) (*IRCNotifier, error) {
|
||||||
|
|
||||||
ircConfig := irc.NewConfig(config.IRCNick)
|
ircConfig := irc.NewConfig(config.IRCNick)
|
||||||
ircConfig.Me.Ident = config.IRCNick
|
ircConfig.Me.Ident = config.IRCNick
|
||||||
@ -89,7 +89,7 @@ func NewIRCNotifier(config *Config, alertNotices chan AlertNotice) (*IRCNotifier
|
|||||||
Client: irc.Client(ircConfig),
|
Client: irc.Client(ircConfig),
|
||||||
StopRunning: make(chan bool),
|
StopRunning: make(chan bool),
|
||||||
StoppedRunning: make(chan bool),
|
StoppedRunning: make(chan bool),
|
||||||
AlertNotices: alertNotices,
|
AlertMsgs: alertMsgs,
|
||||||
sessionUpSignal: make(chan bool),
|
sessionUpSignal: make(chan bool),
|
||||||
sessionDownSignal: make(chan bool),
|
sessionDownSignal: make(chan bool),
|
||||||
PreJoinChannels: config.IRCChannels,
|
PreJoinChannels: config.IRCChannels,
|
||||||
@ -189,14 +189,14 @@ func (notifier *IRCNotifier) MaybeIdentifyNick() {
|
|||||||
time.Sleep(notifier.NickservDelayWait)
|
time.Sleep(notifier.NickservDelayWait)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (notifier *IRCNotifier) MaybeSendAlertNotice(alertNotice *AlertNotice) {
|
func (notifier *IRCNotifier) MaybeSendAlertMsg(alertMsg *AlertMsg) {
|
||||||
if !notifier.sessionUp {
|
if !notifier.sessionUp {
|
||||||
log.Printf("Cannot send alert to %s : IRC not connected",
|
log.Printf("Cannot send alert to %s : IRC not connected",
|
||||||
alertNotice.Channel)
|
alertMsg.Channel)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
notifier.JoinChannel(&IRCChannel{Name: alertNotice.Channel})
|
notifier.JoinChannel(&IRCChannel{Name: alertMsg.Channel})
|
||||||
notifier.Client.Notice(alertNotice.Channel, alertNotice.Alert)
|
notifier.Client.Notice(alertMsg.Channel, alertMsg.Alert)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (notifier *IRCNotifier) Run() {
|
func (notifier *IRCNotifier) Run() {
|
||||||
@ -219,8 +219,8 @@ func (notifier *IRCNotifier) Run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case alertNotice := <-notifier.AlertNotices:
|
case alertMsg := <-notifier.AlertMsgs:
|
||||||
notifier.MaybeSendAlertNotice(&alertNotice)
|
notifier.MaybeSendAlertMsg(&alertMsg)
|
||||||
case <-notifier.sessionUpSignal:
|
case <-notifier.sessionUpSignal:
|
||||||
notifier.sessionUp = true
|
notifier.sessionUp = true
|
||||||
notifier.MaybeIdentifyNick()
|
notifier.MaybeIdentifyNick()
|
||||||
|
22
irc_test.go
22
irc_test.go
@ -215,16 +215,16 @@ func makeTestIRCConfig(IRCPort int) *Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeTestNotifier(t *testing.T, config *Config) (*IRCNotifier, chan AlertNotice) {
|
func makeTestNotifier(t *testing.T, config *Config) (*IRCNotifier, chan AlertMsg) {
|
||||||
alertNotices := make(chan AlertNotice)
|
alertMsgs := make(chan AlertMsg)
|
||||||
notifier, err := NewIRCNotifier(config, alertNotices)
|
notifier, err := NewIRCNotifier(config, alertMsgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(fmt.Sprintf("Could not create IRC notifier: %s", err))
|
t.Fatal(fmt.Sprintf("Could not create IRC notifier: %s", err))
|
||||||
}
|
}
|
||||||
notifier.Client.Config().Flood = true
|
notifier.Client.Config().Flood = true
|
||||||
notifier.BackoffCounter = &FakeDelayer{}
|
notifier.BackoffCounter = &FakeDelayer{}
|
||||||
|
|
||||||
return notifier, alertNotices
|
return notifier, alertMsgs
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPreJoinChannels(t *testing.T) {
|
func TestPreJoinChannels(t *testing.T) {
|
||||||
@ -268,7 +268,7 @@ func TestPreJoinChannels(t *testing.T) {
|
|||||||
func TestSendAlertOnPreJoinedChannel(t *testing.T) {
|
func TestSendAlertOnPreJoinedChannel(t *testing.T) {
|
||||||
server, port := makeTestServer(t)
|
server, port := makeTestServer(t)
|
||||||
config := makeTestIRCConfig(port)
|
config := makeTestIRCConfig(port)
|
||||||
notifier, alertNotices := makeTestNotifier(t, config)
|
notifier, alertMsgs := makeTestNotifier(t, config)
|
||||||
|
|
||||||
var testStep sync.WaitGroup
|
var testStep sync.WaitGroup
|
||||||
|
|
||||||
@ -299,7 +299,7 @@ func TestSendAlertOnPreJoinedChannel(t *testing.T) {
|
|||||||
server.SetHandler("NOTICE", noticeHandler)
|
server.SetHandler("NOTICE", noticeHandler)
|
||||||
|
|
||||||
testStep.Add(1)
|
testStep.Add(1)
|
||||||
alertNotices <- AlertNotice{Channel: testChannel, Alert: testMessage}
|
alertMsgs <- AlertMsg{Channel: testChannel, Alert: testMessage}
|
||||||
|
|
||||||
testStep.Wait()
|
testStep.Wait()
|
||||||
|
|
||||||
@ -324,7 +324,7 @@ func TestSendAlertOnPreJoinedChannel(t *testing.T) {
|
|||||||
func TestSendAlertAndJoinChannel(t *testing.T) {
|
func TestSendAlertAndJoinChannel(t *testing.T) {
|
||||||
server, port := makeTestServer(t)
|
server, port := makeTestServer(t)
|
||||||
config := makeTestIRCConfig(port)
|
config := makeTestIRCConfig(port)
|
||||||
notifier, alertNotices := makeTestNotifier(t, config)
|
notifier, alertMsgs := makeTestNotifier(t, config)
|
||||||
|
|
||||||
var testStep sync.WaitGroup
|
var testStep sync.WaitGroup
|
||||||
|
|
||||||
@ -356,7 +356,7 @@ func TestSendAlertAndJoinChannel(t *testing.T) {
|
|||||||
server.SetHandler("NOTICE", noticeHandler)
|
server.SetHandler("NOTICE", noticeHandler)
|
||||||
|
|
||||||
testStep.Add(1)
|
testStep.Add(1)
|
||||||
alertNotices <- AlertNotice{Channel: testChannel, Alert: testMessage}
|
alertMsgs <- AlertMsg{Channel: testChannel, Alert: testMessage}
|
||||||
|
|
||||||
testStep.Wait()
|
testStep.Wait()
|
||||||
|
|
||||||
@ -383,7 +383,7 @@ func TestSendAlertAndJoinChannel(t *testing.T) {
|
|||||||
func TestSendAlertDisconnected(t *testing.T) {
|
func TestSendAlertDisconnected(t *testing.T) {
|
||||||
server, port := makeTestServer(t)
|
server, port := makeTestServer(t)
|
||||||
config := makeTestIRCConfig(port)
|
config := makeTestIRCConfig(port)
|
||||||
notifier, alertNotices := makeTestNotifier(t, config)
|
notifier, alertMsgs := makeTestNotifier(t, config)
|
||||||
|
|
||||||
var testStep, holdUserStep sync.WaitGroup
|
var testStep, holdUserStep sync.WaitGroup
|
||||||
|
|
||||||
@ -405,7 +405,7 @@ func TestSendAlertDisconnected(t *testing.T) {
|
|||||||
|
|
||||||
go notifier.Run()
|
go notifier.Run()
|
||||||
|
|
||||||
alertNotices <- AlertNotice{Channel: testChannel, Alert: disconnectedTestMessage}
|
alertMsgs <- AlertMsg{Channel: testChannel, Alert: disconnectedTestMessage}
|
||||||
|
|
||||||
testStep.Done()
|
testStep.Done()
|
||||||
holdUserStep.Wait()
|
holdUserStep.Wait()
|
||||||
@ -432,7 +432,7 @@ func TestSendAlertDisconnected(t *testing.T) {
|
|||||||
}
|
}
|
||||||
server.SetHandler("NOTICE", noticeHandler)
|
server.SetHandler("NOTICE", noticeHandler)
|
||||||
|
|
||||||
alertNotices <- AlertNotice{Channel: testChannel, Alert: connectedTestMessage}
|
alertMsgs <- AlertMsg{Channel: testChannel, Alert: connectedTestMessage}
|
||||||
|
|
||||||
testStep.Wait()
|
testStep.Wait()
|
||||||
|
|
||||||
|
6
main.go
6
main.go
@ -37,16 +37,16 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
alertNotices := make(chan AlertNotice, 10)
|
alertMsgs := make(chan AlertMsg, 10)
|
||||||
|
|
||||||
ircNotifier, err := NewIRCNotifier(config, alertNotices)
|
ircNotifier, err := NewIRCNotifier(config, alertMsgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Could not create IRC notifier: %s", err)
|
log.Printf("Could not create IRC notifier: %s", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
go ircNotifier.Run()
|
go ircNotifier.Run()
|
||||||
|
|
||||||
httpServer, err := NewHTTPServer(config, alertNotices)
|
httpServer, err := NewHTTPServer(config, alertMsgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Could not create HTTP server: %s", err)
|
log.Printf("Could not create HTTP server: %s", err)
|
||||||
return
|
return
|
||||||
|
Loading…
x
Reference in New Issue
Block a user