Merge pull request #42 from safing/feature/update-trigger

Add update module status, allow disabling of updates
This commit is contained in:
Daniel 2020-04-21 15:44:24 +02:00 committed by GitHub
commit e7149ac226
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 110 additions and 12 deletions

View file

@ -5,13 +5,16 @@ import (
"fmt" "fmt"
"github.com/safing/portbase/config" "github.com/safing/portbase/config"
"github.com/safing/portbase/log"
) )
var ( var (
releaseChannel config.StringOption releaseChannel config.StringOption
devMode config.BoolOption devMode config.BoolOption
disableUpdates config.BoolOption
previousReleaseChannel string previousReleaseChannel string
updatesCurrentlyDisabled bool
previousDevMode bool previousDevMode bool
) )
@ -32,16 +35,35 @@ func registerConfig() error {
return err return err
} }
return module.RegisterEventHook("config", "config change", "update registry config", updateRegistryConfig) err = config.Register(&config.Option{
Name: "Disable Updates",
Key: disableUpdatesKey,
Description: "Disable automatic updates.",
OptType: config.OptTypeBool,
ExpertiseLevel: config.ExpertiseLevelExpert,
ReleaseLevel: config.ReleaseLevelStable,
RequiresRestart: false,
DefaultValue: false,
ExternalOptType: "disable updates",
})
if err != nil {
return err
}
return nil
} }
func initConfig() { func initConfig() {
releaseChannel = config.GetAsString(releaseChannelKey, releaseChannelStable) releaseChannel = config.GetAsString(releaseChannelKey, releaseChannelStable)
disableUpdates = config.GetAsBool(disableUpdatesKey, false)
devMode = config.GetAsBool("core/devMode", false) devMode = config.GetAsBool("core/devMode", false)
} }
func updateRegistryConfig(_ context.Context, _ interface{}) error { func updateRegistryConfig(_ context.Context, _ interface{}) error {
changed := false changed := false
forceUpdate := false
if releaseChannel() != previousReleaseChannel { if releaseChannel() != previousReleaseChannel {
registry.SetBeta(releaseChannel() == releaseChannelBeta) registry.SetBeta(releaseChannel() == releaseChannelBeta)
previousReleaseChannel = releaseChannel() previousReleaseChannel = releaseChannel()
@ -49,14 +71,29 @@ func updateRegistryConfig(_ context.Context, _ interface{}) error {
} }
if devMode() != previousDevMode { if devMode() != previousDevMode {
registry.SetBeta(devMode()) registry.SetDevMode(devMode())
previousDevMode = devMode() previousDevMode = devMode()
changed = true changed = true
} }
if disableUpdates() != updatesCurrentlyDisabled {
updatesCurrentlyDisabled = disableUpdates()
changed = true
forceUpdate = !updatesCurrentlyDisabled
}
if changed { if changed {
registry.SelectVersions() registry.SelectVersions()
module.TriggerEvent(VersionUpdateEvent, nil) module.TriggerEvent(VersionUpdateEvent, nil)
if forceUpdate {
module.Resolve(updateFailed)
_ = TriggerUpdate()
log.Infof("updates: automatic updates enabled again.")
} else {
module.Warning(updateFailed, "Updates are disabled!")
log.Warningf("updates: automatic updates are now disabled.")
}
} }
return nil return nil

View file

@ -19,6 +19,8 @@ const (
releaseChannelStable = "stable" releaseChannelStable = "stable"
releaseChannelBeta = "beta" releaseChannelBeta = "beta"
disableUpdatesKey = "core/disableUpdates"
// ModuleName is the name of the update module // ModuleName is the name of the update module
// and can be used when declaring module dependencies. // and can be used when declaring module dependencies.
ModuleName = "updates" ModuleName = "updates"
@ -36,6 +38,10 @@ const (
// to check if new versions of their resources are // to check if new versions of their resources are
// available by checking File.UpgradeAvailable(). // available by checking File.UpgradeAvailable().
ResourceUpdateEvent = "resource update" ResourceUpdateEvent = "resource update"
// TriggerUpdateEvent is the event that can be emitted
// by the updates module to trigger an update.
TriggerUpdateEvent = "trigger update"
) )
var ( var (
@ -46,15 +52,51 @@ var (
disableTaskSchedule bool disableTaskSchedule bool
) )
const (
updateInProgress = "update-in-progress"
updateInProcessDescr = "Portmaster is currently checking and downloading updates."
updateFailed = "update-failed"
)
func init() { func init() {
module = modules.Register(ModuleName, registerConfig, start, stop, "base") module = modules.Register(ModuleName, prep, start, stop, "base")
module.RegisterEvent(VersionUpdateEvent) module.RegisterEvent(VersionUpdateEvent)
module.RegisterEvent(ResourceUpdateEvent) module.RegisterEvent(ResourceUpdateEvent)
} }
func prep() error {
if err := registerConfig(); err != nil {
return err
}
module.RegisterEvent(TriggerUpdateEvent)
return nil
}
func start() error { func start() error {
initConfig() initConfig()
if err := module.RegisterEventHook(
"config",
"config change",
"update registry config",
updateRegistryConfig); err != nil {
return err
}
if err := module.RegisterEventHook(
module.Name,
TriggerUpdateEvent,
"Check for and download available updates",
func(context.Context, interface{}) error {
_ = TriggerUpdate()
return nil
},
); err != nil {
return err
}
var mandatoryUpdates []string var mandatoryUpdates []string
if onWindows { if onWindows {
mandatoryUpdates = []string{ mandatoryUpdates = []string{
@ -115,8 +157,8 @@ func start() error {
if !disableTaskSchedule { if !disableTaskSchedule {
updateTask. updateTask.
Repeat(24 * time.Hour). Repeat(1 * time.Hour).
MaxDelay(1 * time.Hour). MaxDelay(30 * time.Minute).
Schedule(time.Now().Add(10 * time.Second)) Schedule(time.Now().Add(10 * time.Second))
} }
@ -138,6 +180,7 @@ func TriggerUpdate() error {
updateASAP = true updateASAP = true
} else { } else {
updateTask.StartASAP() updateTask.StartASAP()
log.Debugf("updates: triggering update to run as soon as possible")
} }
return nil return nil
@ -156,14 +199,32 @@ func DisableUpdateSchedule() error {
return nil return nil
} }
func checkForUpdates(ctx context.Context) error { func checkForUpdates(ctx context.Context) (err error) {
if err := registry.UpdateIndexes(); err != nil { if updatesCurrentlyDisabled {
return fmt.Errorf("updates: failed to update indexes: %w", err) log.Debugf("updates: automatic updates are disabled")
return nil
}
defer log.Debugf("updates: finished checking for updates")
module.Hint(updateInProgress, updateInProcessDescr)
defer func() {
if err == nil {
module.Resolve(updateInProgress)
} else {
module.Warning(updateFailed, "Failed to check for updates: "+err.Error())
}
}()
if err = registry.UpdateIndexes(); err != nil {
err = fmt.Errorf("failed to update indexes: %w", err)
return
} }
err := registry.DownloadUpdates(ctx) err = registry.DownloadUpdates(ctx)
if err != nil { if err != nil {
return fmt.Errorf("updates: failed to update: %w", err) err = fmt.Errorf("failed to update: %w", err)
return
} }
registry.SelectVersions() registry.SelectVersions()