GoBroke/daemon/funcs_updater.go

178 lines
4.9 KiB
Go
Raw Normal View History

2025-02-04 12:14:08 -05:00
package daemon
import (
`bytes`
`os`
`time`
sysd "github.com/coreos/go-systemd/daemon"
`github.com/davecgh/go-spew/spew`
`r00t2.io/gobroke/conf`
`r00t2.io/gobroke/runner`
`r00t2.io/goutils/multierr`
)
// Start starts an Updater. This blocks.
func (u *Updater) Start() (err error) {
var sig os.Signal
var t time.Time
var tunResults []*runner.TunnelResult
var tunsChanged bool
var tunsUpdated bool
var mErr *multierr.MultiError = multierr.NewMultiError(nil)
u.log.Debug("daemon.Updater.Start: Starting persistent Updater.")
u.timer.Reset(u.cfg.Freq)
if isSystemd {
var supported bool
// https://www.freedesktop.org/software/systemd/man/sd_notify.html
if supported, err = sysd.SdNotify(false, sysd.SdNotifyReady); err != nil {
u.log.Err(
"daemon.Updater.Start: Error encountered when notifying systemd of changestate to READY (supported: %v): %v",
supported, err,
)
err = nil
}
}
breakLoop:
for !u.isStopping {
if u.isStopping {
break
}
select {
case t = <-u.timer.C:
u.log.Debug("daemon.Updater.Start: Tick at %s; running check/update.", t.String())
if tunResults, tunsChanged, tunsUpdated, err = runner.Run(u.cfg, u.log); err != nil {
u.log.Err("daemon.Updater.Start: Received error running check/update: %v", err)
mErr.AddError(err)
err = nil
} else {
u.log.Debug(
"daemon.Updater.Start: Check/update finished at %s; waiting %s. Changed: %v, Updated: %v, Results:\n%s",
t.String(), u.cfg.Freq.String(), tunsChanged, tunsUpdated, spew.Sdump(tunResults),
)
}
u.timer.Reset(u.cfg.Freq)
case sig = <-u.reloadChan:
u.log.Debug("daemon.Updater.Start: Received reload signal %v (%#v): %v", sig, sig, sig.String())
if u.isStopping {
break breakLoop
}
if err = u.Reload(); err != nil {
u.log.Err("daemon.Updater.Start: Received error running reload: %v", err)
mErr.AddError(err)
err = nil
}
case sig = <-u.stopChan:
u.isStopping = true
u.log.Debug("daemon.Updater.Start: Received stop signal %v (%#v): %v", sig, sig, sig.String())
if err = u.Stop(); err != nil {
u.log.Err("daemon.Updater.Start: Received error stopping: %v", err)
mErr.AddError(err)
err = nil
}
break breakLoop
}
}
if !mErr.IsEmpty() {
err = mErr
return
}
u.log.Debug("daemon.Updater.Start: Persistent updater stopped.")
return
}
// Stop stops an Updater. This is called by signal handlers in Start, and will close Start's block.
func (u *Updater) Stop() (err error) {
u.log.Debug("daemon.Updater.Stop: Stopping persistent Updater.")
if isSystemd {
// https://www.freedesktop.org/software/systemd/man/sd_notify.html
if _, err = sysd.SdNotify(false, sysd.SdNotifyStopping); err != nil {
u.log.Err("daemon.Updater.Stop: Received error notifying systemd of stop: %v", err)
err = nil
}
}
u.isStopping = true
u.timer.Stop()
close(u.stopChan)
close(u.reloadChan)
u.log.Debug("daemon.Updater.Stop: Stopped persistent Updater.")
return
}
// Reload reloads the configuration if it was originally set via a file.
func (u *Updater) Reload() (err error) {
var prevCfg *conf.Config
var supported bool
var newCksum []byte
u.log.Debug("daemon.Updater.Reload: Reloading persistent Updater.")
if isSystemd {
// https://www.freedesktop.org/software/systemd/man/sd_notify.html
if _, err = sysd.SdNotify(false, sysd.SdNotifyReloading); err != nil {
u.log.Err("daemon.Updater.Reload: Received error notifying systemd of reload: %v", err)
err = nil
}
}
if u.cfg.Path() != "" {
if newCksum, err = conf.ChecksumPath(u.cfg.Path()); err != nil {
u.log.Err(
"daemon.Updater.Reload: Received error getting checksum of defined conf path '%s'; skipping reload: %v",
u.cfg.Path(), err,
)
err = nil
} else {
if bytes.Equal(newCksum, u.cfg.Checksum()) {
u.log.Warning("daemon.Updater.Reload: Config path '%s' checksum unchanged; skipping reload", u.cfg.Path())
} else {
prevCfg = new(conf.Config)
*prevCfg = *u.cfg
if u.cfg, err = conf.NewConfig(u.cfg.Path(), u.cfg.IsDebug(), u.log); err != nil {
u.log.Err("daemon.Updater.Reload: Received error parsing new config; reverting to previous configuration: %v", err)
err = nil
u.cfg = prevCfg
} else {
u.log.Debug(
"daemon.Updater.Reload: New configuration loaded from '%s'; restarting timer for '%s'.",
u.cfg.Path(), u.cfg.Freq.String(),
)
u.timer.Reset(u.cfg.Freq)
}
}
}
} else {
u.log.Debug("daemon.Updater.Reload: No config filepath specified; NO-OP.")
}
if isSystemd {
// https://www.freedesktop.org/software/systemd/man/sd_notify.html
if supported, err = sysd.SdNotify(false, sysd.SdNotifyReady); err != nil {
u.log.Err(
"daemon.Updater.Reload: Error encountered when notifying systemd of changestate to READY (supported: %v): %v",
supported, err,
)
err = nil
}
}
u.log.Debug("daemon.Updater.Reload: Finished Updater reload.")
return
}