first commit
arnaucube arnaucube@gmail.com
Sun, 14 Oct 2018 20:33:30 +0200
10 files changed,
285 insertions(+),
0 deletions(-)
A
README.md
@@ -0,0 +1,39 @@
+# canaryBot +Bot to check if services are alive. +Current bots: +- Matrix (Riot) + + +#### Config +File `config.json` +```json +{ + "matrix": { + "room_id": "!zzzzz:mmmmmm.ooo", + "user": "aaaaa", + "password": "xxxxx", + "server": "https://sssss.ooo" + }, + "services": [{ + "name": "name01", + "url": "http://127.0.0.1:80", + "statusCode": 200 + }, + { + "name": "service02", + "url": "http://127.0.0.1:7000/api", + "statusCode": 200 + } + ], + "sleepTime": 30, + "retry": 5 +} +``` + +- sleepTime: time between each request to the services +- retry: after X times failing, restart the counter + +### Run +``` +./canaryBot +```
A
checker.go
@@ -0,0 +1,54 @@
+package main + +import ( + "log" + "net/http" + "strconv" + "time" +) + +func checker(services []Service) { + log.Println("serverChecker started") + log.Println(services) + + ticker := time.NewTicker(time.Second * time.Duration(int64(config.SleepTime))) + for _ = range ticker.C { + for k, service := range services { + resp, err := checkUrl(service.Url) + if err != nil { + if service.Counter == 0 { + msg := "⚠️ Service " + service.Name + ", with url " + service.Url + " is not responding" + matrixSendMsg(msg) + } + services[k].Counter = services[k].Counter + 1 + } else if resp.StatusCode != service.StatusCode { + if service.Counter == 0 { + msg := "⚠️ Service " + service.Name + ", with url " + service.Url + " has returned a non expected StatusCode: " + strconv.Itoa(resp.StatusCode) + ", expected: " + strconv.Itoa(service.StatusCode) + matrixSendMsg(msg) + } + services[k].Counter = services[k].Counter + 1 + } else { + if services[k].Counter != 0 { + msg := "✔️ Service " + service.Name + ", with url " + service.Url + " is alive again" + matrixSendMsg(msg) + } + services[k].Counter = 0 + } + + if services[k].Counter > config.Retry { + msg := "⚠️ Service " + services[k].Name + ", with url " + services[k].Url + " is still failing" + matrixSendNotice(msg) + services[k].Counter = 1 + } + } + } +} + +func checkUrl(url string) (*http.Response, error) { + timeout := time.Duration(1 * time.Second) + client := http.Client{ + Timeout: timeout, + } + resp, err := client.Get(url) + return resp, err +}
A
config.go
@@ -0,0 +1,37 @@
+package main + +import ( + "encoding/json" + "io/ioutil" +) + +//MatrixConfig stores the matrix data config +type MatrixConfig struct { + RoomId string `json:"room_id"` + User string `json:"user"` + Password string `json:"password"` + Server string `json:"server"` +} +type Service struct { + Name string `json:"name"` + Url string `json:"url"` + StatusCode int `json:"statusCode"` + Counter int +} +type Config struct { + Matrix MatrixConfig `json:"matrix"` + Services []Service `json:"services"` + SleepTime int `json:"sleepTime"` + Retry int `json:"retry"` +} + +var config Config + +func readConfig() { + file, e := ioutil.ReadFile("config.json") + if e != nil { + panic(e) + } + content := string(file) + json.Unmarshal([]byte(content), &config) +}
A
go.mod
@@ -0,0 +1,7 @@
+module github.com/arnaucube/canaryBot + +require ( + github.com/fatih/color v1.7.0 + github.com/mattn/go-colorable v0.0.9 // indirect + github.com/mattn/go-isatty v0.0.4 // indirect +)
A
go.sum
@@ -0,0 +1,6 @@
+github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
A
log.go
@@ -0,0 +1,19 @@
+package main + +import ( + "io" + "log" + "os" + "time" +) + +func savelog() { + timeS := time.Now().String() + _ = os.Mkdir("logs", os.ModePerm) + logFile, err := os.OpenFile("logs/log-"+timeS+".log", os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666) + if err != nil { + panic(err) + } + mw := io.MultiWriter(os.Stdout, logFile) + log.SetOutput(mw) +}
A
main.go
@@ -0,0 +1,28 @@
+package main + +import ( + "fmt" + + "github.com/fatih/color" +) + +const version = "0.0.1-dev" + +func main() { + savelog() + + color.Green("canaryBot") + color.Yellow("version: " + version) + + color.Magenta("------matrix------") + readConfig() + loginMatrix() + fmt.Print("matrix token: ") + color.Cyan(matrixToken.AccessToken) + fmt.Println("") + matrixSendMsg("canaryBot started") + + color.Magenta("------starting to listen------") + + checker(config.Services) +}
A
matrix.go
@@ -0,0 +1,93 @@
+package main + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "log" + "math/rand" + "net/http" + "strconv" + "strings" + "time" + + "github.com/fatih/color" +) + +//MatrixToken stores the token data from matrix +type MatrixToken struct { + AccessToken string `json:"access_token"` + Server string `json:"server"` + UserId string `json:"user_id"` + DeviceId string `json:"device_id"` +} + +var matrixToken MatrixToken + +var defaultTimeFormat = "15:04:05" + +func loginMatrix() { + url := config.Matrix.Server + "/_matrix/client/r0/login" + jsonStr := `{ + "type":"m.login.password", + "user":"` + config.Matrix.User + `", + "password":"` + config.Matrix.Password + `" + }` + b := strings.NewReader(jsonStr) + req, _ := http.NewRequest("POST", url, b) + req.Header.Set("Content-Type", "application/json") + res, err := http.DefaultClient.Do(req) + if err != nil { + log.Println(err) + } + defer res.Body.Close() + body, _ := ioutil.ReadAll(res.Body) + + json.Unmarshal([]byte(body), &matrixToken) + +} +func matrixSendMsg(msg string) { + txnId := strconv.Itoa(rand.Int()) + url := config.Matrix.Server + "/_matrix/client/r0/rooms/" + config.Matrix.RoomId + "/send/m.room.message/" + txnId + "?access_token=" + matrixToken.AccessToken + jsonStr := `{ + "body":"` + time.Now().Format(defaultTimeFormat) + `: ` + msg + `", + "msgtype":"m.text" + }` + b := strings.NewReader(jsonStr) + req, _ := http.NewRequest("PUT", url, b) + req.Header.Set("Content-Type", "application/json") + res, err := http.DefaultClient.Do(req) + if err != nil { + log.Println(err) + } + defer res.Body.Close() + body, _ := ioutil.ReadAll(res.Body) + + fmt.Println(string(body)) + fmt.Print("msg sent to Matrix: ") + color.Green(msg) + +} + +func matrixSendNotice(msg string) { + txnId := strconv.Itoa(rand.Int()) + url := config.Matrix.Server + "/_matrix/client/r0/rooms/" + config.Matrix.RoomId + "/send/m.room.message/" + txnId + "?access_token=" + matrixToken.AccessToken + jsonStr := `{ + "body":"` + time.Now().Format(defaultTimeFormat) + `: ` + msg + `", + "msgtype":"m.notice" + }` + b := strings.NewReader(jsonStr) + req, _ := http.NewRequest("PUT", url, b) + req.Header.Set("Content-Type", "application/json") + res, err := http.DefaultClient.Do(req) + if err != nil { + log.Println(err) + } + defer res.Body.Close() + body, _ := ioutil.ReadAll(res.Body) + + fmt.Println(string(body)) + fmt.Print("msg sent to Matrix: ") + color.Green(msg) + +}