refactor configuration format to allow multiple checks

This commit is contained in:
Kegan Myers 2015-08-22 19:35:33 -05:00
parent 619bb2e023
commit b7609e24da
7 changed files with 60 additions and 41 deletions

19
main.go
View file

@ -17,14 +17,21 @@ func main() {
c := monitor.Config{} c := monitor.Config{}
json.Unmarshal(file, &c) json.Unmarshal(file, &c)
handlers := make([]monitor.GenericHandler, 2) for _, check := range c.Checks {
handlers[0] = monitor.NewLogHandler() handlers := make([]*monitor.GenericHandler, 0)
handlers[1] = monitor.NewCloudflareHandler(c.Cloudflare)
engine := monitor.CreateEngine(handlers) for _, reaction := range check.Reactions {
handler := monitor.CreateHandler(reaction)
for _, endpoint := range c.Hosts { if handler == nil {
monitor.CreateCheck(c.Interval, engine, endpoint) continue
}
handlers = append(handlers, handler)
}
engine := monitor.CreateEngine(handlers)
monitor.CreateCheck(check.Interval, engine, check.Target)
} }
select{} select{}

View file

@ -6,16 +6,20 @@ import (
"fmt" "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{ return runHandler(make(chan Transition, 5), &cloudflareHandler{
config, config,
cloudflare.NewClient(config.Email, config.ApiKey), cloudflare.NewClient(config.Options["email"], config.Options["apiKey"]),
make(map[string]bool), make(map[string]bool),
}) })
} }
type cloudflareHandler struct{ type cloudflareHandler struct{
config CloudflareConfig config ReactionConfig
client *cloudflare.Client client *cloudflare.Client
actuallyDownHosts map[string]bool actuallyDownHosts map[string]bool
} }
@ -26,20 +30,20 @@ func (this *cloudflareHandler) handle(transition Transition) {
log.Print(fmt.Sprintf( log.Print(fmt.Sprintf(
"Removed cloudflare record for `%s`: `%v`\n", "Removed cloudflare record for `%s`: `%v`\n",
transition.RecordValue, transition.RecordValue,
removeCloudflareRecord(this.client, this.config, transition.RecordValue))) this.removeCloudflareRecord(transition.RecordValue)))
case Up: case Up:
log.Print(fmt.Sprintf( log.Print(fmt.Sprintf(
"Added cloudflare record for `%s`: `%v`\n", "Added cloudflare record for `%s`: `%v`\n",
transition.RecordValue, 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 case Unknown: //just leave it how it was, going up/down is idempotent anyways
} }
} }
func removeCloudflareRecord(client *cloudflare.Client, config CloudflareConfig, recordValue string) bool { func (this *cloudflareHandler) removeCloudflareRecord(recordValue string) bool {
records, err := client.RetrieveRecordsByName(config.Domain, config.Name) records, err := this.client.RetrieveRecordsByName(this.config.Options["Domain"], this.config.Options["Name"])
if err != nil { if err != nil {
return false return false
@ -51,22 +55,22 @@ func removeCloudflareRecord(client *cloudflare.Client, config CloudflareConfig,
continue continue
} }
exitStatus = exitStatus && client.DestroyRecord(config.Domain, record.Id) == nil exitStatus = exitStatus && this.client.DestroyRecord(this.config.Options["domain"], record.Id) == nil
} }
return exitStatus return exitStatus
} }
func addCloudflareRecord(client *cloudflare.Client, config CloudflareConfig, recordValue string) bool { func (this *cloudflareHandler) addCloudflareRecord(recordValue string) bool {
opts := cloudflare.CreateRecord{ opts := cloudflare.CreateRecord{
"A", "A",
config.Name, this.config.Options["name"],
recordValue, recordValue,
"1", "1",
"0", "0",
} }
_, err := client.CreateRecord(config.Domain, &opts) _, err := this.client.CreateRecord(this.config.Options["domain"], &opts)
if err != nil { if err != nil {
return fmt.Sprintf("%s", err) == "API Error: The record already exists." return fmt.Sprintf("%s", err) == "API Error: The record already exists."

View file

@ -1,21 +1,22 @@
package monitor package monitor
type HostConfig struct { type Config struct {
Host string Checks []CheckConfig
}
type CheckConfig struct {
Interval uint16
Target TargetConfig
Reactions []ReactionConfig
}
type TargetConfig struct {
Type string Type string
Host string
Options map[string]string Options map[string]string
} }
type CloudflareConfig struct { type ReactionConfig struct {
Email string Type string
ApiKey string Options map[string]string
Domain string
Name string
Ttl string
}
type Config struct {
Cloudflare CloudflareConfig
Hosts []HostConfig
Interval uint16
} }

View file

@ -10,7 +10,7 @@ import (
type checkConfig struct { type checkConfig struct {
engine *Engine engine *Engine
interval time.Duration interval time.Duration
host HostConfig host TargetConfig
} }
type httpChecker struct { type httpChecker struct {
@ -57,7 +57,7 @@ func newHttpChecker(config checkConfig) *httpChecker {
return &checker return &checker
} }
func CreateCheck(interval uint16, engine *Engine, host HostConfig) { func CreateCheck(interval uint16, engine *Engine, host TargetConfig) {
config := checkConfig{ config := checkConfig{
engine, engine,
time.Duration(int64(interval)) * time.Second, time.Duration(int64(interval)) * time.Second,

View file

@ -1,14 +1,11 @@
package monitor package monitor
import (
)
type Engine struct { type Engine struct {
Input chan Result Input chan Result
output []GenericHandler output []*GenericHandler
} }
func CreateEngine(handlers []GenericHandler) *Engine { func CreateEngine(handlers []*GenericHandler) *Engine {
input := make(chan Result) input := make(chan Result)
engine := Engine{ engine := Engine{

View file

@ -8,13 +8,23 @@ type GenericHandler struct {
channel chan Transition channel chan Transition
} }
func runHandler(input chan Transition, handler handler) GenericHandler { func runHandler(input chan Transition, handler handler) *GenericHandler {
go func() { go func() {
for true { for true {
handler.handle(<-input) handler.handle(<-input)
} }
}() }()
return GenericHandler{ return &GenericHandler{
input, input,
} }
} }
func CreateHandler(handler ReactionConfig) *GenericHandler {
switch handler.Type {
case "cloudflare":
return newCloudflareHandler(handler)
case "log":
return newLogHandler(handler)
}
return nil
}

View file

@ -5,7 +5,7 @@ import (
"log" "log"
) )
func NewLogHandler() GenericHandler { func newLogHandler(config ReactionConfig) *GenericHandler {
return runHandler(make(chan Transition), &logHandler{}) return runHandler(make(chan Transition), &logHandler{})
} }