mirror of
https://github.com/tailscale/tailscale.git
synced 2025-03-28 12:02:23 +00:00
ipn/ipnlocal: support most Linuxes in handleC2NUpdate (#9114)
* ipn/ipnlocal: support most Linuxes in handleC2NUpdate Updates #6995 Signed-off-by: Chris Palmer <cpalmer@tailscale.com>
This commit is contained in:
parent
c621141746
commit
ce1e02096a
@ -57,14 +57,8 @@ func versionToTrack(v string) (string, error) {
|
|||||||
return "unstable", nil
|
return "unstable", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type updater struct {
|
// Arguments contains arguments needed to run an update.
|
||||||
UpdateArgs
|
type Arguments struct {
|
||||||
track string
|
|
||||||
update func() error
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateArgs contains arguments needed to run an update.
|
|
||||||
type UpdateArgs struct {
|
|
||||||
// Version can be a specific version number or one of the predefined track
|
// Version can be a specific version number or one of the predefined track
|
||||||
// constants:
|
// constants:
|
||||||
//
|
//
|
||||||
@ -76,7 +70,7 @@ type UpdateArgs struct {
|
|||||||
// Leaving this empty is the same as using CurrentTrack.
|
// Leaving this empty is the same as using CurrentTrack.
|
||||||
Version string
|
Version string
|
||||||
// AppStore forces a local app store check, even if the current binary was
|
// AppStore forces a local app store check, even if the current binary was
|
||||||
// not installed via an app store.
|
// not installed via an app store. TODO(cpalmer): Remove this.
|
||||||
AppStore bool
|
AppStore bool
|
||||||
// Logf is a logger for update progress messages.
|
// Logf is a logger for update progress messages.
|
||||||
Logf logger.Logf
|
Logf logger.Logf
|
||||||
@ -89,30 +83,31 @@ type UpdateArgs struct {
|
|||||||
PkgsAddr string
|
PkgsAddr string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (args UpdateArgs) validate() error {
|
func (args Arguments) validate() error {
|
||||||
if args.Confirm == nil {
|
if args.Confirm == nil {
|
||||||
return errors.New("missing Confirm callback in UpdateArgs")
|
return errors.New("missing Confirm callback in Arguments")
|
||||||
}
|
}
|
||||||
if args.Logf == nil {
|
if args.Logf == nil {
|
||||||
return errors.New("missing Logf callback in UpdateArgs")
|
return errors.New("missing Logf callback in Arguments")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update runs a single update attempt using the platform-specific mechanism.
|
type Updater struct {
|
||||||
//
|
Arguments
|
||||||
// On Windows, this copies the calling binary and re-executes it to apply the
|
track string
|
||||||
// update. The calling binary should handle an "update" subcommand and call
|
// Update is a platform-specific method that updates the installation. May be
|
||||||
// this function again for the re-executed binary to proceed.
|
// nil (not all platforms support updates from within Tailscale).
|
||||||
func Update(args UpdateArgs) error {
|
Update func() error
|
||||||
if err := args.validate(); err != nil {
|
}
|
||||||
return err
|
|
||||||
|
func NewUpdater(args Arguments) (*Updater, error) {
|
||||||
|
up := Updater{
|
||||||
|
Arguments: args,
|
||||||
}
|
}
|
||||||
if args.PkgsAddr == "" {
|
up.Update = up.getUpdateFunction()
|
||||||
args.PkgsAddr = "https://pkgs.tailscale.com"
|
if up.Update == nil {
|
||||||
}
|
return nil, errors.ErrUnsupported
|
||||||
up := &updater{
|
|
||||||
UpdateArgs: args,
|
|
||||||
}
|
}
|
||||||
switch up.Version {
|
switch up.Version {
|
||||||
case StableTrack, UnstableTrack:
|
case StableTrack, UnstableTrack:
|
||||||
@ -127,60 +122,82 @@ func Update(args UpdateArgs) error {
|
|||||||
var err error
|
var err error
|
||||||
up.track, err = versionToTrack(args.Version)
|
up.track, err = versionToTrack(args.Version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if args.PkgsAddr == "" {
|
||||||
|
args.PkgsAddr = "https://pkgs.tailscale.com"
|
||||||
|
}
|
||||||
|
return &up, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type updateFunction func() error
|
||||||
|
|
||||||
|
func (up *Updater) getUpdateFunction() updateFunction {
|
||||||
switch runtime.GOOS {
|
switch runtime.GOOS {
|
||||||
case "windows":
|
case "windows":
|
||||||
up.update = up.updateWindows
|
return up.updateWindows
|
||||||
case "linux":
|
case "linux":
|
||||||
switch distro.Get() {
|
switch distro.Get() {
|
||||||
case distro.Synology:
|
case distro.Synology:
|
||||||
up.update = up.updateSynology
|
return up.updateSynology
|
||||||
case distro.Debian: // includes Ubuntu
|
case distro.Debian: // includes Ubuntu
|
||||||
up.update = up.updateDebLike
|
return up.updateDebLike
|
||||||
case distro.Arch:
|
case distro.Arch:
|
||||||
up.update = up.updateArchLike
|
return up.updateArchLike
|
||||||
case distro.Alpine:
|
case distro.Alpine:
|
||||||
up.update = up.updateAlpineLike
|
return up.updateAlpineLike
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case haveExecutable("pacman"):
|
case haveExecutable("pacman"):
|
||||||
up.update = up.updateArchLike
|
return up.updateArchLike
|
||||||
case haveExecutable("apt-get"): // TODO(awly): add support for "apt"
|
case haveExecutable("apt-get"): // TODO(awly): add support for "apt"
|
||||||
// The distro.Debian switch case above should catch most apt-based
|
// The distro.Debian switch case above should catch most apt-based
|
||||||
// systems, but add this fallback just in case.
|
// systems, but add this fallback just in case.
|
||||||
up.update = up.updateDebLike
|
return up.updateDebLike
|
||||||
case haveExecutable("dnf"):
|
case haveExecutable("dnf"):
|
||||||
up.update = up.updateFedoraLike("dnf")
|
return up.updateFedoraLike("dnf")
|
||||||
case haveExecutable("yum"):
|
case haveExecutable("yum"):
|
||||||
up.update = up.updateFedoraLike("yum")
|
return up.updateFedoraLike("yum")
|
||||||
case haveExecutable("apk"):
|
case haveExecutable("apk"):
|
||||||
up.update = up.updateAlpineLike
|
return up.updateAlpineLike
|
||||||
}
|
}
|
||||||
// If nothing matched, fall back to tarball updates.
|
// If nothing matched, fall back to tarball updates.
|
||||||
if up.update == nil {
|
if up.Update == nil {
|
||||||
up.update = up.updateLinuxBinary
|
return up.updateLinuxBinary
|
||||||
}
|
}
|
||||||
case "darwin":
|
case "darwin":
|
||||||
switch {
|
switch {
|
||||||
case !args.AppStore && !version.IsSandboxedMacOS():
|
case !up.Arguments.AppStore && !version.IsSandboxedMacOS():
|
||||||
return errors.ErrUnsupported
|
return nil
|
||||||
case !args.AppStore && strings.HasSuffix(os.Getenv("HOME"), "/io.tailscale.ipn.macsys/Data"):
|
case !up.Arguments.AppStore && strings.HasSuffix(os.Getenv("HOME"), "/io.tailscale.ipn.macsys/Data"):
|
||||||
up.update = up.updateMacSys
|
return up.updateMacSys
|
||||||
default:
|
default:
|
||||||
up.update = up.updateMacAppStore
|
return up.updateMacAppStore
|
||||||
}
|
}
|
||||||
case "freebsd":
|
case "freebsd":
|
||||||
up.update = up.updateFreeBSD
|
return up.updateFreeBSD
|
||||||
}
|
}
|
||||||
if up.update == nil {
|
return nil
|
||||||
return errors.ErrUnsupported
|
|
||||||
}
|
|
||||||
return up.update()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (up *updater) confirm(ver string) bool {
|
// Update runs a single update attempt using the platform-specific mechanism.
|
||||||
|
//
|
||||||
|
// On Windows, this copies the calling binary and re-executes it to apply the
|
||||||
|
// update. The calling binary should handle an "update" subcommand and call
|
||||||
|
// this function again for the re-executed binary to proceed.
|
||||||
|
func Update(args Arguments) error {
|
||||||
|
if err := args.validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
up, err := NewUpdater(args)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return up.Update()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (up *Updater) confirm(ver string) bool {
|
||||||
if version.Short() == ver {
|
if version.Short() == ver {
|
||||||
up.Logf("already running %v; no update needed", ver)
|
up.Logf("already running %v; no update needed", ver)
|
||||||
return false
|
return false
|
||||||
@ -193,7 +210,7 @@ func (up *updater) confirm(ver string) bool {
|
|||||||
|
|
||||||
const synoinfoConfPath = "/etc/synoinfo.conf"
|
const synoinfoConfPath = "/etc/synoinfo.conf"
|
||||||
|
|
||||||
func (up *updater) updateSynology() error {
|
func (up *Updater) updateSynology() error {
|
||||||
if up.Version != "" {
|
if up.Version != "" {
|
||||||
return errors.New("installing a specific version on Synology is not supported")
|
return errors.New("installing a specific version on Synology is not supported")
|
||||||
}
|
}
|
||||||
@ -303,7 +320,7 @@ func parseSynoinfo(path string) (string, error) {
|
|||||||
return "", fmt.Errorf(`missing "unique=" field in %q`, path)
|
return "", fmt.Errorf(`missing "unique=" field in %q`, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (up *updater) updateDebLike() error {
|
func (up *Updater) updateDebLike() error {
|
||||||
if err := requireRoot(); err != nil {
|
if err := requireRoot(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -409,7 +426,7 @@ func updateDebianAptSourcesListBytes(was []byte, dstTrack string) (newContent []
|
|||||||
return buf.Bytes(), nil
|
return buf.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (up *updater) updateArchLike() error {
|
func (up *Updater) updateArchLike() error {
|
||||||
if err := exec.Command("pacman", "--query", "tailscale").Run(); err != nil && isExitError(err) {
|
if err := exec.Command("pacman", "--query", "tailscale").Run(); err != nil && isExitError(err) {
|
||||||
// Tailscale was not installed via pacman, update via tarball download
|
// Tailscale was not installed via pacman, update via tarball download
|
||||||
// instead.
|
// instead.
|
||||||
@ -427,7 +444,7 @@ const yumRepoConfigFile = "/etc/yum.repos.d/tailscale.repo"
|
|||||||
// updateFedoraLike updates tailscale on any distros in the Fedora family,
|
// updateFedoraLike updates tailscale on any distros in the Fedora family,
|
||||||
// specifically anything that uses "dnf" or "yum" package managers. The actual
|
// specifically anything that uses "dnf" or "yum" package managers. The actual
|
||||||
// package manager is passed via packageManager.
|
// package manager is passed via packageManager.
|
||||||
func (up *updater) updateFedoraLike(packageManager string) func() error {
|
func (up *Updater) updateFedoraLike(packageManager string) func() error {
|
||||||
return func() (err error) {
|
return func() (err error) {
|
||||||
if err := requireRoot(); err != nil {
|
if err := requireRoot(); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -508,7 +525,7 @@ func updateYUMRepoTrack(repoFile, dstTrack string) (rewrote bool, err error) {
|
|||||||
return true, os.WriteFile(repoFile, newContent.Bytes(), 0644)
|
return true, os.WriteFile(repoFile, newContent.Bytes(), 0644)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (up *updater) updateAlpineLike() (err error) {
|
func (up *Updater) updateAlpineLike() (err error) {
|
||||||
if up.Version != "" {
|
if up.Version != "" {
|
||||||
return errors.New("installing a specific version on Alpine-based distros is not supported")
|
return errors.New("installing a specific version on Alpine-based distros is not supported")
|
||||||
}
|
}
|
||||||
@ -570,11 +587,11 @@ func parseAlpinePackageVersion(out []byte) (string, error) {
|
|||||||
return "", errors.New("tailscale version not found in output")
|
return "", errors.New("tailscale version not found in output")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (up *updater) updateMacSys() error {
|
func (up *Updater) updateMacSys() error {
|
||||||
return errors.New("NOTREACHED: On MacSys builds, `tailscale update` is handled in Swift to launch the GUI updater")
|
return errors.New("NOTREACHED: On MacSys builds, `tailscale update` is handled in Swift to launch the GUI updater")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (up *updater) updateMacAppStore() error {
|
func (up *Updater) updateMacAppStore() error {
|
||||||
out, err := exec.Command("defaults", "read", "/Library/Preferences/com.apple.commerce.plist", "AutoUpdate").CombinedOutput()
|
out, err := exec.Command("defaults", "read", "/Library/Preferences/com.apple.commerce.plist", "AutoUpdate").CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't check App Store auto-update setting: %w, output: %q", err, string(out))
|
return fmt.Errorf("can't check App Store auto-update setting: %w, output: %q", err, string(out))
|
||||||
@ -635,7 +652,7 @@ var (
|
|||||||
markTempFileFunc func(string) error // or nil on non-Windows
|
markTempFileFunc func(string) error // or nil on non-Windows
|
||||||
)
|
)
|
||||||
|
|
||||||
func (up *updater) updateWindows() error {
|
func (up *Updater) updateWindows() error {
|
||||||
if msi := os.Getenv(winMSIEnv); msi != "" {
|
if msi := os.Getenv(winMSIEnv); msi != "" {
|
||||||
up.Logf("installing %v ...", msi)
|
up.Logf("installing %v ...", msi)
|
||||||
if err := up.installMSI(msi); err != nil {
|
if err := up.installMSI(msi); err != nil {
|
||||||
@ -705,7 +722,7 @@ func (up *updater) updateWindows() error {
|
|||||||
panic("unreachable")
|
panic("unreachable")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (up *updater) installMSI(msi string) error {
|
func (up *Updater) installMSI(msi string) error {
|
||||||
var err error
|
var err error
|
||||||
for tries := 0; tries < 2; tries++ {
|
for tries := 0; tries < 2; tries++ {
|
||||||
cmd := exec.Command("msiexec.exe", "/i", filepath.Base(msi), "/quiet", "/promptrestart", "/qn")
|
cmd := exec.Command("msiexec.exe", "/i", filepath.Base(msi), "/quiet", "/promptrestart", "/qn")
|
||||||
@ -772,7 +789,7 @@ func makeSelfCopy() (tmpPathExe string, err error) {
|
|||||||
return f2.Name(), f2.Close()
|
return f2.Name(), f2.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (up *updater) downloadURLToFile(pathSrc, fileDst string) (ret error) {
|
func (up *Updater) downloadURLToFile(pathSrc, fileDst string) (ret error) {
|
||||||
c, err := distsign.NewClient(up.Logf, up.PkgsAddr)
|
c, err := distsign.NewClient(up.Logf, up.PkgsAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -780,7 +797,7 @@ func (up *updater) downloadURLToFile(pathSrc, fileDst string) (ret error) {
|
|||||||
return c.Download(context.Background(), pathSrc, fileDst)
|
return c.Download(context.Background(), pathSrc, fileDst)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (up *updater) updateFreeBSD() (err error) {
|
func (up *Updater) updateFreeBSD() (err error) {
|
||||||
if up.Version != "" {
|
if up.Version != "" {
|
||||||
return errors.New("installing a specific version on FreeBSD is not supported")
|
return errors.New("installing a specific version on FreeBSD is not supported")
|
||||||
}
|
}
|
||||||
@ -821,7 +838,7 @@ func (up *updater) updateFreeBSD() (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (up *updater) updateLinuxBinary() error {
|
func (up *Updater) updateLinuxBinary() error {
|
||||||
return errors.New("Linux binary updates without a package manager are not supported yet")
|
return errors.New("Linux binary updates without a package manager are not supported yet")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ func runUpdate(ctx context.Context, args []string) error {
|
|||||||
if updateArgs.track != "" {
|
if updateArgs.track != "" {
|
||||||
ver = updateArgs.track
|
ver = updateArgs.track
|
||||||
}
|
}
|
||||||
err := clientupdate.Update(clientupdate.UpdateArgs{
|
err := clientupdate.Update(clientupdate.Arguments{
|
||||||
Version: ver,
|
Version: ver,
|
||||||
AppStore: updateArgs.appStore,
|
AppStore: updateArgs.appStore,
|
||||||
Logf: func(format string, args ...any) { fmt.Printf(format+"\n", args...) },
|
Logf: func(format string, args ...any) { fmt.Printf(format+"\n", args...) },
|
||||||
|
@ -94,8 +94,8 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
L github.com/google/nftables/expr from github.com/google/nftables+
|
L github.com/google/nftables/expr from github.com/google/nftables+
|
||||||
L github.com/google/nftables/internal/parseexprfunc from github.com/google/nftables+
|
L github.com/google/nftables/internal/parseexprfunc from github.com/google/nftables+
|
||||||
L github.com/google/nftables/xt from github.com/google/nftables/expr+
|
L github.com/google/nftables/xt from github.com/google/nftables/expr+
|
||||||
github.com/google/uuid from tailscale.com/ipn/ipnlocal
|
github.com/google/uuid from tailscale.com/ipn/ipnlocal+
|
||||||
github.com/hdevalence/ed25519consensus from tailscale.com/tka
|
github.com/hdevalence/ed25519consensus from tailscale.com/tka+
|
||||||
L 💣 github.com/illarion/gonotify from tailscale.com/net/dns
|
L 💣 github.com/illarion/gonotify from tailscale.com/net/dns
|
||||||
L github.com/insomniacslk/dhcp/dhcpv4 from tailscale.com/net/tstun
|
L github.com/insomniacslk/dhcp/dhcpv4 from tailscale.com/net/tstun
|
||||||
L github.com/insomniacslk/dhcp/iana from github.com/insomniacslk/dhcp/dhcpv4
|
L github.com/insomniacslk/dhcp/iana from github.com/insomniacslk/dhcp/dhcpv4
|
||||||
@ -216,6 +216,8 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
LD tailscale.com/chirp from tailscale.com/cmd/tailscaled
|
LD tailscale.com/chirp from tailscale.com/cmd/tailscaled
|
||||||
tailscale.com/client/tailscale from tailscale.com/derp
|
tailscale.com/client/tailscale from tailscale.com/derp
|
||||||
tailscale.com/client/tailscale/apitype from tailscale.com/ipn/ipnlocal+
|
tailscale.com/client/tailscale/apitype from tailscale.com/ipn/ipnlocal+
|
||||||
|
tailscale.com/clientupdate from tailscale.com/ipn/ipnlocal
|
||||||
|
tailscale.com/clientupdate/distsign from tailscale.com/clientupdate
|
||||||
tailscale.com/cmd/tailscaled/childproc from tailscale.com/ssh/tailssh+
|
tailscale.com/cmd/tailscaled/childproc from tailscale.com/ssh/tailssh+
|
||||||
tailscale.com/control/controlbase from tailscale.com/control/controlclient+
|
tailscale.com/control/controlbase from tailscale.com/control/controlclient+
|
||||||
tailscale.com/control/controlclient from tailscale.com/ipn/ipnlocal+
|
tailscale.com/control/controlclient from tailscale.com/ipn/ipnlocal+
|
||||||
@ -334,7 +336,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
L tailscale.com/util/linuxfw from tailscale.com/net/netns+
|
L tailscale.com/util/linuxfw from tailscale.com/net/netns+
|
||||||
tailscale.com/util/mak from tailscale.com/control/controlclient+
|
tailscale.com/util/mak from tailscale.com/control/controlclient+
|
||||||
tailscale.com/util/multierr from tailscale.com/control/controlclient+
|
tailscale.com/util/multierr from tailscale.com/control/controlclient+
|
||||||
tailscale.com/util/must from tailscale.com/logpolicy
|
tailscale.com/util/must from tailscale.com/logpolicy+
|
||||||
💣 tailscale.com/util/osdiag from tailscale.com/cmd/tailscaled+
|
💣 tailscale.com/util/osdiag from tailscale.com/cmd/tailscaled+
|
||||||
W 💣 tailscale.com/util/osdiag/internal/wsc from tailscale.com/util/osdiag
|
W 💣 tailscale.com/util/osdiag/internal/wsc from tailscale.com/util/osdiag
|
||||||
tailscale.com/util/osshare from tailscale.com/ipn/ipnlocal+
|
tailscale.com/util/osshare from tailscale.com/ipn/ipnlocal+
|
||||||
@ -349,7 +351,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
tailscale.com/util/testenv from tailscale.com/ipn/ipnlocal+
|
tailscale.com/util/testenv from tailscale.com/ipn/ipnlocal+
|
||||||
tailscale.com/util/uniq from tailscale.com/wgengine/magicsock+
|
tailscale.com/util/uniq from tailscale.com/wgengine/magicsock+
|
||||||
💣 tailscale.com/util/winutil from tailscale.com/control/controlclient+
|
💣 tailscale.com/util/winutil from tailscale.com/control/controlclient+
|
||||||
W 💣 tailscale.com/util/winutil/authenticode from tailscale.com/util/osdiag
|
W 💣 tailscale.com/util/winutil/authenticode from tailscale.com/util/osdiag+
|
||||||
W tailscale.com/util/winutil/policy from tailscale.com/ipn/ipnlocal
|
W tailscale.com/util/winutil/policy from tailscale.com/ipn/ipnlocal
|
||||||
tailscale.com/version from tailscale.com/derp+
|
tailscale.com/version from tailscale.com/derp+
|
||||||
tailscale.com/version/distro from tailscale.com/hostinfo+
|
tailscale.com/version/distro from tailscale.com/hostinfo+
|
||||||
|
@ -16,13 +16,13 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"tailscale.com/clientupdate"
|
||||||
"tailscale.com/envknob"
|
"tailscale.com/envknob"
|
||||||
"tailscale.com/net/sockstats"
|
"tailscale.com/net/sockstats"
|
||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
"tailscale.com/util/clientmetric"
|
"tailscale.com/util/clientmetric"
|
||||||
"tailscale.com/util/goroutines"
|
"tailscale.com/util/goroutines"
|
||||||
"tailscale.com/version"
|
"tailscale.com/version"
|
||||||
"tailscale.com/version/distro"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var c2nLogHeap func(http.ResponseWriter, *http.Request) // non-nil on most platforms (c2n_pprof.go)
|
var c2nLogHeap func(http.ResponseWriter, *http.Request) // non-nil on most platforms (c2n_pprof.go)
|
||||||
@ -115,17 +115,24 @@ func (b *LocalBackend) handleC2NUpdate(w http.ResponseWriter, r *http.Request) {
|
|||||||
// TODO(bradfitz): add some sort of semaphore that prevents two concurrent
|
// TODO(bradfitz): add some sort of semaphore that prevents two concurrent
|
||||||
// updates, or if one happened in the past 5 minutes, or something.
|
// updates, or if one happened in the past 5 minutes, or something.
|
||||||
|
|
||||||
var res tailcfg.C2NUpdateResponse
|
// GET returns the current status, and POST actually begins an update.
|
||||||
res.Enabled = envknob.AllowsRemoteUpdate()
|
if r.Method != "GET" && r.Method != "POST" {
|
||||||
res.Supported = runtime.GOOS == "windows" || (runtime.GOOS == "linux" && distro.Get() == distro.Debian)
|
|
||||||
|
|
||||||
switch r.Method {
|
|
||||||
case "GET", "POST":
|
|
||||||
default:
|
|
||||||
http.Error(w, "bad method", http.StatusMethodNotAllowed)
|
http.Error(w, "bad method", http.StatusMethodNotAllowed)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If NewUpdater does not return an error, we can update the installation.
|
||||||
|
// Exception: When version.IsMacSysExt returns true, we don't support that
|
||||||
|
// yet. TODO(cpalmer, #6995): Implement it.
|
||||||
|
//
|
||||||
|
// Note that we create the Updater solely to check for errors; we do not
|
||||||
|
// invoke it here. For this purpose, it is ok to pass it a zero Arguments.
|
||||||
|
_, err := clientupdate.NewUpdater(clientupdate.Arguments{})
|
||||||
|
res := tailcfg.C2NUpdateResponse{
|
||||||
|
Enabled: envknob.AllowsRemoteUpdate(),
|
||||||
|
Supported: err == nil && !version.IsMacSysExt(),
|
||||||
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(w).Encode(res)
|
json.NewEncoder(w).Encode(res)
|
||||||
@ -134,16 +141,15 @@ func (b *LocalBackend) handleC2NUpdate(w http.ResponseWriter, r *http.Request) {
|
|||||||
if r.Method == "GET" {
|
if r.Method == "GET" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !res.Enabled {
|
if !res.Enabled {
|
||||||
res.Err = "not enabled"
|
res.Err = "not enabled"
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !res.Supported {
|
if !res.Supported {
|
||||||
res.Err = "not supported"
|
res.Err = "not supported"
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdTS, err := findCmdTailscale()
|
cmdTS, err := findCmdTailscale()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
res.Err = fmt.Sprintf("failed to find cmd/tailscale binary: %v", err)
|
res.Err = fmt.Sprintf("failed to find cmd/tailscale binary: %v", err)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user