aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitchell Riedstra <mitch@riedstra.dev>2021-01-24 16:51:48 -0500
committerMitchell Riedstra <mitch@riedstra.dev>2021-01-24 16:51:48 -0500
commit9c8cc14958c248ddba1669becb5e026d43dd997c (patch)
treef0639dcbfbc5adf9b715f39caa8a1ce9cb3737b4
parent023ce2fd00c2269202969c1750e237a6c9c8f985 (diff)
downloadcheckup-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.go26
-rw-r--r--cmd/main/http.go26
-rw-r--r--cmd/main/main.go97
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)
+ }
}