mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-25 11:05:45 +00:00
clientupdate: add support for QNAP (#10179)
Use the `qpkg_cli` to check for updates and install them. There are a couple special things about this compare to other updaters: * qpkg_cli can tell you when upgrade is available, but not what the version is * qpkg_cli --add Tailscale works for new installs, upgrades and reinstalling existing version; even reinstall of existing version takes a while Updates #10178 Signed-off-by: Andrew Lytvynov <awly@tailscale.com>
This commit is contained in:
parent
45be37cb01
commit
1f4a38ed49
@ -180,6 +180,8 @@ func (up *Updater) getUpdateFunction() (fn updateFunction, canAutoUpdate bool) {
|
||||
// plugin manager to be persistent.
|
||||
// TODO(awly): implement Unraid updates using the 'plugin' CLI.
|
||||
return nil, false
|
||||
case distro.QNAP:
|
||||
return up.updateQNAP, true
|
||||
}
|
||||
switch {
|
||||
case haveExecutable("pacman"):
|
||||
@ -1067,6 +1069,77 @@ func (up *Updater) unpackLinuxTarball(path string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (up *Updater) updateQNAP() (err error) {
|
||||
if up.Version != "" {
|
||||
return errors.New("installing a specific version on QNAP is not supported")
|
||||
}
|
||||
if err := requireRoot(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
err = fmt.Errorf(`%w; you can try updating using "qpkg_cli --add Tailscale"`, err)
|
||||
}
|
||||
}()
|
||||
|
||||
out, err := exec.Command("qpkg_cli", "--upgradable", "Tailscale").CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to check if Tailscale is upgradable using qpkg_cli: %w, output: %q", err, out)
|
||||
}
|
||||
|
||||
// Output should look like this:
|
||||
//
|
||||
// $ qpkg_cli -G Tailscale
|
||||
// [Tailscale]
|
||||
// upgradeStatus = 1
|
||||
statusRe := regexp.MustCompile(`upgradeStatus = (\d)`)
|
||||
m := statusRe.FindStringSubmatch(string(out))
|
||||
if len(m) < 2 {
|
||||
return fmt.Errorf("failed to check if Tailscale is upgradable using qpkg_cli, output: %q", out)
|
||||
}
|
||||
status, err := strconv.Atoi(m[1])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot parse upgradeStatus from qpkg_cli output %q: %w", out, err)
|
||||
}
|
||||
// Possible status values:
|
||||
// 0:can upgrade
|
||||
// 1:can not upgrade
|
||||
// 2:error
|
||||
// 3:can not get rss information
|
||||
// 4:qpkg not found
|
||||
// 5:qpkg not installed
|
||||
//
|
||||
// We want status 0.
|
||||
switch status {
|
||||
case 0: // proceed with upgrade
|
||||
case 1:
|
||||
up.Logf("no update available")
|
||||
return nil
|
||||
case 2, 3, 4:
|
||||
return fmt.Errorf("failed to check update status with qpkg_cli (upgradeStatus = %d)", status)
|
||||
case 5:
|
||||
return errors.New("Tailscale was not found in the QNAP App Center")
|
||||
default:
|
||||
return fmt.Errorf("failed to check update status with qpkg_cli (upgradeStatus = %d)", status)
|
||||
}
|
||||
|
||||
// There doesn't seem to be a way to fetch what the available upgrade
|
||||
// version is. Use the generic "latest" version in confirmation prompt.
|
||||
if up.Confirm != nil && !up.Confirm("latest") {
|
||||
return nil
|
||||
}
|
||||
|
||||
up.Logf("c2n: running qpkg_cli --add Tailscale")
|
||||
cmd := exec.Command("qpkg_cli", "--add", "Tailscale")
|
||||
cmd.Stdout = up.Stdout
|
||||
cmd.Stderr = up.Stderr
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("failed tailscale update using qpkg_cli: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeFile(r io.Reader, path string, perm os.FileMode) error {
|
||||
if err := os.Remove(path); err != nil && !os.IsNotExist(err) {
|
||||
return fmt.Errorf("failed to remove existing file at %q: %w", path, err)
|
||||
|
@ -31,6 +31,7 @@
|
||||
"tailscale.com/util/httpm"
|
||||
"tailscale.com/util/syspolicy"
|
||||
"tailscale.com/version"
|
||||
"tailscale.com/version/distro"
|
||||
)
|
||||
|
||||
var c2nLogHeap func(http.ResponseWriter, *http.Request) // non-nil on most platforms (c2n_pprof.go)
|
||||
@ -341,6 +342,14 @@ func findCmdTailscale() (string, error) {
|
||||
if self == "/usr/local/sbin/tailscaled" || self == "/usr/local/bin/tailscaled" {
|
||||
ts = "/usr/local/bin/tailscale"
|
||||
}
|
||||
if distro.Get() == distro.QNAP {
|
||||
// The volume under /share/ where qpkg are installed is not
|
||||
// predictable. But the rest of the path is.
|
||||
ok, err := filepath.Match("/share/*/.qpkg/Tailscale/tailscaled", self)
|
||||
if err == nil && ok {
|
||||
ts = filepath.Join(filepath.Dir(self), "tailscale")
|
||||
}
|
||||
}
|
||||
case "windows":
|
||||
ts = filepath.Join(filepath.Dir(self), "tailscale.exe")
|
||||
case "freebsd":
|
||||
|
Loading…
Reference in New Issue
Block a user