package main import ( "fmt" "strings" "time" "git.sr.ht/~emersion/go-scfg" ) type alertMode int const ( single alertMode = iota multi ) type config struct { BaseURL string HTTPAddress string LogLevel string alertMode alertMode User string Password string ntfy ntfyConfig labels labels cache cacheConfig am alertmanagerConfig resolved resolvedConfig } type ntfyConfig struct { Topic string User string Password string } type labels struct { Order []string Label map[string]labelConfig } type labelConfig struct { Priority string Tags []string } type cacheConfig struct { CleanupInterval time.Duration Duration time.Duration } type alertmanagerConfig struct { User string Password string SilenceDuration time.Duration URL string } type resolvedConfig struct { Tags []string } func readConfig(path string) (*config, error) { cfg, err := scfg.Load(path) if err != nil { return nil, err } config := new(config) // Set default values config.HTTPAddress = "127.0.0.1:8080" config.LogLevel = "info" config.alertMode = single config.cache.CleanupInterval = time.Hour config.cache.Duration = time.Hour * 24 d := cfg.Get("log-level") if d != nil { if err := d.ParseParams(&config.LogLevel); err != nil { return nil, err } } d = cfg.Get("http-address") if d != nil { if err := d.ParseParams(&config.HTTPAddress); err != nil { return nil, err } } d = cfg.Get("base-url") if d != nil { if err := d.ParseParams(&config.BaseURL); err != nil { return nil, err } } d = cfg.Get("alert-mode") if d != nil { var mode string if err := d.ParseParams(&mode); err != nil { return nil, err } switch strings.ToLower(mode) { case "single": config.alertMode = single case "multi": config.alertMode = multi default: return nil, fmt.Errorf("%q directive: illegal mode %q", d.Name, mode) } } d = cfg.Get("user") if d != nil { if err := d.ParseParams(&config.User); err != nil { return nil, err } } d = cfg.Get("password") if d != nil { if err := d.ParseParams(&config.Password); err != nil { return nil, err } } labelsDir := cfg.Get("labels") if labelsDir != nil { d = labelsDir.Children.Get("order") if d != nil { var order string if err := d.ParseParams(&order); err != nil { return nil, err } config.labels.Order = strings.Split(order, ",") } labels := make(map[string]labelConfig) for _, labelName := range config.labels.Order { for _, labelDir := range labelsDir.Children.GetAll(labelName) { labelConfig := new(labelConfig) var name string if err := labelDir.ParseParams(&name); err != nil { return nil, err } d = labelDir.Children.Get("priority") if d != nil { if err := d.ParseParams(&labelConfig.Priority); err != nil { return nil, err } } d = labelDir.Children.Get("tags") if d != nil { var tags string if err := d.ParseParams(&tags); err != nil { return nil, err } labelConfig.Tags = strings.Split(tags, ",") } labels[fmt.Sprintf("%s:%s", labelName, name)] = *labelConfig } } config.labels.Label = labels } ntfyDir := cfg.Get("ntfy") if ntfyDir == nil { return nil, fmt.Errorf("%q directive missing", "ntfy") } d = ntfyDir.Children.Get("topic") if d == nil { return nil, fmt.Errorf("%q missing from %q directive", "topic", "ntfy") } if err := d.ParseParams(&config.ntfy.Topic); err != nil { return nil, err } d = ntfyDir.Children.Get("user") if d != nil { if err := d.ParseParams(&config.ntfy.User); err != nil { return nil, err } } d = ntfyDir.Children.Get("password") if d != nil { if err := d.ParseParams(&config.ntfy.Password); err != nil { return nil, err } } cacheDir := cfg.Get("cache") if cacheDir != nil { var durationString string d = cacheDir.Children.Get("duration") if d != nil { if err := d.ParseParams(&durationString); err != nil { return nil, err } duration, err := time.ParseDuration(durationString) if err != nil { return nil, err } config.cache.Duration = duration } var cleanupIntervalString string d = cacheDir.Children.Get("cleanup-interval") if d != nil { if err := d.ParseParams(&cleanupIntervalString); err != nil { return nil, err } interval, err := time.ParseDuration(cleanupIntervalString) if err != nil { return nil, err } config.cache.CleanupInterval = interval } } amDir := cfg.Get("alertmanager") if amDir != nil { var durationString string d = amDir.Children.Get("silence-duration") if d != nil { if err := d.ParseParams(&durationString); err != nil { return nil, err } duration, err := time.ParseDuration(durationString) if err != nil { return nil, err } config.am.SilenceDuration = duration } d = amDir.Children.Get("user") if d != nil { if err := d.ParseParams(&config.am.User); err != nil { return nil, err } } d = amDir.Children.Get("password") if d != nil { if err := d.ParseParams(&config.am.Password); err != nil { return nil, err } } d = amDir.Children.Get("url") if d != nil { if err := d.ParseParams(&config.am.URL); err != nil { return nil, err } } } resolvedDir := cfg.Get("resolved") if resolvedDir != nil { d = resolvedDir.Children.Get("tags") if d != nil { var tags string if err := d.ParseParams(&tags); err != nil { return nil, err } config.resolved.Tags = strings.Split(tags, ",") } } return config, nil }