watcher: a name removed from the targets leaves the state (closes #223)
check / check (push) Canceled after 0s
check / check (push) Canceled after 0s
The port checks, which the first check after startup runs after its DNS checks, now also remove the domain and hostname entries of names no longer in DNSWATCHER_TARGETS, and the certificate entries of those names and of addresses a name no longer resolves to. A configured domain's own records, saved as a hostname entry under its name, are kept, and so are the certificate entries of a configured name none of whose nameservers answered, as its port entries already were. Nothing is notified. Model: opus-5-5
This commit is contained in:
@@ -774,8 +774,12 @@ func (w *Watcher) checkAllPorts(ctx context.Context) {
|
||||
}
|
||||
|
||||
// Phase 3: Remove port state entries that no longer have
|
||||
// any hostname referencing them.
|
||||
// any hostname referencing them, the domain, hostname and
|
||||
// certificate entries of names no longer configured, and
|
||||
// certificate entries for an address their name no longer has.
|
||||
w.cleanupStalePorts(associations)
|
||||
w.cleanupRemovedTargets()
|
||||
w.cleanupStaleCertificates()
|
||||
}
|
||||
|
||||
// buildPortAssociations constructs a map from IP:port keys to
|
||||
@@ -859,11 +863,68 @@ func (w *Watcher) cleanupStalePorts(
|
||||
}
|
||||
}
|
||||
|
||||
// cleanupRemovedTargets removes the domain and hostname state entries
|
||||
// of names no longer in the configuration. A configured domain's own
|
||||
// records are saved as a hostname entry under its name, which is kept.
|
||||
func (w *Watcher) cleanupRemovedTargets() {
|
||||
for _, name := range w.state.GetAllDomainNames() {
|
||||
if !slices.Contains(w.config.Domains, name) {
|
||||
w.state.DeleteDomainState(name)
|
||||
}
|
||||
}
|
||||
|
||||
for _, name := range w.state.GetAllHostnames() {
|
||||
if !w.isConfigured(name) {
|
||||
w.state.DeleteHostnameState(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// cleanupStaleCertificates removes the certificate entries of names no
|
||||
// longer configured, and those for an address their name no longer
|
||||
// resolves to. An entry saved for a configured name none of whose
|
||||
// nameservers answered is kept: that name's addresses are not known,
|
||||
// not gone.
|
||||
func (w *Watcher) cleanupStaleCertificates() {
|
||||
for _, key := range w.state.GetAllCertificateKeys() {
|
||||
ip, hostname := parseCertKey(key)
|
||||
|
||||
if w.isConfigured(hostname) &&
|
||||
slices.Contains(w.collectIPs(hostname), ip) {
|
||||
continue
|
||||
}
|
||||
|
||||
if w.noNameserverAnswered(hostname) {
|
||||
continue
|
||||
}
|
||||
|
||||
w.state.DeleteCertificateState(key)
|
||||
}
|
||||
}
|
||||
|
||||
// parseCertKey splits an "ip:port:hostname" certificate key into its
|
||||
// address and hostname.
|
||||
func parseCertKey(key string) (string, string) {
|
||||
lastColon := strings.LastIndex(key, ":")
|
||||
if lastColon < 0 {
|
||||
return "", key
|
||||
}
|
||||
|
||||
ip, _ := parsePortKey(key[:lastColon])
|
||||
|
||||
return ip, key[lastColon+1:]
|
||||
}
|
||||
|
||||
// isConfigured reports whether name is a configured domain or hostname.
|
||||
func (w *Watcher) isConfigured(name string) bool {
|
||||
return slices.Contains(w.config.Domains, name) ||
|
||||
slices.Contains(w.config.Hostnames, name)
|
||||
}
|
||||
|
||||
// noNameserverAnswered reports whether name is a configured domain or
|
||||
// hostname and none of its nameservers answered on its last check.
|
||||
func (w *Watcher) noNameserverAnswered(name string) bool {
|
||||
if !slices.Contains(w.config.Hostnames, name) &&
|
||||
!slices.Contains(w.config.Domains, name) {
|
||||
if !w.isConfigured(name) {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user