diff options
| author | Mitchell Riedstra <mitch@riedstra.dev> | 2021-01-24 16:51:48 -0500 |
|---|---|---|
| committer | Mitchell Riedstra <mitch@riedstra.dev> | 2021-01-24 16:51:48 -0500 |
| commit | 9c8cc14958c248ddba1669becb5e026d43dd997c (patch) | |
| tree | f0639dcbfbc5adf9b715f39caa8a1ce9cb3737b4 | |
| parent | 023ce2fd00c2269202969c1750e237a6c9c8f985 (diff) | |
| download | checkup-9c8cc14958c248ddba1669becb5e026d43dd997c.tar.gz checkup-9c8cc14958c248ddba1669becb5e026d43dd997c.tar.xz | |
Keep track of previous errors, default to running as a foreground service
| -rw-r--r-- | cmd/main/certs.go | 26 | ||||
| -rw-r--r-- | cmd/main/http.go | 26 | ||||
| -rw-r--r-- | cmd/main/main.go | 97 |
3 files changed, 122 insertions, 27 deletions
diff --git a/cmd/main/certs.go b/cmd/main/certs.go index 66fe0cd..41ed1a8 100644 --- a/cmd/main/certs.go +++ b/cmd/main/certs.go @@ -13,12 +13,16 @@ type certCheck struct { Window time.Duration } -func certWorker(jobs <-chan certCheck, msg chan<- *string) { +func certWorker(jobs <-chan certCheck, msg chan<- *jobResponse) { for cc := range jobs { conn, err := checkup.CertExpiresSoon(cc.Host, cc.Port, cc.Window) if err != nil { - s := fmt.Sprintf("%s:%s --> %s\n", cc.Host, cc.Port, err) - msg <- &s + s := fmt.Sprintf("%s:%s --> %s", cc.Host, cc.Port, err) + msg <- &jobResponse{ + Id: cc.Host + ":" + cc.Port, + Message: s, + Err: err, + } continue } conn.Close() @@ -26,11 +30,11 @@ func certWorker(jobs <-chan certCheck, msg chan<- *string) { } } -func checkCerts(conf *Config) { +func checkCerts(conf *Config) map[string]*jobResponse { buf := &bytes.Buffer{} cc := make(chan certCheck) - msgs := make(chan *string) + msgs := make(chan *jobResponse) for i := 1; i <= conf.Workers; i++ { go certWorker(cc, msgs) @@ -47,12 +51,16 @@ func checkCerts(conf *Config) { close(cc) }() + out := make(map[string]*jobResponse) for i := 0; i < len(conf.CheckCerts); i++ { - m := <-msgs - if m != nil { - buf.Write([]byte(*m)) + resp := <-msgs + if resp != nil { + buf.Write([]byte(resp.Message)) + out[resp.Id] = resp } } - notify(conf, buf.Bytes()) + // notify(conf, buf.Bytes()) + + return out } diff --git a/cmd/main/http.go b/cmd/main/http.go index ce31495..94d6ae5 100644 --- a/cmd/main/http.go +++ b/cmd/main/http.go @@ -12,24 +12,28 @@ type httpCheck struct { Code int } -func httpStatusWorker(jobs <-chan httpCheck, msg chan<- *string) { +func httpStatusWorker(jobs <-chan httpCheck, msg chan<- *jobResponse) { for hc := range jobs { err := checkup.HttpStatusOK(hc.URL, hc.Code) if err != nil { - s := fmt.Sprintf("Checking: %s, %v\n", + s := fmt.Sprintf("Checking: %s, %v", hc.URL, err) - msg <- &s + msg <- &jobResponse{ + Id: hc.URL + "->" + string(hc.Code), + Message: s, + Err: err, + } continue } msg <- nil } } -func checkStatus(conf *Config) { +func checkStatus(conf *Config) map[string]*jobResponse { buf := &bytes.Buffer{} hc := make(chan httpCheck) - msgs := make(chan *string) + msgs := make(chan *jobResponse) for i := 1; i <= conf.Workers; i++ { go httpStatusWorker(hc, msgs) @@ -45,12 +49,16 @@ func checkStatus(conf *Config) { close(hc) }() + out := make(map[string]*jobResponse) for i := 0; i < len(conf.StatusChecks); i++ { - m := <-msgs - if m != nil { - buf.Write([]byte(*m)) + resp := <-msgs + if resp != nil { + buf.Write([]byte(resp.Message)) + out[resp.Id] = resp } } - notify(conf, buf.Bytes()) + // notify(conf, buf.Bytes()) + + return out } diff --git a/cmd/main/main.go b/cmd/main/main.go index 2e11184..34fc6f4 100644 --- a/cmd/main/main.go +++ b/cmd/main/main.go @@ -1,16 +1,26 @@ package main import ( + "bytes" "flag" "fmt" "gopkg.in/yaml.v3" "os" + "time" "riedstra.dev/go/checkup" ) var Version = "Development" +// jobResponse lets us return a bit more info from each of the jobs +// and track how the response has changed +type jobResponse struct { + Id string + Message string + Err error +} + type Config struct { RocketChatURL string `yaml:"RocketChatURL"` DiscordURL string `yaml:"DiscordURL"` @@ -20,18 +30,63 @@ type Config struct { ExpectedStatusCode int `yaml:"ExpectedStatusCode"` StatusChecks map[string]*int `yaml:"StatusChecks"` Workers int `yaml:"Workers"` + Interval int `yaml:"Interval"` } -func ReadConfig(fn string) (*Config, error) { +func ReadConfig(fn string, conf *Config) error { fh, err := os.Open(fn) if err != nil { - return nil, err + return err } dec := yaml.NewDecoder(fh) - conf := &Config{} err = dec.Decode(conf) - return conf, err + return err +} + +func jobNotifyDedup(conf *Config, prevJobs, newJobs map[string]*jobResponse) { + buf := &bytes.Buffer{} + + for id, resp := range newJobs { + oldresp, ok := prevJobs[id] + if !ok { + buf.Write([]byte(resp.Message)) + buf.Write([]byte{'\n'}) + continue + } + + if oldresp.Message == resp.Message { + continue + } + + buf.Write([]byte( + oldresp.Message + " now --> " + resp.Message, + )) + buf.Write([]byte{'\n'}) + } + + for id, resp := range prevJobs { + _, ok := newJobs[id] + if !ok { + buf.Write([]byte( + "[CLEARED]: " + resp.Message + "\n", + )) + } + } + + fmt.Print(string(buf.Bytes())) + notify(conf, buf.Bytes()) +} + +func jobNotify(conf *Config, jobs map[string]*jobResponse) { + buf := &bytes.Buffer{} + + for _, resp := range jobs { + buf.Write([]byte(resp.Message)) + buf.Write([]byte{'\n'}) + } + + notify(conf, buf.Bytes()) } func notify(conf *Config, b []byte) { @@ -62,6 +117,7 @@ func main() { confFn := fl.String("c", "config.yml", "Configuration file path") version := fl.Bool("v", false, "Print version and exit") + once := fl.Bool("o", false, "Run once then exit") _ = fl.Parse(os.Args[1:]) @@ -70,17 +126,40 @@ func main() { os.Exit(0) } - conf, err := ReadConfig(*confFn) + // Defaults to be overridden by config + conf := &Config{ + Workers: 1, + DefaultCertPort: "443", + CertWindow: 15, + ExpectedStatusCode: 200, + Interval: 60, + } + + err := ReadConfig(*confFn, conf) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } - if conf.Workers == 0 { - conf.Workers = 1 + if *once { + jobNotify(conf, checkCerts(conf)) + jobNotify(conf, checkStatus(conf)) + os.Exit(0) } - checkCerts(conf) - checkStatus(conf) + certsPrev := map[string]*jobResponse{} + statusPrev := map[string]*jobResponse{} + for { + cert := checkCerts(conf) + status := checkStatus(conf) + + jobNotifyDedup(conf, certsPrev, cert) + jobNotifyDedup(conf, statusPrev, status) + + certsPrev = cert + statusPrev = status + + time.Sleep(time.Duration(conf.Interval) * time.Second) + } } |
