package main import "fmt" import "net/http" import "io" import "io/ioutil" import "log" import "gopkg.in/yaml.v3" import "time" import "sync" type Check struct { Type string `yaml:"type"` Port int `yaml:"port"` Uri string `yaml:"uri"` Method string `yaml:"method"` Timeout int `yaml:"timeout"` Interval int `yaml:"interval"` } type Group struct { Name string `yaml:"group"` Tables []string `yaml:"tables"` Hosts []string `yaml:"hosts"` Check Check `yaml:"check"` } func main() { log.Println("Starting") var waitGroup sync.WaitGroup var conf map[string]Group yamlFile, err := ioutil.ReadFile("conf.yaml") if err != nil { log.Fatalf("Configuration open error #%v ", err) } err = yaml.Unmarshal(yamlFile, &conf) if err != nil { log.Fatalf("Configuration read error #%v", err) } stopChannel := make(chan bool) for name, group := range conf { log.Println("Checking group", name, group) waitGroup.Add(1) go checkGroup(name, group, &waitGroup, stopChannel) } time.Sleep(5 * time.Second) log.Println("main closing stopChannel") close(stopChannel) waitGroup.Wait() } func checkGroup(name string, group Group, waitGroup *sync.WaitGroup, stopChannel chan bool) { channels := make(map[string]chan int) var checkHostWaitGroup sync.WaitGroup for _, host := range group.Hosts { channel := make(chan int, 1) channels[host] = channel checkHostWaitGroup.Add(1) go checkHost(channels[host], name, host, group.Check, &checkHostWaitGroup, stopChannel) } for { select { case <-stopChannel: log.Println("checkGroup", name, "stopChannel") checkHostWaitGroup.Wait() waitGroup.Done() return break default: for host, channel := range channels { select { case stop := <-stopChannel: log.Println("checkGroup", name, "stopChannel", stop) break case status := <-channel: log.Println("Status for ", host, "is", status) default: time.Sleep(100 * time.Millisecond) } } } } } func checkHost(status chan<- int,group string, host string, check Check, waitGroup *sync.WaitGroup, stopChannel chan bool) { client := &http.Client{ Timeout: time.Second * time.Duration(check.Timeout), } for { select { case <-stopChannel: log.Println("checkHost", host, "group", group, "stopChannel") waitGroup.Done() return default: resp, err := client.Head(fmt.Sprintf("http://%s", host)) if err != nil { log.Println(host, "Failed") status <- 1 } else { status <- 0 _, _ = io.ReadAll(resp.Body) resp.Body.Close() log.Println(host, "Status", resp.StatusCode) } time.Sleep(time.Duration(check.Interval) * time.Second) } } }