diff --git a/conf.yaml b/conf.yaml index b7f9d98..688dd25 100644 --- a/conf.yaml +++ b/conf.yaml @@ -9,6 +9,8 @@ IDE: port: 80 uri: / method: HEAD + interval: 5 + timeout: 2 PLOOPI: tables: @@ -19,6 +21,8 @@ PLOOPI: check: type: tcp port: 80 + interval: 5 + timeout: 2 SMTP: tables: @@ -29,4 +33,6 @@ SMTP: check: type: smtp port: 25 + interval: 5 + timeout: 2 diff --git a/main.go b/main.go index 019f461..97441bf 100644 --- a/main.go +++ b/main.go @@ -7,13 +7,17 @@ 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"` + 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"` @@ -24,36 +28,87 @@ type Group struct { func main() { log.Println("Starting") + var waitGroup sync.WaitGroup + var conf map[string]Group yamlFile, err := ioutil.ReadFile("conf.yaml") if err != nil { - log.Printf("Configuration open error #%v ", err) + 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) - go checkGroup(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(group Group) { +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 { - client := &http.Client{ - Timeout: time.Second * 5, - } - resp, err := client.Head(fmt.Sprintf("http://%s", host)) - if err != nil { - log.Println(host, "Failed") - } else { - _, _ = io.ReadAll(resp.Body) - resp.Body.Close() - log.Println(host, "Status", resp.StatusCode) - } + 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) + } + } }