ntfy-alertmanager/config/config.go

430 lines
9 KiB
Go
Raw Permalink Normal View History

2023-07-12 14:56:48 +02:00
// Package config defines the configuration file.
package config
2022-10-10 01:30:39 +02:00
import (
"errors"
2022-10-10 01:30:39 +02:00
"fmt"
"strings"
"time"
2022-10-10 01:30:39 +02:00
"git.sr.ht/~emersion/go-scfg"
)
2023-07-12 14:56:48 +02:00
// AlertMode determines if alerts grouped by Alertmanager are being kept together.
type AlertMode int
2023-01-20 15:03:46 +01:00
2023-07-12 14:56:48 +02:00
// The different modes for AlertMode.
2023-01-20 15:03:46 +01:00
const (
2023-07-12 14:56:48 +02:00
Single AlertMode = iota
Multi
2023-01-20 15:03:46 +01:00
)
2023-07-12 14:56:48 +02:00
// Config is the configuration of the bridge.
type Config struct {
BaseURL string
HTTPAddress string
LogLevel string
LogFormat string
2023-07-12 14:56:48 +02:00
AlertMode AlertMode
User string
Password string
2023-07-12 14:56:48 +02:00
Ntfy ntfyConfig
Labels labels
Cache CacheConfig
2023-07-12 14:56:48 +02:00
Am alertmanagerConfig
Resolved resolvedConfig
2022-10-10 02:42:13 +02:00
}
type ntfyConfig struct {
Topic string
User string
Password string
AccessToken string
CertFingerprint string
EmailAddress string
Call string
}
type labels struct {
Order []string
Label map[string]labelConfig
}
type labelConfig struct {
Priority string
Tags []string
Icon string
2023-07-12 14:56:48 +02:00
EmailAddress string
Call string
}
// CacheConfig is the configuration of the cache.
type CacheConfig struct {
2023-03-08 22:17:32 +01:00
// shared settings
Type string
2023-03-08 22:17:32 +01:00
Duration time.Duration
// memory settings
CleanupInterval time.Duration
2023-03-08 22:17:32 +01:00
// redis settings
RedisURL string
}
type alertmanagerConfig struct {
2023-02-12 14:15:02 +01:00
User string
Password string
SilenceDuration time.Duration
URL string
}
type resolvedConfig struct {
2023-09-28 13:42:49 +02:00
Tags []string
Icon string
2023-09-27 15:15:32 +02:00
Priority string
}
2023-07-12 14:56:48 +02:00
// ReadConfig reads an scfg formatted file and returns the configuration struct.
func ReadConfig(path string) (*Config, error) {
cfg, err := scfg.Load(path)
if err != nil {
return nil, err
}
2023-07-12 14:56:48 +02:00
config := new(Config)
// Set default values
config.HTTPAddress = "127.0.0.1:8080"
config.LogLevel = "info"
config.LogFormat = "text"
config.AlertMode = Multi
config.Cache.Type = "disabled"
2023-07-12 14:56:48 +02:00
config.Cache.Duration = time.Hour * 24
2023-03-08 22:17:32 +01:00
// memory
2023-07-12 14:56:48 +02:00
config.Cache.CleanupInterval = time.Hour
2023-03-08 22:17:32 +01:00
// redis
2023-07-12 14:56:48 +02:00
config.Cache.RedisURL = "redis://localhost:6379"
d := cfg.Get("log-level")
if d != nil {
if err := d.ParseParams(&config.LogLevel); err != nil {
return nil, err
}
}
d = cfg.Get("log-format")
if d != nil {
if err := d.ParseParams(&config.LogFormat); 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
}
}
2023-01-20 15:03:46 +01:00
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":
2023-07-12 14:56:48 +02:00
config.AlertMode = Single
2023-01-20 15:03:46 +01:00
case "multi":
2023-07-12 14:56:48 +02:00
config.AlertMode = Multi
2023-01-20 15:03:46 +01:00
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
}
}
if (config.Password != "" && config.User == "") ||
(config.Password == "" && config.User != "") {
return nil, errors.New("user and password have to be set together")
}
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
}
2023-07-12 14:56:48 +02:00
config.Labels.Order = strings.Split(order, ",")
}
labels := make(map[string]labelConfig)
2023-07-12 14:56:48 +02:00
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
}
}
2022-10-12 17:04:44 +02:00
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, ",")
}
d = labelDir.Children.Get("icon")
if d != nil {
if err := d.ParseParams(&labelConfig.Icon); err != nil {
return nil, err
}
}
d = labelDir.Children.Get("email-address")
if d != nil {
2023-07-12 14:56:48 +02:00
if err := d.ParseParams(&labelConfig.EmailAddress); err != nil {
return nil, err
}
}
d = labelDir.Children.Get("call")
if d != nil {
2023-07-12 14:56:48 +02:00
if err := d.ParseParams(&labelConfig.Call); err != nil {
return nil, err
}
}
labels[fmt.Sprintf("%s:%s", labelName, name)] = *labelConfig
}
}
2023-07-12 14:56:48 +02:00
config.Labels.Label = labels
}
2022-10-10 02:42:13 +02:00
ntfyDir := cfg.Get("ntfy")
if ntfyDir == nil {
return nil, fmt.Errorf("%q directive missing", "ntfy")
}
d = ntfyDir.Children.Get("topic")
2022-10-10 01:30:39 +02:00
if d == nil {
2022-10-10 02:42:13 +02:00
return nil, fmt.Errorf("%q missing from %q directive", "topic", "ntfy")
2022-10-10 01:30:39 +02:00
}
2023-07-12 14:56:48 +02:00
if err := d.ParseParams(&config.Ntfy.Topic); err != nil {
2022-10-10 01:30:39 +02:00
return nil, err
}
2022-10-10 02:42:13 +02:00
d = ntfyDir.Children.Get("user")
if d != nil {
2023-07-12 14:56:48 +02:00
if err := d.ParseParams(&config.Ntfy.User); err != nil {
2022-10-10 02:42:13 +02:00
return nil, err
}
}
d = ntfyDir.Children.Get("password")
if d != nil {
2023-07-12 14:56:48 +02:00
if err := d.ParseParams(&config.Ntfy.Password); err != nil {
2022-10-10 02:42:13 +02:00
return nil, err
}
}
2023-07-12 14:56:48 +02:00
if (config.Ntfy.Password != "" && config.Ntfy.User == "") ||
(config.Ntfy.Password == "" && config.Ntfy.User != "") {
return nil, errors.New("ntfy: user and password have to be set together")
}
d = ntfyDir.Children.Get("access-token")
if d != nil {
2023-07-12 14:56:48 +02:00
if err := d.ParseParams(&config.Ntfy.AccessToken); err != nil {
return nil, err
}
}
2023-07-12 14:56:48 +02:00
if config.Ntfy.User != "" && config.Ntfy.AccessToken != "" {
return nil, errors.New("ntfy: cannot use both an access-token and a user/password at the same time")
}
d = ntfyDir.Children.Get("certificate-fingerprint")
if d != nil {
if err := d.ParseParams(&config.Ntfy.CertFingerprint); err != nil {
return nil, err
}
// hex.EncodeToString outputs a lower case string
config.Ntfy.CertFingerprint = strings.ToLower(strings.ReplaceAll(config.Ntfy.CertFingerprint, ":", ""))
}
d = ntfyDir.Children.Get("email-address")
if d != nil {
2023-07-12 14:56:48 +02:00
if err := d.ParseParams(&config.Ntfy.EmailAddress); err != nil {
return nil, err
}
}
d = ntfyDir.Children.Get("call")
if d != nil {
2023-07-12 14:56:48 +02:00
if err := d.ParseParams(&config.Ntfy.Call); err != nil {
return nil, err
}
}
cacheDir := cfg.Get("cache")
if cacheDir != nil {
2023-03-08 16:30:58 +01:00
d = cacheDir.Children.Get("type")
if d != nil {
if err := d.ParseParams(&config.Cache.Type); err != nil {
2023-03-08 16:30:58 +01:00
return nil, err
}
}
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
}
2023-07-12 14:56:48 +02:00
config.Cache.Duration = duration
}
2023-03-08 22:17:32 +01:00
// memory
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
}
2023-07-12 14:56:48 +02:00
config.Cache.CleanupInterval = interval
}
2023-03-08 22:17:32 +01:00
// redis
d = cacheDir.Children.Get("redis-url")
if d != nil {
2023-07-12 14:56:48 +02:00
if err := d.ParseParams(&config.Cache.RedisURL); err != nil {
2023-03-08 22:17:32 +01:00
return nil, err
}
}
}
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
}
2023-07-12 14:56:48 +02:00
config.Am.SilenceDuration = duration
}
2023-02-12 14:15:02 +01:00
d = amDir.Children.Get("user")
if d != nil {
2023-07-12 14:56:48 +02:00
if err := d.ParseParams(&config.Am.User); err != nil {
2023-02-12 14:15:02 +01:00
return nil, err
}
}
d = amDir.Children.Get("password")
if d != nil {
2023-07-12 14:56:48 +02:00
if err := d.ParseParams(&config.Am.Password); err != nil {
2023-02-12 14:15:02 +01:00
return nil, err
}
}
2023-07-12 14:56:48 +02:00
if (config.Am.Password != "" && config.Am.User == "") ||
(config.Am.Password == "" && config.Am.User != "") {
return nil, errors.New("alertmanager: user and password have to be set together")
}
d = amDir.Children.Get("url")
if d != nil {
2023-07-12 14:56:48 +02:00
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
}
2023-07-12 14:56:48 +02:00
config.Resolved.Tags = strings.Split(tags, ",")
}
d = resolvedDir.Children.Get("icon")
if d != nil {
2023-07-12 14:56:48 +02:00
if err := d.ParseParams(&config.Resolved.Icon); err != nil {
return nil, err
}
}
2023-09-27 15:15:32 +02:00
d = resolvedDir.Children.Get("priority")
if d != nil {
if err := d.ParseParams(&config.Resolved.Priority); err != nil {
return nil, err
}
}
}
return config, nil
}