Compare commits

..
1 Commits
Author SHA1 Message Date
clawbot e08a379994 watcher: a removed nameserver is an NS Change, not an NS Failure (closes #262)
check / check (push) Canceled after 0s
A nameserver that left a domain's delegation was reported twice: as the
domain's NS Change, and by the check of the domain's own records as an
error-level NS Failure saying it disappeared. The check of a name's
records now sends one NS Change at warning level, starting Hostname: or
Domain:, listing the nameservers it was asked at before and not now.
For a domain it leaves out those of its saved delegation, which the
domain's own NS Change lists, so a domain's new delegation is now
notified and saved only after, and only together with, its records.
Nothing is sent for a nameserver that joins.

A nameserver that was failing before it left is now listed too; the
NS Failure skipped it.

Model: opus-5-5
2026-10-13 16:39:59 +00:00
4 changed files with 1 additions and 32 deletions
+1 -1
View File
@@ -449,7 +449,7 @@ following precedence (highest to lowest):
| `DNSWATCHER_SENTRY_DSN` | Sentry DSN for error reporting | `""` |
| `DNSWATCHER_MAINTENANCE_MODE` | Only sets `maintenanceMode` in the health check response; changes nothing else | `false` |
| `DNSWATCHER_METRICS_USERNAME` | Basic auth username for /metrics, which is served only when this is set | `""` |
| `DNSWATCHER_METRICS_PASSWORD` | Basic auth password for /metrics; required when `DNSWATCHER_METRICS_USERNAME` is set, and startup stops without it | `""` |
| `DNSWATCHER_METRICS_PASSWORD` | Basic auth password for /metrics | `""` |
| `DNSWATCHER_SEND_TEST_NOTIFICATION` | Send a test notification after first scan completes | `false` |
**`DNSWATCHER_TARGETS` is required.** dnswatcher will refuse to start if no
-2
View File
@@ -21,8 +21,6 @@ trial run of the finished image: https://git.eeqj.de/sneak/dnswatcher/issues/149
- 2026-10-13: a nameserver leaving a domain's delegation sends only NS Change;
one leaving a hostname's zone sends NS Change, not NS Failure (closes #262).
- 2026-10-13: `DNSWATCHER_METRICS_USERNAME` set without
`DNSWATCHER_METRICS_PASSWORD` stops startup (closes #268).
- 2026-10-13: a save syncs the state file to disk before renaming it into place,
so a crash cannot leave it empty and stop the next start (closes #264).
- 2026-10-13: a `PORT` that cannot be bound stops startup with an error naming
-11
View File
@@ -61,13 +61,6 @@ var ErrInvalidTLSExpiryWarning = errors.New(
// unset and means the default.
var ErrInvalidBool = errors.New("value must be true or false")
// ErrNoMetricsPassword is returned when DNSWATCHER_METRICS_USERNAME is set and
// DNSWATCHER_METRICS_PASSWORD is empty. Basic Auth on /metrics would otherwise
// let in anyone who sends the username with an empty password.
var ErrNoMetricsPassword = errors.New(
"DNSWATCHER_METRICS_PASSWORD must be set when DNSWATCHER_METRICS_USERNAME is set",
)
// Params contains dependencies for Config.
type Params struct {
fx.In
@@ -115,10 +108,6 @@ func New(_ fx.Lifecycle, params Params) (*Config, error) {
return nil, err
}
if cfg.MetricsUsername != "" && cfg.MetricsPassword == "" {
return nil, ErrNoMetricsPassword
}
configureDebugLogging(cfg, params)
return cfg, nil
-18
View File
@@ -354,24 +354,6 @@ func TestNew_SkipRecordNotificationsNotInTargetsStopsStartup(t *testing.T) {
require.ErrorContains(t, err, `"www.example.net"`)
}
// TestNew_MetricsUsernameWithoutPasswordStopsStartup checks an unset and an
// empty password; TestNew_EnvironmentOverrides checks a username with one.
func TestNew_MetricsUsernameWithoutPasswordStopsStartup(t *testing.T) {
viper.Reset()
t.Setenv("DNSWATCHER_TARGETS", "example.com")
t.Setenv("DNSWATCHER_METRICS_USERNAME", "prom")
_, err := config.New(nil, newTestParams(t))
require.ErrorIs(t, err, config.ErrNoMetricsPassword, "password unset")
require.ErrorContains(t, err, "DNSWATCHER_METRICS_PASSWORD")
viper.Reset()
t.Setenv("DNSWATCHER_METRICS_PASSWORD", "")
_, err = config.New(nil, newTestParams(t))
require.ErrorIs(t, err, config.ErrNoMetricsPassword, "password empty")
}
func TestNew_CustomDNSIntervalDuration(t *testing.T) {
viper.Reset()
t.Setenv("DNSWATCHER_TARGETS", "example.com")