From b7609e24da4442c9ee336e83751d252e68d6e6f0 Mon Sep 17 00:00:00 2001 From: Kegan Myers Date: Sat, 22 Aug 2015 19:35:33 -0500 Subject: [PATCH] refactor configuration format to allow multiple checks --- main.go | 19 +++++++++++++------ monitor/cloudflare.go | 26 +++++++++++++++----------- monitor/config.go | 29 +++++++++++++++-------------- monitor/createCheck.go | 4 ++-- monitor/engine.go | 7 ++----- monitor/handler.go | 14 ++++++++++++-- monitor/log.go | 2 +- 7 files changed, 60 insertions(+), 41 deletions(-) diff --git a/main.go b/main.go index ed76fc9..5675f13 100644 --- a/main.go +++ b/main.go @@ -17,14 +17,21 @@ func main() { c := monitor.Config{} json.Unmarshal(file, &c) - handlers := make([]monitor.GenericHandler, 2) - handlers[0] = monitor.NewLogHandler() - handlers[1] = monitor.NewCloudflareHandler(c.Cloudflare) + for _, check := range c.Checks { + handlers := make([]*monitor.GenericHandler, 0) - engine := monitor.CreateEngine(handlers) + for _, reaction := range check.Reactions { + handler := monitor.CreateHandler(reaction) - for _, endpoint := range c.Hosts { - monitor.CreateCheck(c.Interval, engine, endpoint) + if handler == nil { + continue + } + + handlers = append(handlers, handler) + } + + engine := monitor.CreateEngine(handlers) + monitor.CreateCheck(check.Interval, engine, check.Target) } select{} diff --git a/monitor/cloudflare.go b/monitor/cloudflare.go index 5ff1f26..fd964b2 100644 --- a/monitor/cloudflare.go +++ b/monitor/cloudflare.go @@ -6,16 +6,20 @@ import ( "fmt" ) -func NewCloudflareHandler(config CloudflareConfig) GenericHandler { +func newCloudflareHandler(config ReactionConfig) *GenericHandler { + if config.Options["email"] == "" || config.Options["apiKey"] == "" || config.Options["domain"] == "" || config.Options["name"] == "" || config.Options["ttl"] == "" { + log.Fatal(fmt.Sprintf("Misconfigured cloudflare handler: %#v", config)) + } + return runHandler(make(chan Transition, 5), &cloudflareHandler{ config, - cloudflare.NewClient(config.Email, config.ApiKey), + cloudflare.NewClient(config.Options["email"], config.Options["apiKey"]), make(map[string]bool), }) } type cloudflareHandler struct{ - config CloudflareConfig + config ReactionConfig client *cloudflare.Client actuallyDownHosts map[string]bool } @@ -26,20 +30,20 @@ func (this *cloudflareHandler) handle(transition Transition) { log.Print(fmt.Sprintf( "Removed cloudflare record for `%s`: `%v`\n", transition.RecordValue, - removeCloudflareRecord(this.client, this.config, transition.RecordValue))) + this.removeCloudflareRecord(transition.RecordValue))) case Up: log.Print(fmt.Sprintf( "Added cloudflare record for `%s`: `%v`\n", transition.RecordValue, - addCloudflareRecord(this.client, this.config, transition.RecordValue))) + this.addCloudflareRecord(transition.RecordValue))) case Unknown: //just leave it how it was, going up/down is idempotent anyways } } -func removeCloudflareRecord(client *cloudflare.Client, config CloudflareConfig, recordValue string) bool { - records, err := client.RetrieveRecordsByName(config.Domain, config.Name) +func (this *cloudflareHandler) removeCloudflareRecord(recordValue string) bool { + records, err := this.client.RetrieveRecordsByName(this.config.Options["Domain"], this.config.Options["Name"]) if err != nil { return false @@ -51,22 +55,22 @@ func removeCloudflareRecord(client *cloudflare.Client, config CloudflareConfig, continue } - exitStatus = exitStatus && client.DestroyRecord(config.Domain, record.Id) == nil + exitStatus = exitStatus && this.client.DestroyRecord(this.config.Options["domain"], record.Id) == nil } return exitStatus } -func addCloudflareRecord(client *cloudflare.Client, config CloudflareConfig, recordValue string) bool { +func (this *cloudflareHandler) addCloudflareRecord(recordValue string) bool { opts := cloudflare.CreateRecord{ "A", - config.Name, + this.config.Options["name"], recordValue, "1", "0", } - _, err := client.CreateRecord(config.Domain, &opts) + _, err := this.client.CreateRecord(this.config.Options["domain"], &opts) if err != nil { return fmt.Sprintf("%s", err) == "API Error: The record already exists." diff --git a/monitor/config.go b/monitor/config.go index 523f492..efc4b12 100644 --- a/monitor/config.go +++ b/monitor/config.go @@ -1,21 +1,22 @@ package monitor -type HostConfig struct { - Host string +type Config struct { + Checks []CheckConfig +} + +type CheckConfig struct { + Interval uint16 + Target TargetConfig + Reactions []ReactionConfig +} + +type TargetConfig struct { Type string + Host string Options map[string]string } -type CloudflareConfig struct { - Email string - ApiKey string - Domain string - Name string - Ttl string -} - -type Config struct { - Cloudflare CloudflareConfig - Hosts []HostConfig - Interval uint16 +type ReactionConfig struct { + Type string + Options map[string]string } diff --git a/monitor/createCheck.go b/monitor/createCheck.go index cf6459b..ea5bfd0 100644 --- a/monitor/createCheck.go +++ b/monitor/createCheck.go @@ -10,7 +10,7 @@ import ( type checkConfig struct { engine *Engine interval time.Duration - host HostConfig + host TargetConfig } type httpChecker struct { @@ -57,7 +57,7 @@ func newHttpChecker(config checkConfig) *httpChecker { return &checker } -func CreateCheck(interval uint16, engine *Engine, host HostConfig) { +func CreateCheck(interval uint16, engine *Engine, host TargetConfig) { config := checkConfig{ engine, time.Duration(int64(interval)) * time.Second, diff --git a/monitor/engine.go b/monitor/engine.go index 98e29ad..a7e3484 100644 --- a/monitor/engine.go +++ b/monitor/engine.go @@ -1,14 +1,11 @@ package monitor -import ( -) - type Engine struct { Input chan Result - output []GenericHandler + output []*GenericHandler } -func CreateEngine(handlers []GenericHandler) *Engine { +func CreateEngine(handlers []*GenericHandler) *Engine { input := make(chan Result) engine := Engine{ diff --git a/monitor/handler.go b/monitor/handler.go index 99b27c4..149973c 100644 --- a/monitor/handler.go +++ b/monitor/handler.go @@ -8,13 +8,23 @@ type GenericHandler struct { channel chan Transition } -func runHandler(input chan Transition, handler handler) GenericHandler { +func runHandler(input chan Transition, handler handler) *GenericHandler { go func() { for true { handler.handle(<-input) } }() - return GenericHandler{ + return &GenericHandler{ input, } } + +func CreateHandler(handler ReactionConfig) *GenericHandler { + switch handler.Type { + case "cloudflare": + return newCloudflareHandler(handler) + case "log": + return newLogHandler(handler) + } + return nil +} diff --git a/monitor/log.go b/monitor/log.go index 9be1b92..8d2feac 100644 --- a/monitor/log.go +++ b/monitor/log.go @@ -5,7 +5,7 @@ import ( "log" ) -func NewLogHandler() GenericHandler { +func newLogHandler(config ReactionConfig) *GenericHandler { return runHandler(make(chan Transition), &logHandler{}) }