176 lines
4.0 KiB
Go
176 lines
4.0 KiB
Go
package cachet
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"io/ioutil"
|
|
"net"
|
|
"net/http"
|
|
"net/url"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/castawaylabs/cachet-monitor/backends"
|
|
cachetbackend "github.com/castawaylabs/cachet-monitor/backends/cachet"
|
|
"github.com/castawaylabs/cachet-monitor/monitors"
|
|
|
|
"github.com/mitchellh/mapstructure"
|
|
"github.com/sirupsen/logrus"
|
|
yaml "gopkg.in/yaml.v2"
|
|
)
|
|
|
|
type CachetMonitor struct {
|
|
RawMonitors []map[string]interface{} `json:"monitors" yaml:"monitors"`
|
|
RawBackend map[string]interface{} `json:"backend" yaml:"backend"`
|
|
|
|
SystemName string `json:"system_name" yaml:"system_name"`
|
|
Backend backends.BackendInterface `json:"-" yaml:"-"`
|
|
Monitors []monitors.MonitorInterface `json:"-" yaml:"-"`
|
|
Immediate bool `json:"-" yaml:"-"`
|
|
}
|
|
|
|
func New(path string) (*CachetMonitor, error) {
|
|
var cfg *CachetMonitor
|
|
var data []byte
|
|
|
|
// test if its a url
|
|
url, err := url.ParseRequestURI(path)
|
|
if err == nil && len(url.Scheme) > 0 {
|
|
// download config
|
|
response, err := http.Get(path)
|
|
if err != nil {
|
|
logrus.Warn("Unable to download network configuration")
|
|
return nil, err
|
|
}
|
|
|
|
defer response.Body.Close()
|
|
data, _ = ioutil.ReadAll(response.Body)
|
|
|
|
logrus.Info("Downloaded network configuration.")
|
|
} else {
|
|
data, err = ioutil.ReadFile(path)
|
|
if err != nil {
|
|
return nil, errors.New("Unable to open file: '" + path + "'")
|
|
}
|
|
}
|
|
|
|
if strings.HasSuffix(path, ".yaml") || strings.HasSuffix(path, ".yml") {
|
|
err = yaml.Unmarshal(data, &cfg)
|
|
} else {
|
|
err = json.Unmarshal(data, &cfg)
|
|
}
|
|
|
|
if err != nil {
|
|
logrus.Warnf("Unable to parse configuration file")
|
|
return nil, err
|
|
}
|
|
|
|
// get default type
|
|
if backend, ok := cfg.RawBackend["type"].(string); !ok {
|
|
err = errors.New("Cannot determine backend type")
|
|
} else {
|
|
switch backend {
|
|
case "cachet":
|
|
var backend cachetbackend.CachetBackend
|
|
err = mapstructure.Decode(cfg.RawBackend, &backend)
|
|
cfg.Backend = &backend
|
|
// backend.config = cfg
|
|
default:
|
|
err = errors.New("Invalid backend type: %v" + backend)
|
|
}
|
|
}
|
|
|
|
if errs := cfg.Backend.Validate(); len(errs) > 0 {
|
|
logrus.Errorf("Backend validation errors: %v", errs)
|
|
os.Exit(1)
|
|
}
|
|
|
|
if err != nil {
|
|
logrus.Errorf("Unable to unmarshal backend: %v", err)
|
|
return nil, err
|
|
}
|
|
|
|
cfg.Monitors = make([]monitors.MonitorInterface, len(cfg.RawMonitors))
|
|
for index, rawMonitor := range cfg.RawMonitors {
|
|
var t monitors.MonitorInterface
|
|
|
|
// get default type
|
|
monType := GetMonitorType("")
|
|
if t, ok := rawMonitor["type"].(string); ok {
|
|
monType = GetMonitorType(t)
|
|
}
|
|
|
|
switch monType {
|
|
case "http":
|
|
var mon monitors.HTTPMonitor
|
|
err = mapstructure.Decode(rawMonitor, &mon)
|
|
t = &mon
|
|
case "dns":
|
|
var mon monitors.DNSMonitor
|
|
err = mapstructure.Decode(rawMonitor, &mon)
|
|
t = &mon
|
|
default:
|
|
logrus.Errorf("Invalid monitor type (index: %d) %v", index, monType)
|
|
continue
|
|
}
|
|
|
|
if err != nil {
|
|
logrus.Errorf("Unable to unmarshal monitor to type (index: %d): %v", index, err)
|
|
continue
|
|
}
|
|
|
|
mon := t.GetMonitor()
|
|
mon.Type = monType
|
|
cfg.Monitors[index] = t
|
|
}
|
|
|
|
return cfg, err
|
|
}
|
|
|
|
// Validate configuration
|
|
func (cfg *CachetMonitor) Validate() bool {
|
|
valid := true
|
|
|
|
if len(cfg.SystemName) == 0 {
|
|
// get hostname
|
|
cfg.SystemName = getHostname()
|
|
}
|
|
|
|
if len(cfg.Monitors) == 0 {
|
|
logrus.Warnf("No monitors defined!\nSee help for example configuration")
|
|
valid = false
|
|
}
|
|
|
|
for index, monitor := range cfg.Monitors {
|
|
if errs := monitor.Validate(cfg.Backend.ValidateMonitor); len(errs) > 0 {
|
|
logrus.Warnf("Monitor validation errors (index %d): %v", index, "\n - "+strings.Join(errs, "\n - "))
|
|
valid = false
|
|
}
|
|
}
|
|
|
|
return valid
|
|
}
|
|
|
|
// getHostname returns id of the current system
|
|
func getHostname() string {
|
|
hostname, err := os.Hostname()
|
|
if err == nil && len(hostname) > 0 {
|
|
return hostname
|
|
}
|
|
|
|
addrs, err := net.InterfaceAddrs()
|
|
if err != nil || len(addrs) == 0 {
|
|
return "unknown"
|
|
}
|
|
|
|
return addrs[0].String()
|
|
}
|
|
|
|
func GetMonitorType(t string) string {
|
|
if len(t) == 0 {
|
|
return "http"
|
|
}
|
|
|
|
return strings.ToLower(t)
|
|
}
|