func autoUpgrade(cfg *config.Wrapper) { timer := time.NewTimer(0) sub := events.Default.Subscribe(events.DeviceConnected) for { select { case event := <-sub.C(): data, ok := event.Data.(map[string]string) if !ok || data["clientName"] != "syncthing" || upgrade.CompareVersions(data["clientVersion"], Version) != upgrade.Newer { continue } l.Infof("Connected to device %s with a newer version (current %q < remote %q). Checking for upgrades.", data["id"], Version, data["clientVersion"]) case <-timer.C: } rel, err := upgrade.LatestRelease(cfg.Options().ReleasesURL, Version) if err == upgrade.ErrUpgradeUnsupported { events.Default.Unsubscribe(sub) return } if err != nil { // Don't complain too loudly here; we might simply not have // internet connectivity, or the upgrade server might be down. l.Infoln("Automatic upgrade:", err) timer.Reset(time.Duration(cfg.Options().AutoUpgradeIntervalH) * time.Hour) continue } if upgrade.CompareVersions(rel.Tag, Version) != upgrade.Newer { // Skip equal, older or majorly newer (incompatible) versions timer.Reset(time.Duration(cfg.Options().AutoUpgradeIntervalH) * time.Hour) continue } l.Infof("Automatic upgrade (current %q < latest %q)", Version, rel.Tag) err = upgrade.To(rel) if err != nil { l.Warnln("Automatic upgrade:", err) timer.Reset(time.Duration(cfg.Options().AutoUpgradeIntervalH) * time.Hour) continue } events.Default.Unsubscribe(sub) l.Warnf("Automatically upgraded to version %q. Restarting in 1 minute.", rel.Tag) time.Sleep(time.Minute) stop <- exitUpgrading return } }
func checkUpgrade() upgrade.Release { cfg, _ := loadConfig() releasesURL := cfg.Options().ReleasesURL release, err := upgrade.LatestRelease(releasesURL, Version) if err != nil { l.Fatalln("Upgrade:", err) } if upgrade.CompareVersions(release.Tag, Version) <= 0 { noUpgradeMessage := "No upgrade available (current %q >= latest %q)." l.Infof(noUpgradeMessage, Version, release.Tag) os.Exit(exitNoUpgradeAvailable) } l.Infof("Upgrade available (current %q < latest %q)", Version, release.Tag) return release }
func (s *apiService) getSystemUpgrade(w http.ResponseWriter, r *http.Request) { if noUpgrade { http.Error(w, upgrade.ErrUpgradeUnsupported.Error(), 500) return } rel, err := upgrade.LatestRelease(s.cfg.Options().ReleasesURL, Version) if err != nil { http.Error(w, err.Error(), 500) return } res := make(map[string]interface{}) res["running"] = Version res["latest"] = rel.Tag res["newer"] = upgrade.CompareVersions(rel.Tag, Version) == upgrade.Newer res["majorNewer"] = upgrade.CompareVersions(rel.Tag, Version) == upgrade.MajorNewer sendJSON(w, res) }
func (s *apiService) postSystemUpgrade(w http.ResponseWriter, r *http.Request) { rel, err := upgrade.LatestRelease(s.cfg.Options().ReleasesURL, Version) if err != nil { l.Warnln("getting latest release:", err) http.Error(w, err.Error(), 500) return } if upgrade.CompareVersions(rel.Tag, Version) > upgrade.Equal { err = upgrade.To(rel) if err != nil { l.Warnln("upgrading:", err) http.Error(w, err.Error(), 500) return } s.flushResponse(`{"ok": "restarting"}`, w) l.Infoln("Upgrading") stop <- exitUpgrading } }