package main import ( "os" "path/filepath" "reflect" "testing" "time" ) func TestReadConfig(t *testing.T) { configContent := ` # Public facing base URL of the service (e.g. https://ntfy-alertmanager.xenrox.net) # This setting is required for the "Silence" feature. base-url https://ntfy-alertmanager.xenrox.net # http listen address http-address :8080 # Log level (either debug, info, warning, error) log-level info # When multiple alerts are grouped together by Alertmanager, they can either be sent # each on their own (single mode) or be kept together (multi mode) (either single or multi; default is single) alert-mode multi # Optionally protect with HTTP basic authentication user webhookUser password webhookPass labels { order "severity,instance" severity "critical" { priority 5 tags "rotating_light" } severity "info" { priority 1 } instance "example.com" { tags "computer,example" } } ntfy { # URL of the ntfy topic - required topic https://ntfy.sh/alertmanager-alerts # ntfy access control (https://ntfy.sh/docs/config/#access-control) user user password pass } alertmanager { # If set, the ntfy message will contain a "Silence" button, which can be used # to create a silence via the Alertmanager API. Because of limitations in ntfy, # the request will be proxied through ntfy-alertmanager. Therefore ntfy-alertmanager # needs to be exposed to external network requests and base-url has to be set. silence-duration 24h # Basic authentication (https://prometheus.io/docs/alerting/latest/https/) user user password pass } # When the alert-mode is set to single, ntfy-alertmanager will cache each single alert # to avoid sending recurrences. cache { # How long messages stay in the cache for duration 48h # Interval in which the cache is cleaned up # cleanup-interval 1h } ` expectedCfg := &config{ BaseURL: "https://ntfy-alertmanager.xenrox.net", HTTPAddress: ":8080", LogLevel: "info", alertMode: multi, User: "webhookUser", Password: "webhookPass", ntfy: ntfyConfig{Topic: "https://ntfy.sh/alertmanager-alerts", User: "user", Password: "pass"}, labels: labels{Order: []string{"severity", "instance"}, Label: map[string]labelConfig{ "severity:critical": {Priority: "5", Tags: []string{"rotating_light"}}, "severity:info": {Priority: "1"}, "instance:example.com": {Tags: []string{"computer", "example"}}, }, }, cache: cacheConfig{CleanupInterval: time.Hour, Duration: 48 * time.Hour}, am: alertmanagerConfig{ SilenceDuration: time.Hour * 24, User: "user", Password: "pass", }, } configPath := filepath.Join(t.TempDir(), "config") err := os.WriteFile(configPath, []byte(configContent), 0600) if err != nil { t.Errorf("failed to write config file: %v", err) } cfg, err := readConfig(configPath) if err != nil { t.Errorf("failed to read config file: %v", err) } if !reflect.DeepEqual(cfg, expectedCfg) { t.Errorf("expected: %v, got %v", expectedCfg, cfg) } }