notification fixes, tests

pull/458/head
hunterlong 2020-03-25 11:46:50 -07:00
parent f331e9bbf9
commit 7d385b4da2
23 changed files with 760 additions and 56 deletions

View File

@ -1,3 +1,8 @@
# 0.90.17
- Fixed notification fields for frontend
- Fixed notification JSON form to send integer if value is an integer.
- Added testing for notifiers
# 0.90.16
- Added Notify After (int) field for Services. Will send notifications after x amount of failures.
- Added new method in utils package for replacing `{{.Service.*}}` and `{{.Failure.*}}` variables from string to it's true value

View File

@ -5,6 +5,7 @@ import (
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/core"
"github.com/statping/statping/types/services"
"github.com/statping/statping/utils"
)
func InitApp() error {
@ -22,5 +23,6 @@ func InitApp() error {
database.StartMaintenceRoutine()
core.App.Setup = true
core.App.Started = utils.Now()
return nil
}

View File

@ -92,7 +92,11 @@ export default {
this.form.method = this.notifier.method
this.notifier.form.forEach((f) => {
let field = f.field.toLowerCase()
this.form[field] = this.notifier[field]
let val = this.notifier[field]
if (this.isNumeric(val)) {
val = parseInt(val)
}
this.form[field] = val
});
await Api.notifier_save(this.form)
// const notifiers = await Api.notifiers()
@ -109,12 +113,16 @@ export default {
let form = {}
this.notifier.form.forEach((f) => {
let field = f.field.toLowerCase()
this.form[field] = this.notifier[field]
let val = this.notifier[field]
if (this.isNumeric(val)) {
val = parseInt(val)
}
this.form[field] = val
});
form.enabled = this.notifier.enabled
form.limits = parseInt(this.notifier.limits)
form.method = this.notifier.method
const tested = await Api.notifier_test(form)
this.form.enabled = this.notifier.enabled
this.form.limits = parseInt(this.notifier.limits)
this.form.method = this.notifier.method
const tested = await Api.notifier_test(this.form)
if (tested === 'ok') {
this.ok = true
} else {

View File

@ -9,6 +9,9 @@ export default Vue.mixin({
now() {
return new Date()
},
isNumeric: function (n) {
return !isNaN(parseFloat(n)) && isFinite(n);
},
current() {
return parseISO(new Date())
},

View File

@ -17,7 +17,6 @@ package handlers
import (
"encoding/json"
"errors"
"fmt"
"github.com/gorilla/mux"
"github.com/statping/statping/types/notifications"
@ -34,16 +33,14 @@ func apiNotifiersHandler(w http.ResponseWriter, r *http.Request) {
func apiNotifierGetHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
notifier := vars["notifier"]
notifiers := services.AllNotifiers()
for _, n := range notifiers {
notf := n.Select()
if notifier == notf.Method {
returnJson(n, w, r)
return
}
notif := services.FindNotifier(vars["notifier"])
notifer, err := notifications.Find(notif.Method)
if err != nil {
sendErrorJson(err, w, r)
return
}
sendErrorJson(errors.New("notifier not found"), w, r)
notif = notif.UpdateFields(notifer)
returnJson(notif, w, r)
}
func apiNotifierUpdateHandler(w http.ResponseWriter, r *http.Request) {
@ -53,14 +50,15 @@ func apiNotifierUpdateHandler(w http.ResponseWriter, r *http.Request) {
sendErrorJson(err, w, r)
return
}
defer r.Body.Close()
var notif *notifications.Notification
decoder := json.NewDecoder(r.Body)
err = decoder.Decode(&notifer)
err = decoder.Decode(&notif)
if err != nil {
sendErrorJson(err, w, r)
return
}
notifer = notifer.UpdateFields(notif)
err = notifer.Update()
if err != nil {
sendErrorJson(err, w, r)

View File

@ -102,6 +102,7 @@ func processSetupHandler(w http.ResponseWriter, r *http.Request) {
//ApiSecret: apiSecret.(string),
Domain: "http://localhost:8080",
Version: core.App.Version,
Started: utils.Now(),
CreatedAt: utils.Now(),
UseCdn: null.NewNullBool(false),
Footer: null.NewNullString(""),

View File

@ -72,25 +72,25 @@ func runCommand(app string, cmd ...string) (string, string, error) {
}
// OnFailure for commandLine will trigger failing service
func (u *commandLine) OnFailure(s *services.Service, f *failures.Failure) error {
msg := u.GetValue("var2")
func (c *commandLine) OnFailure(s *services.Service, f *failures.Failure) error {
msg := c.GetValue("var2")
tmpl := ReplaceVars(msg, s, f)
_, _, err := runCommand(u.Host, tmpl)
_, _, err := runCommand(c.Host, tmpl)
return err
}
// OnSuccess for commandLine will trigger successful service
func (u *commandLine) OnSuccess(s *services.Service) error {
msg := u.GetValue("var1")
func (c *commandLine) OnSuccess(s *services.Service) error {
msg := c.GetValue("var1")
tmpl := ReplaceVars(msg, s, nil)
_, _, err := runCommand(u.Host, tmpl)
_, _, err := runCommand(c.Host, tmpl)
return err
}
// OnTest for commandLine triggers when this notifier has been saved
func (u *commandLine) OnTest() error {
cmds := strings.Split(u.Var1, " ")
in, out, err := runCommand(u.Host, cmds...)
func (c *commandLine) OnTest() error {
cmds := strings.Split(c.Var1, " ")
in, out, err := runCommand(c.Host, cmds...)
utils.Log.Infoln(in)
utils.Log.Infoln(out)
return err

67
notifiers/command_test.go Normal file
View File

@ -0,0 +1,67 @@
// Statping
// Copyright (C) 2018. Hunter Long and the project contributors
// Written by Hunter Long <info@socialeck.com> and the project contributors
//
// https://github.com/hunterlong/statping
//
// The licenses for most software and other practical works are designed
// to take away your freedom to share and change the works. By contrast,
// the GNU General Public License is intended to guarantee your freedom to
// share and change all versions of a program--to make sure it remains free
// software for all its users.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package notifiers
import (
"github.com/statping/statping/database"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"testing"
"time"
)
func TestCommandNotifier(t *testing.T) {
db, err := database.OpenTester()
require.Nil(t, err)
db.AutoMigrate(&notifications.Notification{})
notifications.SetDB(db)
t.Run("Load Command", func(t *testing.T) {
Command.Host = "/bin/echo"
Command.Var1 = "service {{.Service.Domain}} is online"
Command.Var2 = "service {{.Service.Domain}} is offline"
Command.Delay = time.Duration(100 * time.Millisecond)
Command.Limits = 99
Command.Enabled = null.NewNullBool(true)
Add(Command)
assert.Equal(t, "Hunter Long", Command.Author)
assert.Equal(t, "/bin/echo", Command.Host)
})
t.Run("Command Notifier Tester", func(t *testing.T) {
assert.True(t, Command.CanSend())
})
t.Run("Command OnFailure", func(t *testing.T) {
err := Command.OnFailure(exampleService, exampleFailure)
assert.Nil(t, err)
})
t.Run("Command OnSuccess", func(t *testing.T) {
err := Command.OnSuccess(exampleService)
assert.Nil(t, err)
})
t.Run("Command Test", func(t *testing.T) {
err := Command.OnTest()
assert.Nil(t, err)
})
}

79
notifiers/discord_test.go Normal file
View File

@ -0,0 +1,79 @@
// Statping
// Copyright (C) 2018. Hunter Long and the project contributors
// Written by Hunter Long <info@socialeck.com> and the project contributors
//
// https://github.com/hunterlong/statping
//
// The licenses for most software and other practical works are designed
// to take away your freedom to share and change the works. By contrast,
// the GNU General Public License is intended to guarantee your freedom to
// share and change all versions of a program--to make sure it remains free
// software for all its users.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package notifiers
import (
"github.com/statping/statping/database"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"os"
"testing"
"time"
)
var (
DISCORD_URL = os.Getenv("DISCORD_URL")
discordMessage = `{"content": "The discord notifier on Statping has been tested!"}`
)
func init() {
DISCORD_URL = os.Getenv("DISCORD_URL")
}
func TestDiscordNotifier(t *testing.T) {
db, err := database.OpenTester()
require.Nil(t, err)
db.AutoMigrate(&notifications.Notification{})
notifications.SetDB(db)
if DISCORD_URL == "" {
t.Log("discord notifier testing skipped, missing DISCORD_URL environment variable")
t.SkipNow()
}
t.Run("Load discord", func(t *testing.T) {
Discorder.Host = DISCORD_URL
Discorder.Delay = time.Duration(100 * time.Millisecond)
Discorder.Enabled = null.NewNullBool(true)
Add(Discorder)
assert.Equal(t, "Hunter Long", Discorder.Author)
assert.Equal(t, DISCORD_URL, Discorder.Host)
})
t.Run("discord Notifier Tester", func(t *testing.T) {
assert.True(t, Discorder.CanSend())
})
t.Run("discord OnFailure", func(t *testing.T) {
err := Discorder.OnFailure(exampleService, exampleFailure)
assert.Nil(t, err)
})
t.Run("discord OnSuccess", func(t *testing.T) {
err := Discorder.OnSuccess(exampleService)
assert.Nil(t, err)
})
t.Run("discord Test", func(t *testing.T) {
err := Discorder.OnTest()
assert.Nil(t, err)
})
}

View File

@ -16,7 +16,6 @@
package notifiers
import (
"bytes"
"crypto/tls"
"fmt"
"github.com/go-mail/mail"
@ -26,7 +25,6 @@ import (
"github.com/statping/statping/types/null"
"github.com/statping/statping/types/services"
"github.com/statping/statping/utils"
"html/template"
"time"
)
@ -183,7 +181,7 @@ func (e *emailer) OnFailure(s *services.Service, f *failures.Failure) error {
To: e.Var2,
Subject: fmt.Sprintf("Service %v is Failing", s.Name),
Template: mainEmailTemplate,
Data: interface{}(s),
Data: ToMap(s, f),
From: e.Var1,
}
return e.dialSend(email)
@ -196,7 +194,7 @@ func (e *emailer) OnSuccess(s *services.Service) error {
To: e.Var2,
Subject: msg,
Template: mainEmailTemplate,
Data: interface{}(s),
Data: ToMap(s, nil),
From: e.Var1,
}
return e.dialSend(email)
@ -230,7 +228,6 @@ func (e *emailer) OnTest() error {
func (e *emailer) dialSend(email *emailOutgoing) error {
mailer = mail.NewDialer(e.Host, e.Port, e.Username, e.Password)
emailSource(email)
m := mail.NewMessage()
// if email setting TLS is Disabled
if e.ApiKey == "true" {
@ -241,29 +238,11 @@ func (e *emailer) dialSend(email *emailOutgoing) error {
m.SetHeader("From", email.From)
m.SetHeader("To", email.To)
m.SetHeader("Subject", email.Subject)
m.SetBody("text/html", email.Source)
m.SetBody("text/html", utils.ReplaceTemplate(email.Template, email.Data))
if err := mailer.DialAndSend(m); err != nil {
utils.Log.Errorln(fmt.Sprintf("email '%v' sent to: %v (size: %v) %v", email.Subject, email.To, len([]byte(email.Source)), err))
return err
}
return nil
}
func emailSource(email *emailOutgoing) {
source := emailTemplate(email.Template, email.Data)
email.Source = source
}
func emailTemplate(contents string, data interface{}) string {
t := template.New("email")
t, err := t.Parse(contents)
if err != nil {
utils.Log.Errorln(err)
}
var tpl bytes.Buffer
if err := t.Execute(&tpl, data); err != nil {
utils.Log.Warnln(err)
}
result := tpl.String()
return result
}

114
notifiers/email_test.go Normal file
View File

@ -0,0 +1,114 @@
// Statping
// Copyright (C) 2018. Hunter Long and the project contributors
// Written by Hunter Long <info@socialeck.com> and the project contributors
//
// https://github.com/hunterlong/statping
//
// The licenses for most software and other practical works are designed
// to take away your freedom to share and change the works. By contrast,
// the GNU General Public License is intended to guarantee your freedom to
// share and change all versions of a program--to make sure it remains free
// software for all its users.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package notifiers
import (
"fmt"
"github.com/statping/statping/database"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null"
"github.com/statping/statping/utils"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"os"
"testing"
"time"
)
var (
EMAIL_HOST string
EMAIL_USER string
EMAIL_PASS string
EMAIL_OUTGOING string
EMAIL_SEND_TO string
EMAIL_PORT int64
)
var testEmail *emailOutgoing
func init() {
EMAIL_HOST = os.Getenv("EMAIL_HOST")
EMAIL_USER = os.Getenv("EMAIL_USER")
EMAIL_PASS = os.Getenv("EMAIL_PASS")
EMAIL_OUTGOING = os.Getenv("EMAIL_OUTGOING")
EMAIL_SEND_TO = os.Getenv("EMAIL_SEND_TO")
EMAIL_PORT = utils.ToInt(os.Getenv("EMAIL_PORT"))
}
func TestEmailNotifier(t *testing.T) {
db, err := database.OpenTester()
require.Nil(t, err)
db.AutoMigrate(&notifications.Notification{})
notifications.SetDB(db)
if EMAIL_HOST == "" || EMAIL_USER == "" || EMAIL_PASS == "" {
t.Log("email notifier testing skipped, missing EMAIL_ environment variables")
t.SkipNow()
}
t.Run("New email", func(t *testing.T) {
email.Host = EMAIL_HOST
email.Username = EMAIL_USER
email.Password = EMAIL_PASS
email.Var1 = EMAIL_OUTGOING
email.Var2 = EMAIL_SEND_TO
email.Port = int(EMAIL_PORT)
email.Delay = time.Duration(100 * time.Millisecond)
email.Enabled = null.NewNullBool(true)
Add(email)
assert.Equal(t, "Hunter Long", email.Author)
assert.Equal(t, EMAIL_HOST, email.Host)
testEmail = &emailOutgoing{
To: email.GetValue("var2"),
Subject: fmt.Sprintf("Service %v is Failing", exampleService.Name),
Template: mainEmailTemplate,
Data: exampleService,
From: email.GetValue("var1"),
}
})
t.Run("email Within Limits", func(t *testing.T) {
ok := email.CanSend()
assert.True(t, ok)
})
t.Run("email OnFailure", func(t *testing.T) {
err := email.OnFailure(exampleService, exampleFailure)
assert.Nil(t, err)
})
t.Run("email OnSuccess", func(t *testing.T) {
err := email.OnSuccess(exampleService)
assert.Nil(t, err)
})
t.Run("email Check Back Online", func(t *testing.T) {
assert.True(t, exampleService.Online)
})
t.Run("email OnSuccess Again", func(t *testing.T) {
err := email.OnSuccess(exampleService)
assert.Nil(t, err)
})
t.Run("email Test", func(t *testing.T) {
err := email.OnTest()
assert.Nil(t, err)
})
}

87
notifiers/mobile_test.go Normal file
View File

@ -0,0 +1,87 @@
// Statping
// Copyright (C) 2018. Hunter Long and the project contributors
// Written by Hunter Long <info@socialeck.com> and the project contributors
//
// https://github.com/hunterlong/statping
//
// The licenses for most software and other practical works are designed
// to take away your freedom to share and change the works. By contrast,
// the GNU General Public License is intended to guarantee your freedom to
// share and change all versions of a program--to make sure it remains free
// software for all its users.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package notifiers
import (
"github.com/statping/statping/database"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"os"
"testing"
"time"
)
var (
MOBILE_ID string
MOBILE_NUMBER string
)
func init() {
MOBILE_ID = os.Getenv("MOBILE_ID")
MOBILE_NUMBER = os.Getenv("MOBILE_NUMBER")
Mobile.Var1 = MOBILE_ID
}
func TestMobileNotifier(t *testing.T) {
db, err := database.OpenTester()
require.Nil(t, err)
db.AutoMigrate(&notifications.Notification{})
notifications.SetDB(db)
Mobile.Var1 = MOBILE_ID
Mobile.Var2 = os.Getenv("MOBILE_NUMBER")
if MOBILE_ID == "" {
t.Log("Mobile notifier testing skipped, missing MOBILE_ID environment variable")
t.SkipNow()
}
t.Run("Load Mobile", func(t *testing.T) {
Mobile.Var1 = MOBILE_ID
Mobile.Var2 = MOBILE_NUMBER
Mobile.Delay = time.Duration(100 * time.Millisecond)
Mobile.Limits = 10
Mobile.Enabled = null.NewNullBool(true)
Add(Mobile)
assert.Equal(t, "Hunter Long", Mobile.Author)
assert.Equal(t, MOBILE_ID, Mobile.Var1)
assert.Equal(t, MOBILE_NUMBER, Mobile.Var2)
})
t.Run("Mobile Notifier Tester", func(t *testing.T) {
assert.True(t, Mobile.CanSend())
})
t.Run("Mobile OnFailure", func(t *testing.T) {
err := Mobile.OnFailure(exampleService, exampleFailure)
assert.Nil(t, err)
})
t.Run("Mobile OnSuccess", func(t *testing.T) {
err := Mobile.OnSuccess(exampleService)
assert.Nil(t, err)
})
t.Run("Mobile Test", func(t *testing.T) {
t.SkipNow()
err := Mobile.OnTest()
assert.Nil(t, err)
})
}

View File

@ -32,6 +32,13 @@ func Add(notifs ...services.ServiceNotifier) {
}
}
func ToMap(srv *services.Service, f *failures.Failure) map[string]interface{} {
m := make(map[string]interface{})
m["Service"] = srv
m["Failure"] = f
return m
}
func ReplaceVars(input string, s *services.Service, f *failures.Failure) string {
input = utils.ReplaceTemplate(input, s)
if f != nil {

72
notifiers/slack_test.go Normal file
View File

@ -0,0 +1,72 @@
// Statping
// Copyright (C) 2018. Hunter Long and the project contributors
// Written by Hunter Long <info@socialeck.com> and the project contributors
//
// https://github.com/hunterlong/statping
//
// The licenses for most software and other practical works are designed
// to take away your freedom to share and change the works. By contrast,
// the GNU General Public License is intended to guarantee your freedom to
// share and change all versions of a program--to make sure it remains free
// software for all its users.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package notifiers
import (
"github.com/statping/statping/database"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"os"
"testing"
"time"
)
var (
SLACK_URL string
)
func TestSlackNotifier(t *testing.T) {
db, err := database.OpenTester()
require.Nil(t, err)
db.AutoMigrate(&notifications.Notification{})
notifications.SetDB(db)
SLACK_URL = os.Getenv("SLACK_URL")
slacker.Host = SLACK_URL
slacker.Enabled = null.NewNullBool(true)
if SLACK_URL == "" {
t.Log("slack notifier testing skipped, missing SLACK_URL environment variable")
t.SkipNow()
}
t.Run("Load slack", func(t *testing.T) {
slacker.Host = SLACK_URL
slacker.Delay = time.Duration(100 * time.Millisecond)
slacker.Limits = 3
Add(slacker)
assert.Equal(t, "Hunter Long", slacker.Author)
assert.Equal(t, SLACK_URL, slacker.Host)
})
t.Run("slack Within Limits", func(t *testing.T) {
ok := slacker.CanSend()
assert.True(t, ok)
})
t.Run("slack OnFailure", func(t *testing.T) {
err := slacker.OnFailure(exampleService, exampleFailure)
assert.Nil(t, err)
})
t.Run("slack OnSuccess", func(t *testing.T) {
err := slacker.OnSuccess(exampleService)
assert.Nil(t, err)
})
}

View File

@ -0,0 +1,85 @@
// Statup
// Copyright (C) 2018. Hunter Long and the project contributors
// Written by Hunter Long <info@socialeck.com> and the project contributors
//
// https://github.com/hunterlong/statping
//
// The licenses for most software and other practical works are designed
// to take away your freedom to share and change the works. By contrast,
// the GNU General Public License is intended to guarantee your freedom to
// share and change all versions of a program--to make sure it remains free
// software for all its users.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package notifiers
import (
"github.com/statping/statping/database"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"os"
"testing"
"time"
)
var (
telegramToken string
telegramChannel string
telegramMessage = "The Telegram notifier on Statping has been tested!"
)
func init() {
telegramToken = os.Getenv("TELEGRAM_TOKEN")
telegramChannel = os.Getenv("TELEGRAM_CHANNEL")
Telegram.ApiSecret = telegramToken
Telegram.Var1 = telegramChannel
}
func TestTelegramNotifier(t *testing.T) {
db, err := database.OpenTester()
require.Nil(t, err)
db.AutoMigrate(&notifications.Notification{})
notifications.SetDB(db)
if telegramToken == "" || telegramChannel == "" {
t.Log("Telegram notifier testing skipped, missing TELEGRAM_TOKEN and TELEGRAM_CHANNEL environment variable")
t.SkipNow()
}
t.Run("Load Telegram", func(t *testing.T) {
Telegram.ApiSecret = telegramToken
Telegram.Var1 = telegramChannel
Telegram.Delay = time.Duration(1 * time.Second)
Telegram.Enabled = null.NewNullBool(true)
Add(Telegram)
assert.Equal(t, "Hunter Long", Telegram.Author)
assert.Equal(t, telegramToken, Telegram.ApiSecret)
assert.Equal(t, telegramChannel, Telegram.Var1)
})
t.Run("Telegram Within Limits", func(t *testing.T) {
assert.True(t, Telegram.CanSend())
})
t.Run("Telegram OnFailure", func(t *testing.T) {
err := Telegram.OnFailure(exampleService, exampleFailure)
assert.Nil(t, err)
})
t.Run("Telegram OnSuccess", func(t *testing.T) {
err := Telegram.OnSuccess(exampleService)
assert.Nil(t, err)
})
t.Run("Telegram Test", func(t *testing.T) {
err := Telegram.OnTest()
assert.Nil(t, err)
})
}

90
notifiers/twilio_test.go Normal file
View File

@ -0,0 +1,90 @@
// Statping
// Copyright (C) 2018. Hunter Long and the project contributors
// Written by Hunter Long <info@socialeck.com> and the project contributors
//
// https://github.com/hunterlong/statping
//
// The licenses for most software and other practical works are designed
// to take away your freedom to share and change the works. By contrast,
// the GNU General Public License is intended to guarantee your freedom to
// share and change all versions of a program--to make sure it remains free
// software for all its users.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package notifiers
import (
"github.com/statping/statping/database"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"os"
"testing"
"time"
)
var (
TWILIO_SID = os.Getenv("TWILIO_SID")
TWILIO_SECRET = os.Getenv("TWILIO_SECRET")
TWILIO_FROM = os.Getenv("TWILIO_FROM")
TWILIO_TO = os.Getenv("TWILIO_TO")
)
func init() {
TWILIO_SID = os.Getenv("TWILIO_SID")
TWILIO_SECRET = os.Getenv("TWILIO_SECRET")
TWILIO_FROM = os.Getenv("TWILIO_FROM")
TWILIO_TO = os.Getenv("TWILIO_TO")
}
func TestTwilioNotifier(t *testing.T) {
t.SkipNow()
db, err := database.OpenTester()
require.Nil(t, err)
db.AutoMigrate(&notifications.Notification{})
notifications.SetDB(db)
if TWILIO_SID == "" || TWILIO_SECRET == "" || TWILIO_FROM == "" {
t.Log("twilio notifier testing skipped, missing TWILIO_SID environment variable")
t.SkipNow()
}
t.Run("Load Twilio", func(t *testing.T) {
Twilio.ApiKey = TWILIO_SID
Twilio.ApiSecret = TWILIO_SECRET
Twilio.Var1 = TWILIO_TO
Twilio.Var2 = TWILIO_FROM
Twilio.Delay = time.Duration(100 * time.Millisecond)
Twilio.Enabled = null.NewNullBool(true)
Add(Twilio)
assert.Nil(t, err)
assert.Equal(t, "Hunter Long", Twilio.Author)
assert.Equal(t, TWILIO_SID, Twilio.ApiKey)
})
t.Run("Twilio Within Limits", func(t *testing.T) {
assert.True(t, Twilio.CanSend())
})
t.Run("Twilio OnFailure", func(t *testing.T) {
err := Twilio.OnFailure(exampleService, exampleFailure)
assert.Nil(t, err)
})
t.Run("Twilio OnSuccess", func(t *testing.T) {
err := Twilio.OnSuccess(exampleService)
assert.Nil(t, err)
})
t.Run("Twilio Test", func(t *testing.T) {
err := Twilio.OnTest()
assert.Nil(t, err)
})
}

73
notifiers/webhook_test.go Normal file
View File

@ -0,0 +1,73 @@
// Statping
// Copyright (C) 2018. Hunter Long and the project contributors
// Written by Hunter Long <info@socialeck.com> and the project contributors
//
// https://github.com/hunterlong/statping
//
// The licenses for most software and other practical works are designed
// to take away your freedom to share and change the works. By contrast,
// the GNU General Public License is intended to guarantee your freedom to
// share and change all versions of a program--to make sure it remains free
// software for all its users.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package notifiers
import (
"github.com/statping/statping/database"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"testing"
)
var (
webhookTestUrl = "http://localhost:5555"
webhookMessage = `{"id": {{.Service.Id}},"name": "{{.Service.Name}}","online": {{.Service.Online}},"issue": "{{.Failure.Issue}}"}`
apiKey = "application/json"
fullMsg string
)
func TestWebhookNotifier(t *testing.T) {
db, err := database.OpenTester()
require.Nil(t, err)
db.AutoMigrate(&notifications.Notification{})
notifications.SetDB(db)
t.Run("Load webhooker", func(t *testing.T) {
Webhook.Host = webhookTestUrl
Webhook.Var1 = "POST"
Webhook.Var2 = webhookMessage
Webhook.ApiKey = "application/json"
Webhook.Enabled = null.NewNullBool(true)
Add(Webhook)
assert.Equal(t, "Hunter Long", Webhook.Author)
assert.Equal(t, webhookTestUrl, Webhook.Host)
assert.Equal(t, apiKey, Webhook.ApiKey)
})
t.Run("webhooker Notifier Tester", func(t *testing.T) {
assert.True(t, Webhook.CanSend())
})
t.Run("webhooker OnFailure", func(t *testing.T) {
err := Webhook.OnFailure(exampleService, exampleFailure)
assert.Nil(t, err)
})
t.Run("webhooker OnSuccess", func(t *testing.T) {
err := Webhook.OnSuccess(exampleService)
assert.Nil(t, err)
})
t.Run("webhooker Send", func(t *testing.T) {
err := Webhook.Send(fullMsg)
assert.Nil(t, err)
})
}

View File

@ -2,6 +2,7 @@ package core
import (
"github.com/statping/statping/types/null"
"github.com/statping/statping/utils"
"time"
)
@ -12,6 +13,7 @@ var (
func New(version string) {
App = new(Core)
App.Version = version
App.Started = utils.Now()
}
// Core struct contains all the required fields for Statping. All application settings

View File

@ -32,7 +32,23 @@ func (n *Notification) Create() error {
return nil
}
func (n *Notification) UpdateFields(notif *Notification) *Notification {
n.Enabled = notif.Enabled
n.Host = notif.Host
n.Port = notif.Port
n.Username = notif.Username
n.Password = notif.Password
n.ApiKey = notif.ApiKey
n.ApiSecret = notif.ApiSecret
n.Var1 = notif.Var1
n.Var2 = notif.Var2
return n
}
func (n *Notification) Update() error {
if err := db.Update(n); err.Error() != nil {
return err.Error()
}
n.ResetQueue()
if n.Enabled.Bool {
n.Close()
@ -40,8 +56,7 @@ func (n *Notification) Update() error {
} else {
n.Close()
}
err := db.Update(n)
return err.Error()
return nil
}
func loadAll() []*Notification {

View File

@ -64,7 +64,7 @@ func (n *Notification) CanSend() bool {
//fmt.Println("Last sent before now: ", n.lastSent.Add(60*time.Second).Before(utils.Now()))
// the last sent notification was past 1 minute (limit per minute)
if n.lastSent.Add(60 * time.Second).Before(utils.Now()) {
if n.lastSent.Add(60 * time.Minute).Before(utils.Now()) {
if n.lastSentCount != 0 {
n.lastSentCount--
}

View File

@ -13,6 +13,16 @@ func AllNotifiers() []ServiceNotifier {
return allNotifiers
}
func FindNotifier(method string) *notifications.Notification {
for _, n := range allNotifiers {
notif := n.Select()
if notif.Method == method {
return notif
}
}
return nil
}
type ServiceNotifier interface {
OnSuccess(*Service) error // OnSuccess is triggered when a service is successful
OnFailure(*Service, *failures.Failure) error // OnFailure is triggered when a service is failing

View File

@ -3,6 +3,7 @@ package services
import (
"bytes"
"fmt"
"github.com/statping/statping/types/core"
"net"
"net/http"
"net/url"
@ -259,6 +260,12 @@ func sendSuccess(s *Service) {
if s.SuccessNotified {
return
}
// dont send notification if server recently started (60 seconds)
if core.App.Started.Add(60 * time.Second).After(utils.Now()) {
s.SuccessNotified = true
return
}
for _, n := range allNotifiers {
notif := n.Select()
if notif.CanSend() {

View File

@ -1 +1 @@
0.90.16
0.90.17