check / check (push) Waiting to run
When none of the nameservers of a hostname's zone answered, the walk to them failed and the check was only logged. The walk now returns a NoAnswerError naming the nameservers of the zone it reached through a referral when none of them answers. When those are the nameservers the previous check saved for the name, each is saved as failed with the reason, so it gets an NS Failure and later an NS Recovery. A domain with no delegation of its own, whose NS lookup is that same walk, gets the same. A walk that fails before that zone, as when the host loses its network, is still only logged. Model: opus-5-5
161 lines
3.9 KiB
Go
161 lines
3.9 KiB
Go
package watcher
|
|
|
|
import (
|
|
"context"
|
|
"log/slog"
|
|
"time"
|
|
|
|
"sneak.berlin/go/dnswatcher/internal/config"
|
|
"sneak.berlin/go/dnswatcher/internal/resolver"
|
|
"sneak.berlin/go/dnswatcher/internal/state"
|
|
)
|
|
|
|
// NewForTest creates a Watcher without fx for unit testing. A nil cfg
|
|
// is an empty configuration.
|
|
func NewForTest(
|
|
cfg *config.Config,
|
|
st *state.State,
|
|
res DNSResolver,
|
|
pc PortChecker,
|
|
tc TLSChecker,
|
|
n Notifier,
|
|
) *Watcher {
|
|
if cfg == nil {
|
|
cfg = &config.Config{}
|
|
}
|
|
|
|
return &Watcher{
|
|
log: slog.Default(),
|
|
config: cfg,
|
|
state: st,
|
|
resolver: res,
|
|
portCheck: pc,
|
|
tlsCheck: tc,
|
|
notify: n,
|
|
firstRun: true,
|
|
}
|
|
}
|
|
|
|
// SetLogger replaces the watcher's logger, so a test can read what it
|
|
// logs.
|
|
func (w *Watcher) SetLogger(log *slog.Logger) {
|
|
w.log = log
|
|
}
|
|
|
|
// NewlyDisagreeingPairs exports newlyDisagreeingPairs for testing.
|
|
func NewlyDisagreeingPairs(
|
|
prev, current *state.HostnameState,
|
|
) [][2]string {
|
|
return newlyDisagreeingPairs(prev, current)
|
|
}
|
|
|
|
// SetFirstRun sets whether the watcher is on its first check, in which
|
|
// nothing is compared with the previous check. NewForTest's watcher is.
|
|
func (w *Watcher) SetFirstRun(firstRun bool) {
|
|
w.firstRun = firstRun
|
|
}
|
|
|
|
// UpdateHostnameState exports updateHostnameState for testing.
|
|
func (w *Watcher) UpdateHostnameState(
|
|
ctx context.Context,
|
|
hostname string,
|
|
newState *state.HostnameState,
|
|
) {
|
|
w.updateHostnameState(ctx, hostname, newState)
|
|
}
|
|
|
|
// DetectHostnameChanges exports detectHostnameChanges for testing.
|
|
func (w *Watcher) DetectHostnameChanges(
|
|
ctx context.Context,
|
|
hostname string,
|
|
prev, current *state.HostnameState,
|
|
) {
|
|
w.detectHostnameChanges(ctx, hostname, prev, current)
|
|
}
|
|
|
|
// ResolveNameserverAddresses exports resolveNameserverAddresses for
|
|
// testing.
|
|
func (w *Watcher) ResolveNameserverAddresses(
|
|
ctx context.Context,
|
|
nameservers []string,
|
|
prev map[string][]string,
|
|
) map[string][]string {
|
|
return w.resolveNameserverAddresses(ctx, nameservers, prev)
|
|
}
|
|
|
|
// ResolveCNAMEAddresses exports resolveCNAMEAddresses for testing.
|
|
func (w *Watcher) ResolveCNAMEAddresses(
|
|
ctx context.Context,
|
|
hostname string,
|
|
current, prev *state.HostnameState,
|
|
) {
|
|
w.resolveCNAMEAddresses(ctx, hostname, current, prev)
|
|
}
|
|
|
|
// DetectNSAddressChanges exports detectNSAddressChanges for testing.
|
|
func (w *Watcher) DetectNSAddressChanges(
|
|
ctx context.Context,
|
|
domain string,
|
|
prev, current map[string][]string,
|
|
) {
|
|
w.detectNSAddressChanges(ctx, domain, prev, current)
|
|
}
|
|
|
|
// MaybeSendTestNotification exports maybeSendTestNotification for
|
|
// testing.
|
|
func (w *Watcher) MaybeSendTestNotification(ctx context.Context) {
|
|
w.maybeSendTestNotification(ctx)
|
|
}
|
|
|
|
// CleanupRemovedTargets exports cleanupRemovedTargets for testing.
|
|
func (w *Watcher) CleanupRemovedTargets() {
|
|
w.cleanupRemovedTargets()
|
|
}
|
|
|
|
// CheckAllPorts exports checkAllPorts for testing.
|
|
func (w *Watcher) CheckAllPorts(ctx context.Context) {
|
|
w.checkAllPorts(ctx)
|
|
}
|
|
|
|
// RunTLSChecks exports runTLSChecks for testing.
|
|
func (w *Watcher) RunTLSChecks(ctx context.Context) {
|
|
w.runTLSChecks(ctx)
|
|
}
|
|
|
|
// CheckHostnameResult exports checkHostnameResult for testing.
|
|
func (w *Watcher) CheckHostnameResult(
|
|
ctx context.Context,
|
|
hostname string,
|
|
results map[string]*resolver.NameserverResponse,
|
|
err error,
|
|
) bool {
|
|
return w.checkHostnameResult(ctx, hostname, results, err)
|
|
}
|
|
|
|
// CheckDomainResult exports checkDomainResult for testing.
|
|
func (w *Watcher) CheckDomainResult(
|
|
ctx context.Context,
|
|
domain string,
|
|
nameservers []string,
|
|
err error,
|
|
) {
|
|
w.checkDomainResult(ctx, domain, nameservers, err)
|
|
}
|
|
|
|
// FailedNameservers exports failedNameservers for testing.
|
|
func FailedNameservers(
|
|
err error,
|
|
prev *state.HostnameState,
|
|
) map[string]*resolver.NameserverResponse {
|
|
return failedNameservers(err, prev)
|
|
}
|
|
|
|
// BuildHostnameState exports buildHostnameState for testing.
|
|
func BuildHostnameState(
|
|
results map[string]*resolver.NameserverResponse,
|
|
prev *state.HostnameState,
|
|
now time.Time,
|
|
) *state.HostnameState {
|
|
return buildHostnameState(results, prev, now)
|
|
}
|