config: fail fast when DNSWATCHER_TARGETS is empty
All checks were successful
check / check (push) Successful in 45s
All checks were successful
check / check (push) Successful in 45s
When DNSWATCHER_TARGETS is empty or unset (the default), dnswatcher now exits with a clear error message instead of silently starting with nothing to monitor. Added ErrNoTargets sentinel error returned from config.New when both domains and hostnames lists are empty after target classification. This causes the fx application to fail to start, preventing silent misconfiguration. Also extracted classifyAndValidateTargets and parseDurationOrDefault helper functions to keep buildConfig within the funlen limit. Closes #69
This commit is contained in:
@@ -15,6 +15,12 @@ import (
|
||||
"sneak.berlin/go/dnswatcher/internal/logger"
|
||||
)
|
||||
|
||||
// ErrNoTargets is returned when DNSWATCHER_TARGETS is empty or unset.
|
||||
var ErrNoTargets = errors.New(
|
||||
"no targets configured: set DNSWATCHER_TARGETS to a comma-separated " +
|
||||
"list of DNS names to monitor",
|
||||
)
|
||||
|
||||
// Default configuration values.
|
||||
const (
|
||||
defaultPort = 8080
|
||||
@@ -118,25 +124,9 @@ func buildConfig(
|
||||
}
|
||||
}
|
||||
|
||||
dnsInterval, err := time.ParseDuration(
|
||||
viper.GetString("DNS_INTERVAL"),
|
||||
)
|
||||
domains, hostnames, err := classifyAndValidateTargets()
|
||||
if err != nil {
|
||||
dnsInterval = defaultDNSInterval
|
||||
}
|
||||
|
||||
tlsInterval, err := time.ParseDuration(
|
||||
viper.GetString("TLS_INTERVAL"),
|
||||
)
|
||||
if err != nil {
|
||||
tlsInterval = defaultTLSInterval
|
||||
}
|
||||
|
||||
domains, hostnames, err := ClassifyTargets(
|
||||
parseCSV(viper.GetString("TARGETS")),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid targets configuration: %w", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cfg := &Config{
|
||||
@@ -148,8 +138,8 @@ func buildConfig(
|
||||
SlackWebhook: viper.GetString("SLACK_WEBHOOK"),
|
||||
MattermostWebhook: viper.GetString("MATTERMOST_WEBHOOK"),
|
||||
NtfyTopic: viper.GetString("NTFY_TOPIC"),
|
||||
DNSInterval: dnsInterval,
|
||||
TLSInterval: tlsInterval,
|
||||
DNSInterval: parseDurationOrDefault("DNS_INTERVAL", defaultDNSInterval),
|
||||
TLSInterval: parseDurationOrDefault("TLS_INTERVAL", defaultTLSInterval),
|
||||
TLSExpiryWarning: viper.GetInt("TLS_EXPIRY_WARNING"),
|
||||
SentryDSN: viper.GetString("SENTRY_DSN"),
|
||||
MaintenanceMode: viper.GetBool("MAINTENANCE_MODE"),
|
||||
@@ -162,6 +152,32 @@ func buildConfig(
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func classifyAndValidateTargets() ([]string, []string, error) {
|
||||
domains, hostnames, err := ClassifyTargets(
|
||||
parseCSV(viper.GetString("TARGETS")),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf(
|
||||
"invalid targets configuration: %w", err,
|
||||
)
|
||||
}
|
||||
|
||||
if len(domains) == 0 && len(hostnames) == 0 {
|
||||
return nil, nil, ErrNoTargets
|
||||
}
|
||||
|
||||
return domains, hostnames, nil
|
||||
}
|
||||
|
||||
func parseDurationOrDefault(key string, fallback time.Duration) time.Duration {
|
||||
d, err := time.ParseDuration(viper.GetString(key))
|
||||
if err != nil {
|
||||
return fallback
|
||||
}
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
func parseCSV(input string) []string {
|
||||
if input == "" {
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user