feat: fail fast when no monitoring targets configured (#75)
Some checks failed
check / check (push) Failing after 46s
Some checks failed
check / check (push) Failing after 46s
## Summary When `DNSWATCHER_TARGETS` is empty (the default), dnswatcher previously started successfully and ran indefinitely monitoring nothing. This is a common misconfiguration — forgetting to set the variable or making a typo in its name — and gave no indication anything was wrong. ## Changes - Added `ErrNoTargets` sentinel error in `internal/config/config.go` - Extracted `parseAndValidateTargets()` helper to validate that at least one domain or hostname is configured after target classification - If no targets are configured, dnswatcher now exits with a clear error: `"no monitoring targets configured: set DNSWATCHER_TARGETS environment variable"` - Updated README.md to document that `DNSWATCHER_TARGETS` is required and dnswatcher will refuse to start without it ## How it works The validation runs during config construction (via uber/fx), before the watcher or any other component starts. If `DNSWATCHER_TARGETS` is empty or contains only whitespace/empty entries, `buildConfig()` returns `ErrNoTargets`, which causes fx to fail startup with a clear error message. This is fail-fast behavior: a monitoring daemon with nothing to monitor is a misconfiguration and should not silently run. Closes #69 Co-authored-by: clawbot <clawbot@noreply.git.eeqj.de> Reviewed-on: #75 Co-authored-by: clawbot <clawbot@noreply.example.org> Co-committed-by: clawbot <clawbot@noreply.example.org>
This commit was merged in pull request #75.
This commit is contained in:
@@ -23,6 +23,11 @@ const (
|
||||
defaultTLSExpiryWarning = 7
|
||||
)
|
||||
|
||||
// ErrNoTargets is returned when no monitoring targets are configured.
|
||||
var ErrNoTargets = errors.New(
|
||||
"no monitoring targets configured: set DNSWATCHER_TARGETS environment variable",
|
||||
)
|
||||
|
||||
// Params contains dependencies for Config.
|
||||
type Params struct {
|
||||
fx.In
|
||||
@@ -132,11 +137,9 @@ func buildConfig(
|
||||
tlsInterval = defaultTLSInterval
|
||||
}
|
||||
|
||||
domains, hostnames, err := ClassifyTargets(
|
||||
parseCSV(viper.GetString("TARGETS")),
|
||||
)
|
||||
domains, hostnames, err := parseAndValidateTargets()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid targets configuration: %w", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cfg := &Config{
|
||||
@@ -162,6 +165,23 @@ func buildConfig(
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func parseAndValidateTargets() ([]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 parseCSV(input string) []string {
|
||||
if input == "" {
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user