You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
2.3 KiB

package main
import (
"context"
"io/ioutil"
"net"
"strconv"
"strings"
"time"
"github.com/pkg/errors"
"gopkg.in/yaml.v2"
)
var monitorMap = map[string]monitor{
"ping": &pingMonitor{},
}
type agent struct {
config agentConfig
debug bool
}
type agentConfig struct {
Listen string `yaml:"listen"`
Monitors []monitorConfig `yaml:"monitors"`
Alerters []alerterConfig `yaml:"alerters"`
}
type baseConfig struct {
Name string `yaml:"name"`
Type string `yaml:"type"`
Params map[string]interface{} `yaml:"parameters"`
}
type monitorConfig struct {
baseConfig `yaml:",inline"`
Interval time.Duration `yaml:"interval"`
}
type alerterConfig struct {
baseConfig `yaml:",inline"`
MinInterval time.Duration `yaml:"min_interval"`
ThrottleAfter uint `yaml:"throttle_after"`
ThrottleDeadline time.Duration `yaml:"throttle_deadline"`
}
func (a *agent) parseConfig(filename string) error {
content, err := ioutil.ReadFile(filename)
if err != nil {
return err
}
return yaml.Unmarshal(content, &a.config)
}
func (ac *agentConfig) validate() error {
// assumes the config has already been parsed
parts := strings.SplitN(strings.TrimSpace(ac.Listen), ":", 2)
if len(parts) != 2 {
return errors.Errorf("missing optional host, or mandatory port in listen directive: %q", ac.Listen)
}
if parts[0] != "" {
ip := net.ParseIP(parts[0])
if ip == nil || len(ip) < 4 {
return errors.Errorf("IP address %q does not parse as an IPv4 or IPv6 address", parts[0])
}
}
if _, err := strconv.ParseUint(parts[1], 10, 32); err != nil {
return errors.Wrap(err, "invalid port in listen directive")
}
return nil
}
func (a *agent) boot(ctx context.Context) error {
<-ctx.Done()
return ctx.Err()
}
func (ac *agentConfig) assembleMonitors() ([]monitor, error) {
monitors := []monitor{}
for _, mc := range ac.Monitors {
if mc.baseConfig.Name == "" || mc.baseConfig.Type == "" {
return nil, errors.New("invalid configuration file: missing a type and/or name")
}
res, ok := monitorMap[mc.baseConfig.Type]
if !ok {
return nil, errors.Errorf("invalid monitor type %q for name %q", mc.baseConfig.Type, mc.baseConfig.Name)
}
monitor := res.New()
if err := monitor.FromConfig(mc); err != nil {
return nil, err
}
monitors = append(monitors, monitor)
}
return monitors, nil
}