mirror of
https://github.com/tailscale/tailscale.git
synced 2025-10-04 20:12:16 +02:00
feature/clientupdate: move clientupdate to a modular feature, disabled for tsnet
Updates #12614 Change-Id: I5f685dec84a5396b7c2b66f2788ae3d286e1ddc6 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
69c79cb9f3
commit
038cdb4640
@ -24,9 +24,9 @@ import (
|
|||||||
|
|
||||||
"tailscale.com/client/local"
|
"tailscale.com/client/local"
|
||||||
"tailscale.com/client/tailscale/apitype"
|
"tailscale.com/client/tailscale/apitype"
|
||||||
"tailscale.com/clientupdate"
|
|
||||||
"tailscale.com/envknob"
|
"tailscale.com/envknob"
|
||||||
"tailscale.com/envknob/featureknob"
|
"tailscale.com/envknob/featureknob"
|
||||||
|
"tailscale.com/feature"
|
||||||
"tailscale.com/hostinfo"
|
"tailscale.com/hostinfo"
|
||||||
"tailscale.com/ipn"
|
"tailscale.com/ipn"
|
||||||
"tailscale.com/ipn/ipnstate"
|
"tailscale.com/ipn/ipnstate"
|
||||||
@ -1049,7 +1049,7 @@ func availableFeatures() map[string]bool {
|
|||||||
"advertise-routes": true, // available on all platforms
|
"advertise-routes": true, // available on all platforms
|
||||||
"use-exit-node": featureknob.CanUseExitNode() == nil,
|
"use-exit-node": featureknob.CanUseExitNode() == nil,
|
||||||
"ssh": featureknob.CanRunTailscaleSSH() == nil,
|
"ssh": featureknob.CanRunTailscaleSSH() == nil,
|
||||||
"auto-update": version.IsUnstableBuild() && clientupdate.CanAutoUpdate(),
|
"auto-update": version.IsUnstableBuild() && feature.CanAutoUpdate(),
|
||||||
}
|
}
|
||||||
return features
|
return features
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"tailscale.com/feature"
|
||||||
"tailscale.com/hostinfo"
|
"tailscale.com/hostinfo"
|
||||||
"tailscale.com/types/lazy"
|
"tailscale.com/types/lazy"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
@ -252,9 +253,13 @@ func (up *Updater) getUpdateFunction() (fn updateFunction, canAutoUpdate bool) {
|
|||||||
|
|
||||||
var canAutoUpdateCache lazy.SyncValue[bool]
|
var canAutoUpdateCache lazy.SyncValue[bool]
|
||||||
|
|
||||||
// CanAutoUpdate reports whether auto-updating via the clientupdate package
|
func init() {
|
||||||
|
feature.HookCanAutoUpdate.Set(canAutoUpdate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// canAutoUpdate reports whether auto-updating via the clientupdate package
|
||||||
// is supported for the current os/distro.
|
// is supported for the current os/distro.
|
||||||
func CanAutoUpdate() bool { return canAutoUpdateCache.Get(canAutoUpdateUncached) }
|
func canAutoUpdate() bool { return canAutoUpdateCache.Get(canAutoUpdateUncached) }
|
||||||
|
|
||||||
func canAutoUpdateUncached() bool {
|
func canAutoUpdateUncached() bool {
|
||||||
if version.IsMacSysExt() {
|
if version.IsMacSysExt() {
|
||||||
|
@ -12,7 +12,7 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
|
|||||||
github.com/coder/websocket/internal/util from github.com/coder/websocket
|
github.com/coder/websocket/internal/util from github.com/coder/websocket
|
||||||
github.com/coder/websocket/internal/xsync from github.com/coder/websocket
|
github.com/coder/websocket/internal/xsync from github.com/coder/websocket
|
||||||
💣 github.com/davecgh/go-spew/spew from k8s.io/apimachinery/pkg/util/dump
|
💣 github.com/davecgh/go-spew/spew from k8s.io/apimachinery/pkg/util/dump
|
||||||
W 💣 github.com/dblohm7/wingoes from github.com/dblohm7/wingoes/com+
|
W 💣 github.com/dblohm7/wingoes from tailscale.com/net/tshttpproxy+
|
||||||
W 💣 github.com/dblohm7/wingoes/com from tailscale.com/util/osdiag+
|
W 💣 github.com/dblohm7/wingoes/com from tailscale.com/util/osdiag+
|
||||||
W 💣 github.com/dblohm7/wingoes/com/automation from tailscale.com/util/osdiag/internal/wsc
|
W 💣 github.com/dblohm7/wingoes/com/automation from tailscale.com/util/osdiag/internal/wsc
|
||||||
W github.com/dblohm7/wingoes/internal from github.com/dblohm7/wingoes/com
|
W github.com/dblohm7/wingoes/internal from github.com/dblohm7/wingoes/com
|
||||||
@ -60,7 +60,7 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
|
|||||||
github.com/google/gofuzz from k8s.io/apimachinery/pkg/apis/meta/v1+
|
github.com/google/gofuzz from k8s.io/apimachinery/pkg/apis/meta/v1+
|
||||||
github.com/google/gofuzz/bytesource from github.com/google/gofuzz
|
github.com/google/gofuzz/bytesource from github.com/google/gofuzz
|
||||||
github.com/google/uuid from github.com/prometheus-community/pro-bing+
|
github.com/google/uuid from github.com/prometheus-community/pro-bing+
|
||||||
github.com/hdevalence/ed25519consensus from tailscale.com/clientupdate/distsign+
|
github.com/hdevalence/ed25519consensus from tailscale.com/tka
|
||||||
github.com/josharian/intern from github.com/mailru/easyjson/jlexer
|
github.com/josharian/intern from github.com/mailru/easyjson/jlexer
|
||||||
L 💣 github.com/jsimonetti/rtnetlink from tailscale.com/net/netmon
|
L 💣 github.com/jsimonetti/rtnetlink from tailscale.com/net/netmon
|
||||||
L github.com/jsimonetti/rtnetlink/internal/unix from github.com/jsimonetti/rtnetlink
|
L github.com/jsimonetti/rtnetlink/internal/unix from github.com/jsimonetti/rtnetlink
|
||||||
@ -686,8 +686,6 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
|
|||||||
tailscale.com/client/tailscale from tailscale.com/cmd/k8s-operator+
|
tailscale.com/client/tailscale from tailscale.com/cmd/k8s-operator+
|
||||||
tailscale.com/client/tailscale/apitype from tailscale.com/client/tailscale+
|
tailscale.com/client/tailscale/apitype from tailscale.com/client/tailscale+
|
||||||
tailscale.com/client/web from tailscale.com/ipn/ipnlocal
|
tailscale.com/client/web from tailscale.com/ipn/ipnlocal
|
||||||
tailscale.com/clientupdate from tailscale.com/client/web+
|
|
||||||
LW tailscale.com/clientupdate/distsign from tailscale.com/clientupdate
|
|
||||||
tailscale.com/control/controlbase from tailscale.com/control/controlhttp+
|
tailscale.com/control/controlbase from tailscale.com/control/controlhttp+
|
||||||
tailscale.com/control/controlclient from tailscale.com/ipn/ipnlocal+
|
tailscale.com/control/controlclient from tailscale.com/ipn/ipnlocal+
|
||||||
tailscale.com/control/controlhttp from tailscale.com/control/controlclient
|
tailscale.com/control/controlhttp from tailscale.com/control/controlclient
|
||||||
@ -780,7 +778,7 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
|
|||||||
tailscale.com/net/tlsdial/blockblame from tailscale.com/net/tlsdial
|
tailscale.com/net/tlsdial/blockblame from tailscale.com/net/tlsdial
|
||||||
tailscale.com/net/tsaddr from tailscale.com/client/web+
|
tailscale.com/net/tsaddr from tailscale.com/client/web+
|
||||||
tailscale.com/net/tsdial from tailscale.com/control/controlclient+
|
tailscale.com/net/tsdial from tailscale.com/control/controlclient+
|
||||||
💣 tailscale.com/net/tshttpproxy from tailscale.com/clientupdate/distsign+
|
💣 tailscale.com/net/tshttpproxy from tailscale.com/control/controlclient+
|
||||||
tailscale.com/net/tstun from tailscale.com/tsd+
|
tailscale.com/net/tstun from tailscale.com/tsd+
|
||||||
tailscale.com/net/udprelay/endpoint from tailscale.com/wgengine/magicsock
|
tailscale.com/net/udprelay/endpoint from tailscale.com/wgengine/magicsock
|
||||||
tailscale.com/net/udprelay/status from tailscale.com/client/local
|
tailscale.com/net/udprelay/status from tailscale.com/client/local
|
||||||
@ -829,7 +827,7 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
|
|||||||
tailscale.com/util/cibuild from tailscale.com/health
|
tailscale.com/util/cibuild from tailscale.com/health
|
||||||
tailscale.com/util/clientmetric from tailscale.com/cmd/k8s-operator+
|
tailscale.com/util/clientmetric from tailscale.com/cmd/k8s-operator+
|
||||||
tailscale.com/util/cloudenv from tailscale.com/hostinfo+
|
tailscale.com/util/cloudenv from tailscale.com/hostinfo+
|
||||||
tailscale.com/util/cmpver from tailscale.com/clientupdate+
|
LW tailscale.com/util/cmpver from tailscale.com/net/dns+
|
||||||
tailscale.com/util/ctxkey from tailscale.com/client/tailscale/apitype+
|
tailscale.com/util/ctxkey from tailscale.com/client/tailscale/apitype+
|
||||||
💣 tailscale.com/util/deephash from tailscale.com/ipn/ipnlocal+
|
💣 tailscale.com/util/deephash from tailscale.com/ipn/ipnlocal+
|
||||||
L 💣 tailscale.com/util/dirwalk from tailscale.com/metrics
|
L 💣 tailscale.com/util/dirwalk from tailscale.com/metrics
|
||||||
@ -843,7 +841,7 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
|
|||||||
tailscale.com/util/lineiter from tailscale.com/hostinfo+
|
tailscale.com/util/lineiter from tailscale.com/hostinfo+
|
||||||
tailscale.com/util/mak from tailscale.com/appc+
|
tailscale.com/util/mak from tailscale.com/appc+
|
||||||
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/clientupdate/distsign+
|
tailscale.com/util/must from tailscale.com/logpolicy+
|
||||||
tailscale.com/util/nocasemaps from tailscale.com/types/ipproto
|
tailscale.com/util/nocasemaps from tailscale.com/types/ipproto
|
||||||
💣 tailscale.com/util/osdiag from tailscale.com/ipn/localapi
|
💣 tailscale.com/util/osdiag from tailscale.com/ipn/localapi
|
||||||
W 💣 tailscale.com/util/osdiag/internal/wsc from tailscale.com/util/osdiag
|
W 💣 tailscale.com/util/osdiag/internal/wsc from tailscale.com/util/osdiag
|
||||||
@ -869,8 +867,8 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
|
|||||||
tailscale.com/util/truncate from tailscale.com/logtail
|
tailscale.com/util/truncate from tailscale.com/logtail
|
||||||
tailscale.com/util/usermetric from tailscale.com/health+
|
tailscale.com/util/usermetric from tailscale.com/health+
|
||||||
tailscale.com/util/vizerror from tailscale.com/tailcfg+
|
tailscale.com/util/vizerror from tailscale.com/tailcfg+
|
||||||
💣 tailscale.com/util/winutil from tailscale.com/clientupdate+
|
💣 tailscale.com/util/winutil from tailscale.com/hostinfo+
|
||||||
W 💣 tailscale.com/util/winutil/authenticode from tailscale.com/clientupdate+
|
W 💣 tailscale.com/util/winutil/authenticode from tailscale.com/util/osdiag
|
||||||
W 💣 tailscale.com/util/winutil/gp from tailscale.com/net/dns+
|
W 💣 tailscale.com/util/winutil/gp from tailscale.com/net/dns+
|
||||||
W tailscale.com/util/winutil/policy from tailscale.com/ipn/ipnlocal
|
W tailscale.com/util/winutil/policy from tailscale.com/ipn/ipnlocal
|
||||||
W 💣 tailscale.com/util/winutil/winenv from tailscale.com/hostinfo+
|
W 💣 tailscale.com/util/winutil/winenv from tailscale.com/hostinfo+
|
||||||
@ -907,7 +905,7 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
|
|||||||
golang.org/x/crypto/salsa20/salsa from golang.org/x/crypto/nacl/box+
|
golang.org/x/crypto/salsa20/salsa from golang.org/x/crypto/nacl/box+
|
||||||
LD golang.org/x/crypto/ssh from tailscale.com/ipn/ipnlocal
|
LD golang.org/x/crypto/ssh from tailscale.com/ipn/ipnlocal
|
||||||
LD golang.org/x/crypto/ssh/internal/bcrypt_pbkdf from golang.org/x/crypto/ssh
|
LD golang.org/x/crypto/ssh/internal/bcrypt_pbkdf from golang.org/x/crypto/ssh
|
||||||
golang.org/x/exp/constraints from github.com/dblohm7/wingoes/pe+
|
golang.org/x/exp/constraints from tailscale.com/tsweb/varz+
|
||||||
golang.org/x/exp/maps from sigs.k8s.io/controller-runtime/pkg/cache+
|
golang.org/x/exp/maps from sigs.k8s.io/controller-runtime/pkg/cache+
|
||||||
golang.org/x/exp/slices from tailscale.com/cmd/k8s-operator+
|
golang.org/x/exp/slices from tailscale.com/cmd/k8s-operator+
|
||||||
golang.org/x/net/bpf from github.com/mdlayher/genetlink+
|
golang.org/x/net/bpf from github.com/mdlayher/genetlink+
|
||||||
@ -944,13 +942,12 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
|
|||||||
golang.org/x/text/unicode/bidi from golang.org/x/net/idna+
|
golang.org/x/text/unicode/bidi from golang.org/x/net/idna+
|
||||||
golang.org/x/text/unicode/norm from golang.org/x/net/idna
|
golang.org/x/text/unicode/norm from golang.org/x/net/idna
|
||||||
golang.org/x/time/rate from gvisor.dev/gvisor/pkg/log+
|
golang.org/x/time/rate from gvisor.dev/gvisor/pkg/log+
|
||||||
archive/tar from tailscale.com/clientupdate
|
|
||||||
bufio from compress/flate+
|
bufio from compress/flate+
|
||||||
bytes from archive/tar+
|
bytes from bufio+
|
||||||
cmp from github.com/gaissmai/bart+
|
cmp from github.com/gaissmai/bart+
|
||||||
compress/flate from compress/gzip+
|
compress/flate from compress/gzip+
|
||||||
compress/gzip from github.com/emicklei/go-restful/v3+
|
compress/gzip from github.com/emicklei/go-restful/v3+
|
||||||
compress/zlib from debug/pe+
|
compress/zlib from github.com/emicklei/go-restful/v3+
|
||||||
container/heap from gvisor.dev/gvisor/pkg/tcpip/transport/tcp+
|
container/heap from gvisor.dev/gvisor/pkg/tcpip/transport/tcp+
|
||||||
container/list from crypto/tls+
|
container/list from crypto/tls+
|
||||||
context from crypto/tls+
|
context from crypto/tls+
|
||||||
@ -1034,10 +1031,10 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
|
|||||||
encoding/json from expvar+
|
encoding/json from expvar+
|
||||||
encoding/pem from crypto/tls+
|
encoding/pem from crypto/tls+
|
||||||
encoding/xml from github.com/emicklei/go-restful/v3+
|
encoding/xml from github.com/emicklei/go-restful/v3+
|
||||||
errors from archive/tar+
|
errors from bufio+
|
||||||
expvar from github.com/prometheus/client_golang/prometheus+
|
expvar from github.com/prometheus/client_golang/prometheus+
|
||||||
flag from github.com/spf13/pflag+
|
flag from github.com/spf13/pflag+
|
||||||
fmt from archive/tar+
|
fmt from compress/flate+
|
||||||
go/ast from go/doc+
|
go/ast from go/doc+
|
||||||
go/build/constraint from go/parser
|
go/build/constraint from go/parser
|
||||||
go/doc from k8s.io/apimachinery/pkg/runtime
|
go/doc from k8s.io/apimachinery/pkg/runtime
|
||||||
@ -1063,7 +1060,7 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
|
|||||||
internal/filepathlite from os+
|
internal/filepathlite from os+
|
||||||
internal/fmtsort from fmt+
|
internal/fmtsort from fmt+
|
||||||
internal/goarch from crypto/internal/fips140deps/cpu+
|
internal/goarch from crypto/internal/fips140deps/cpu+
|
||||||
internal/godebug from archive/tar+
|
internal/godebug from crypto/internal/fips140deps/godebug+
|
||||||
internal/godebugs from internal/godebug+
|
internal/godebugs from internal/godebug+
|
||||||
internal/goexperiment from hash/maphash+
|
internal/goexperiment from hash/maphash+
|
||||||
internal/goos from crypto/x509+
|
internal/goos from crypto/x509+
|
||||||
@ -1100,8 +1097,8 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
|
|||||||
internal/testlog from os
|
internal/testlog from os
|
||||||
internal/trace/tracev2 from runtime+
|
internal/trace/tracev2 from runtime+
|
||||||
internal/unsafeheader from internal/reflectlite+
|
internal/unsafeheader from internal/reflectlite+
|
||||||
io from archive/tar+
|
io from bufio+
|
||||||
io/fs from archive/tar+
|
io/fs from crypto/x509+
|
||||||
io/ioutil from github.com/digitalocean/go-smbios/smbios+
|
io/ioutil from github.com/digitalocean/go-smbios/smbios+
|
||||||
iter from go/ast+
|
iter from go/ast+
|
||||||
log from expvar+
|
log from expvar+
|
||||||
@ -1110,7 +1107,7 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
|
|||||||
log/slog/internal from log/slog
|
log/slog/internal from log/slog
|
||||||
log/slog/internal/buffer from log/slog
|
log/slog/internal/buffer from log/slog
|
||||||
maps from sigs.k8s.io/controller-runtime/pkg/predicate+
|
maps from sigs.k8s.io/controller-runtime/pkg/predicate+
|
||||||
math from archive/tar+
|
math from compress/flate+
|
||||||
math/big from crypto/dsa+
|
math/big from crypto/dsa+
|
||||||
math/bits from compress/flate+
|
math/bits from compress/flate+
|
||||||
math/rand from github.com/google/go-cmp/cmp+
|
math/rand from github.com/google/go-cmp/cmp+
|
||||||
@ -1132,29 +1129,29 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
|
|||||||
os from crypto/internal/sysrand+
|
os from crypto/internal/sysrand+
|
||||||
os/exec from github.com/godbus/dbus/v5+
|
os/exec from github.com/godbus/dbus/v5+
|
||||||
os/signal from sigs.k8s.io/controller-runtime/pkg/manager/signals
|
os/signal from sigs.k8s.io/controller-runtime/pkg/manager/signals
|
||||||
os/user from archive/tar+
|
os/user from github.com/godbus/dbus/v5+
|
||||||
path from archive/tar+
|
path from debug/dwarf+
|
||||||
path/filepath from archive/tar+
|
path/filepath from crypto/x509+
|
||||||
reflect from archive/tar+
|
reflect from crypto/x509+
|
||||||
regexp from github.com/davecgh/go-spew/spew+
|
regexp from github.com/davecgh/go-spew/spew+
|
||||||
regexp/syntax from regexp
|
regexp/syntax from regexp
|
||||||
runtime from archive/tar+
|
runtime from crypto/internal/fips140+
|
||||||
runtime/debug from github.com/coder/websocket/internal/xsync+
|
runtime/debug from github.com/coder/websocket/internal/xsync+
|
||||||
runtime/metrics from github.com/prometheus/client_golang/prometheus+
|
runtime/metrics from github.com/prometheus/client_golang/prometheus+
|
||||||
runtime/pprof from net/http/pprof+
|
runtime/pprof from net/http/pprof+
|
||||||
runtime/trace from net/http/pprof
|
runtime/trace from net/http/pprof
|
||||||
slices from encoding/base32+
|
slices from encoding/base32+
|
||||||
sort from compress/flate+
|
sort from compress/flate+
|
||||||
strconv from archive/tar+
|
strconv from compress/flate+
|
||||||
strings from archive/tar+
|
strings from bufio+
|
||||||
W structs from internal/syscall/windows
|
W structs from internal/syscall/windows
|
||||||
sync from archive/tar+
|
sync from compress/flate+
|
||||||
sync/atomic from context+
|
sync/atomic from context+
|
||||||
syscall from archive/tar+
|
syscall from crypto/internal/sysrand+
|
||||||
text/tabwriter from k8s.io/apimachinery/pkg/util/diff+
|
text/tabwriter from k8s.io/apimachinery/pkg/util/diff+
|
||||||
text/template from html/template
|
text/template from html/template
|
||||||
text/template/parse from html/template+
|
text/template/parse from html/template+
|
||||||
time from archive/tar+
|
time from compress/gzip+
|
||||||
unicode from bytes+
|
unicode from bytes+
|
||||||
unicode/utf16 from crypto/x509+
|
unicode/utf16 from crypto/x509+
|
||||||
unicode/utf8 from bufio+
|
unicode/utf8 from bufio+
|
||||||
|
@ -15,8 +15,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/peterbourgon/ff/v3/ffcli"
|
"github.com/peterbourgon/ff/v3/ffcli"
|
||||||
"tailscale.com/clientupdate"
|
|
||||||
"tailscale.com/cmd/tailscale/cli/ffcomplete"
|
"tailscale.com/cmd/tailscale/cli/ffcomplete"
|
||||||
|
"tailscale.com/feature/buildfeatures"
|
||||||
"tailscale.com/ipn"
|
"tailscale.com/ipn"
|
||||||
"tailscale.com/net/netutil"
|
"tailscale.com/net/netutil"
|
||||||
"tailscale.com/net/tsaddr"
|
"tailscale.com/net/tsaddr"
|
||||||
@ -226,21 +226,14 @@ func runSet(ctx context.Context, args []string) (retErr error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if maskedPrefs.AutoUpdateSet.ApplySet {
|
if maskedPrefs.AutoUpdateSet.ApplySet && buildfeatures.HasClientUpdate && version.IsMacSysExt() {
|
||||||
if !clientupdate.CanAutoUpdate() {
|
apply := "0"
|
||||||
return errors.New("automatic updates are not supported on this platform")
|
if maskedPrefs.AutoUpdate.Apply.EqualBool(true) {
|
||||||
|
apply = "1"
|
||||||
}
|
}
|
||||||
// On macsys, tailscaled will set the Sparkle auto-update setting. It
|
out, err := exec.Command("defaults", "write", "io.tailscale.ipn.macsys", "SUAutomaticallyUpdate", apply).CombinedOutput()
|
||||||
// does not use clientupdate.
|
if err != nil {
|
||||||
if version.IsMacSysExt() {
|
return fmt.Errorf("failed to enable automatic updates: %v, %q", err, out)
|
||||||
apply := "0"
|
|
||||||
if maskedPrefs.AutoUpdate.Apply.EqualBool(true) {
|
|
||||||
apply = "1"
|
|
||||||
}
|
|
||||||
out, err := exec.Command("defaults", "write", "io.tailscale.ipn.macsys", "SUAutomaticallyUpdate", apply).CombinedOutput()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to enable automatic updates: %v, %q", err, out)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
|
|||||||
tailscale.com/client/tailscale from tailscale.com/internal/client/tailscale
|
tailscale.com/client/tailscale from tailscale.com/internal/client/tailscale
|
||||||
tailscale.com/client/tailscale/apitype from tailscale.com/client/tailscale+
|
tailscale.com/client/tailscale/apitype from tailscale.com/client/tailscale+
|
||||||
tailscale.com/client/web from tailscale.com/cmd/tailscale/cli
|
tailscale.com/client/web from tailscale.com/cmd/tailscale/cli
|
||||||
tailscale.com/clientupdate from tailscale.com/client/web+
|
tailscale.com/clientupdate from tailscale.com/cmd/tailscale/cli
|
||||||
LW tailscale.com/clientupdate/distsign from tailscale.com/clientupdate
|
LW tailscale.com/clientupdate/distsign from tailscale.com/clientupdate
|
||||||
tailscale.com/cmd/tailscale/cli from tailscale.com/cmd/tailscale
|
tailscale.com/cmd/tailscale/cli from tailscale.com/cmd/tailscale
|
||||||
tailscale.com/cmd/tailscale/cli/ffcomplete from tailscale.com/cmd/tailscale/cli
|
tailscale.com/cmd/tailscale/cli/ffcomplete from tailscale.com/cmd/tailscale/cli
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/depaware)
|
tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/depaware)
|
||||||
|
|
||||||
filippo.io/edwards25519 from github.com/hdevalence/ed25519consensus
|
|
||||||
filippo.io/edwards25519/field from filippo.io/edwards25519
|
|
||||||
github.com/digitalocean/go-smbios/smbios from tailscale.com/posture
|
github.com/digitalocean/go-smbios/smbios from tailscale.com/posture
|
||||||
github.com/gaissmai/bart from tailscale.com/net/ipset+
|
github.com/gaissmai/bart from tailscale.com/net/ipset+
|
||||||
github.com/gaissmai/bart/internal/bitset from github.com/gaissmai/bart+
|
github.com/gaissmai/bart/internal/bitset from github.com/gaissmai/bart+
|
||||||
@ -13,7 +11,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
github.com/go-json-experiment/json/internal/jsonwire from github.com/go-json-experiment/json+
|
github.com/go-json-experiment/json/internal/jsonwire from github.com/go-json-experiment/json+
|
||||||
github.com/go-json-experiment/json/jsontext from github.com/go-json-experiment/json+
|
github.com/go-json-experiment/json/jsontext from github.com/go-json-experiment/json+
|
||||||
github.com/golang/groupcache/lru from tailscale.com/net/dnscache
|
github.com/golang/groupcache/lru from tailscale.com/net/dnscache
|
||||||
github.com/hdevalence/ed25519consensus from tailscale.com/clientupdate/distsign
|
|
||||||
💣 github.com/jsimonetti/rtnetlink from tailscale.com/net/netmon
|
💣 github.com/jsimonetti/rtnetlink from tailscale.com/net/netmon
|
||||||
github.com/jsimonetti/rtnetlink/internal/unix from github.com/jsimonetti/rtnetlink
|
github.com/jsimonetti/rtnetlink/internal/unix from github.com/jsimonetti/rtnetlink
|
||||||
github.com/klauspost/compress from github.com/klauspost/compress/zstd
|
github.com/klauspost/compress from github.com/klauspost/compress/zstd
|
||||||
@ -44,8 +41,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
tailscale.com/appc from tailscale.com/ipn/ipnlocal+
|
tailscale.com/appc from tailscale.com/ipn/ipnlocal+
|
||||||
tailscale.com/atomicfile from tailscale.com/ipn+
|
tailscale.com/atomicfile from tailscale.com/ipn+
|
||||||
tailscale.com/client/tailscale/apitype from tailscale.com/ipn/ipnauth+
|
tailscale.com/client/tailscale/apitype from tailscale.com/ipn/ipnauth+
|
||||||
tailscale.com/clientupdate from tailscale.com/ipn/ipnlocal+
|
|
||||||
tailscale.com/clientupdate/distsign from tailscale.com/clientupdate
|
|
||||||
tailscale.com/cmd/tailscaled/childproc from tailscale.com/cmd/tailscaled
|
tailscale.com/cmd/tailscaled/childproc from tailscale.com/cmd/tailscaled
|
||||||
tailscale.com/control/controlbase from tailscale.com/control/controlhttp+
|
tailscale.com/control/controlbase from tailscale.com/control/controlhttp+
|
||||||
tailscale.com/control/controlclient from tailscale.com/cmd/tailscaled+
|
tailscale.com/control/controlclient from tailscale.com/cmd/tailscaled+
|
||||||
@ -65,7 +60,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
tailscale.com/feature/condregister/portmapper from tailscale.com/feature/condregister
|
tailscale.com/feature/condregister/portmapper from tailscale.com/feature/condregister
|
||||||
tailscale.com/health from tailscale.com/cmd/tailscaled+
|
tailscale.com/health from tailscale.com/cmd/tailscaled+
|
||||||
tailscale.com/health/healthmsg from tailscale.com/ipn/ipnlocal+
|
tailscale.com/health/healthmsg from tailscale.com/ipn/ipnlocal+
|
||||||
tailscale.com/hostinfo from tailscale.com/clientupdate+
|
tailscale.com/hostinfo from tailscale.com/cmd/tailscaled+
|
||||||
tailscale.com/internal/noiseconn from tailscale.com/control/controlclient
|
tailscale.com/internal/noiseconn from tailscale.com/control/controlclient
|
||||||
tailscale.com/ipn from tailscale.com/cmd/tailscaled+
|
tailscale.com/ipn from tailscale.com/cmd/tailscaled+
|
||||||
tailscale.com/ipn/conffile from tailscale.com/cmd/tailscaled+
|
tailscale.com/ipn/conffile from tailscale.com/cmd/tailscaled+
|
||||||
@ -116,7 +111,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
tailscale.com/net/tlsdial/blockblame from tailscale.com/net/tlsdial
|
tailscale.com/net/tlsdial/blockblame from tailscale.com/net/tlsdial
|
||||||
tailscale.com/net/tsaddr from tailscale.com/ipn+
|
tailscale.com/net/tsaddr from tailscale.com/ipn+
|
||||||
tailscale.com/net/tsdial from tailscale.com/cmd/tailscaled+
|
tailscale.com/net/tsdial from tailscale.com/cmd/tailscaled+
|
||||||
tailscale.com/net/tshttpproxy from tailscale.com/clientupdate/distsign+
|
tailscale.com/net/tshttpproxy from tailscale.com/cmd/tailscaled+
|
||||||
tailscale.com/net/tstun from tailscale.com/cmd/tailscaled+
|
tailscale.com/net/tstun from tailscale.com/cmd/tailscaled+
|
||||||
tailscale.com/net/udprelay/endpoint from tailscale.com/wgengine/magicsock
|
tailscale.com/net/udprelay/endpoint from tailscale.com/wgengine/magicsock
|
||||||
tailscale.com/omit from tailscale.com/ipn/conffile
|
tailscale.com/omit from tailscale.com/ipn/conffile
|
||||||
@ -142,7 +137,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
tailscale.com/types/flagtype from tailscale.com/cmd/tailscaled
|
tailscale.com/types/flagtype from tailscale.com/cmd/tailscaled
|
||||||
tailscale.com/types/ipproto from tailscale.com/ipn+
|
tailscale.com/types/ipproto from tailscale.com/ipn+
|
||||||
tailscale.com/types/key from tailscale.com/cmd/tailscaled+
|
tailscale.com/types/key from tailscale.com/cmd/tailscaled+
|
||||||
tailscale.com/types/lazy from tailscale.com/clientupdate+
|
tailscale.com/types/lazy from tailscale.com/hostinfo+
|
||||||
tailscale.com/types/logger from tailscale.com/appc+
|
tailscale.com/types/logger from tailscale.com/appc+
|
||||||
tailscale.com/types/logid from tailscale.com/cmd/tailscaled+
|
tailscale.com/types/logid from tailscale.com/cmd/tailscaled+
|
||||||
tailscale.com/types/mapx from tailscale.com/ipn/ipnext
|
tailscale.com/types/mapx from tailscale.com/ipn/ipnext
|
||||||
@ -161,7 +156,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
tailscale.com/util/cibuild from tailscale.com/health
|
tailscale.com/util/cibuild from tailscale.com/health
|
||||||
tailscale.com/util/clientmetric from tailscale.com/appc+
|
tailscale.com/util/clientmetric from tailscale.com/appc+
|
||||||
tailscale.com/util/cloudenv from tailscale.com/hostinfo+
|
tailscale.com/util/cloudenv from tailscale.com/hostinfo+
|
||||||
tailscale.com/util/cmpver from tailscale.com/clientupdate
|
|
||||||
tailscale.com/util/ctxkey from tailscale.com/client/tailscale/apitype+
|
tailscale.com/util/ctxkey from tailscale.com/client/tailscale/apitype+
|
||||||
💣 tailscale.com/util/deephash from tailscale.com/ipn/ipnlocal+
|
💣 tailscale.com/util/deephash from tailscale.com/ipn/ipnlocal+
|
||||||
💣 tailscale.com/util/dirwalk from tailscale.com/metrics
|
💣 tailscale.com/util/dirwalk from tailscale.com/metrics
|
||||||
@ -171,11 +165,11 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
tailscale.com/util/goroutines from tailscale.com/ipn/ipnlocal
|
tailscale.com/util/goroutines from tailscale.com/ipn/ipnlocal
|
||||||
tailscale.com/util/groupmember from tailscale.com/ipn/ipnauth
|
tailscale.com/util/groupmember from tailscale.com/ipn/ipnauth
|
||||||
💣 tailscale.com/util/hashx from tailscale.com/util/deephash
|
💣 tailscale.com/util/hashx from tailscale.com/util/deephash
|
||||||
tailscale.com/util/httpm from tailscale.com/clientupdate/distsign+
|
tailscale.com/util/httpm from tailscale.com/ipn/ipnlocal+
|
||||||
tailscale.com/util/lineiter from tailscale.com/hostinfo+
|
tailscale.com/util/lineiter from tailscale.com/hostinfo+
|
||||||
tailscale.com/util/mak from tailscale.com/appc+
|
tailscale.com/util/mak from tailscale.com/appc+
|
||||||
tailscale.com/util/multierr from tailscale.com/cmd/tailscaled+
|
tailscale.com/util/multierr from tailscale.com/cmd/tailscaled+
|
||||||
tailscale.com/util/must from tailscale.com/clientupdate/distsign+
|
tailscale.com/util/must from tailscale.com/logpolicy+
|
||||||
tailscale.com/util/nocasemaps from tailscale.com/types/ipproto
|
tailscale.com/util/nocasemaps from tailscale.com/types/ipproto
|
||||||
tailscale.com/util/osdiag from tailscale.com/ipn/localapi
|
tailscale.com/util/osdiag from tailscale.com/ipn/localapi
|
||||||
tailscale.com/util/osshare from tailscale.com/cmd/tailscaled
|
tailscale.com/util/osshare from tailscale.com/cmd/tailscaled
|
||||||
@ -195,8 +189,8 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
tailscale.com/util/vizerror from tailscale.com/tailcfg+
|
tailscale.com/util/vizerror from tailscale.com/tailcfg+
|
||||||
tailscale.com/util/winutil from tailscale.com/ipn/ipnauth
|
tailscale.com/util/winutil from tailscale.com/ipn/ipnauth
|
||||||
tailscale.com/util/zstdframe from tailscale.com/control/controlclient
|
tailscale.com/util/zstdframe from tailscale.com/control/controlclient
|
||||||
tailscale.com/version from tailscale.com/clientupdate+
|
tailscale.com/version from tailscale.com/cmd/tailscaled+
|
||||||
tailscale.com/version/distro from tailscale.com/clientupdate+
|
tailscale.com/version/distro from tailscale.com/cmd/tailscaled+
|
||||||
tailscale.com/wgengine from tailscale.com/cmd/tailscaled+
|
tailscale.com/wgengine from tailscale.com/cmd/tailscaled+
|
||||||
tailscale.com/wgengine/filter from tailscale.com/control/controlclient+
|
tailscale.com/wgengine/filter from tailscale.com/control/controlclient+
|
||||||
tailscale.com/wgengine/filter/filtertype from tailscale.com/types/netmap+
|
tailscale.com/wgengine/filter/filtertype from tailscale.com/types/netmap+
|
||||||
@ -249,9 +243,8 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
golang.org/x/text/unicode/bidi from golang.org/x/net/idna+
|
golang.org/x/text/unicode/bidi from golang.org/x/net/idna+
|
||||||
golang.org/x/text/unicode/norm from golang.org/x/net/idna
|
golang.org/x/text/unicode/norm from golang.org/x/net/idna
|
||||||
golang.org/x/time/rate from tailscale.com/derp
|
golang.org/x/time/rate from tailscale.com/derp
|
||||||
archive/tar from tailscale.com/clientupdate
|
|
||||||
bufio from compress/flate+
|
bufio from compress/flate+
|
||||||
bytes from archive/tar+
|
bytes from bufio+
|
||||||
cmp from encoding/json+
|
cmp from encoding/json+
|
||||||
compress/flate from compress/gzip
|
compress/flate from compress/gzip
|
||||||
compress/gzip from golang.org/x/net/http2+
|
compress/gzip from golang.org/x/net/http2+
|
||||||
@ -329,10 +322,10 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
encoding/hex from crypto/x509+
|
encoding/hex from crypto/x509+
|
||||||
encoding/json from expvar+
|
encoding/json from expvar+
|
||||||
encoding/pem from crypto/tls+
|
encoding/pem from crypto/tls+
|
||||||
errors from archive/tar+
|
errors from bufio+
|
||||||
expvar from tailscale.com/health+
|
expvar from tailscale.com/health+
|
||||||
flag from tailscale.com/cmd/tailscaled+
|
flag from tailscale.com/cmd/tailscaled+
|
||||||
fmt from archive/tar+
|
fmt from compress/flate+
|
||||||
hash from crypto+
|
hash from crypto+
|
||||||
hash/crc32 from compress/gzip+
|
hash/crc32 from compress/gzip+
|
||||||
hash/maphash from go4.org/mem
|
hash/maphash from go4.org/mem
|
||||||
@ -348,7 +341,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
internal/filepathlite from os+
|
internal/filepathlite from os+
|
||||||
internal/fmtsort from fmt
|
internal/fmtsort from fmt
|
||||||
internal/goarch from crypto/internal/fips140deps/cpu+
|
internal/goarch from crypto/internal/fips140deps/cpu+
|
||||||
internal/godebug from archive/tar+
|
internal/godebug from crypto/internal/fips140deps/godebug+
|
||||||
internal/godebugs from internal/godebug+
|
internal/godebugs from internal/godebug+
|
||||||
internal/goexperiment from hash/maphash+
|
internal/goexperiment from hash/maphash+
|
||||||
internal/goos from crypto/x509+
|
internal/goos from crypto/x509+
|
||||||
@ -379,14 +372,14 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
internal/testlog from os
|
internal/testlog from os
|
||||||
internal/trace/tracev2 from runtime+
|
internal/trace/tracev2 from runtime+
|
||||||
internal/unsafeheader from internal/reflectlite+
|
internal/unsafeheader from internal/reflectlite+
|
||||||
io from archive/tar+
|
io from bufio+
|
||||||
io/fs from archive/tar+
|
io/fs from crypto/x509+
|
||||||
io/ioutil from github.com/digitalocean/go-smbios/smbios
|
io/ioutil from github.com/digitalocean/go-smbios/smbios
|
||||||
iter from bytes+
|
iter from bytes+
|
||||||
log from expvar+
|
log from expvar+
|
||||||
log/internal from log
|
log/internal from log
|
||||||
maps from archive/tar+
|
maps from crypto/x509+
|
||||||
math from archive/tar+
|
math from compress/flate+
|
||||||
math/big from crypto/dsa+
|
math/big from crypto/dsa+
|
||||||
math/bits from bytes+
|
math/bits from bytes+
|
||||||
math/rand from github.com/mdlayher/netlink+
|
math/rand from github.com/mdlayher/netlink+
|
||||||
@ -405,27 +398,27 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
net/textproto from golang.org/x/net/http/httpguts+
|
net/textproto from golang.org/x/net/http/httpguts+
|
||||||
net/url from crypto/x509+
|
net/url from crypto/x509+
|
||||||
os from crypto/internal/sysrand+
|
os from crypto/internal/sysrand+
|
||||||
os/exec from tailscale.com/clientupdate+
|
os/exec from tailscale.com/hostinfo+
|
||||||
os/signal from tailscale.com/cmd/tailscaled
|
os/signal from tailscale.com/cmd/tailscaled
|
||||||
os/user from archive/tar+
|
os/user from tailscale.com/ipn/ipnauth+
|
||||||
path from archive/tar+
|
path from io/fs+
|
||||||
path/filepath from archive/tar+
|
path/filepath from crypto/x509+
|
||||||
reflect from archive/tar+
|
reflect from crypto/x509+
|
||||||
regexp from internal/profile+
|
regexp from internal/profile+
|
||||||
regexp/syntax from regexp
|
regexp/syntax from regexp
|
||||||
runtime from archive/tar+
|
runtime from crypto/internal/fips140+
|
||||||
runtime/debug from github.com/klauspost/compress/zstd+
|
runtime/debug from github.com/klauspost/compress/zstd+
|
||||||
runtime/pprof from net/http/pprof+
|
runtime/pprof from net/http/pprof+
|
||||||
runtime/trace from net/http/pprof
|
runtime/trace from net/http/pprof
|
||||||
slices from archive/tar+
|
slices from crypto/tls+
|
||||||
sort from compress/flate+
|
sort from compress/flate+
|
||||||
strconv from archive/tar+
|
strconv from compress/flate+
|
||||||
strings from archive/tar+
|
strings from bufio+
|
||||||
sync from archive/tar+
|
sync from compress/flate+
|
||||||
sync/atomic from context+
|
sync/atomic from context+
|
||||||
syscall from archive/tar+
|
syscall from crypto/internal/sysrand+
|
||||||
text/tabwriter from runtime/pprof
|
text/tabwriter from runtime/pprof
|
||||||
time from archive/tar+
|
time from compress/gzip+
|
||||||
unicode from bytes+
|
unicode from bytes+
|
||||||
unicode/utf16 from crypto/x509+
|
unicode/utf16 from crypto/x509+
|
||||||
unicode/utf8 from bufio+
|
unicode/utf8 from bufio+
|
||||||
|
@ -246,7 +246,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
tailscale.com/client/local from tailscale.com/client/web+
|
tailscale.com/client/local from tailscale.com/client/web+
|
||||||
tailscale.com/client/tailscale/apitype from tailscale.com/client/local+
|
tailscale.com/client/tailscale/apitype from tailscale.com/client/local+
|
||||||
tailscale.com/client/web from tailscale.com/ipn/ipnlocal
|
tailscale.com/client/web from tailscale.com/ipn/ipnlocal
|
||||||
tailscale.com/clientupdate from tailscale.com/client/web+
|
tailscale.com/clientupdate from tailscale.com/feature/clientupdate
|
||||||
LW tailscale.com/clientupdate/distsign from tailscale.com/clientupdate
|
LW tailscale.com/clientupdate/distsign from tailscale.com/clientupdate
|
||||||
tailscale.com/cmd/tailscaled/childproc from tailscale.com/cmd/tailscaled+
|
tailscale.com/cmd/tailscaled/childproc from tailscale.com/cmd/tailscaled+
|
||||||
tailscale.com/cmd/tailscaled/tailscaledhooks from tailscale.com/cmd/tailscaled+
|
tailscale.com/cmd/tailscaled/tailscaledhooks from tailscale.com/cmd/tailscaled+
|
||||||
@ -273,6 +273,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
tailscale.com/feature from tailscale.com/feature/wakeonlan+
|
tailscale.com/feature from tailscale.com/feature/wakeonlan+
|
||||||
tailscale.com/feature/buildfeatures from tailscale.com/wgengine/magicsock+
|
tailscale.com/feature/buildfeatures from tailscale.com/wgengine/magicsock+
|
||||||
tailscale.com/feature/capture from tailscale.com/feature/condregister
|
tailscale.com/feature/capture from tailscale.com/feature/condregister
|
||||||
|
tailscale.com/feature/clientupdate from tailscale.com/feature/condregister
|
||||||
tailscale.com/feature/condregister from tailscale.com/cmd/tailscaled
|
tailscale.com/feature/condregister from tailscale.com/cmd/tailscaled
|
||||||
tailscale.com/feature/condregister/portmapper from tailscale.com/feature/condregister
|
tailscale.com/feature/condregister/portmapper from tailscale.com/feature/condregister
|
||||||
tailscale.com/feature/debugportmapper from tailscale.com/feature/condregister
|
tailscale.com/feature/debugportmapper from tailscale.com/feature/condregister
|
||||||
|
@ -9,7 +9,7 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar
|
|||||||
github.com/coder/websocket/internal/errd from github.com/coder/websocket
|
github.com/coder/websocket/internal/errd from github.com/coder/websocket
|
||||||
github.com/coder/websocket/internal/util from github.com/coder/websocket
|
github.com/coder/websocket/internal/util from github.com/coder/websocket
|
||||||
github.com/coder/websocket/internal/xsync from github.com/coder/websocket
|
github.com/coder/websocket/internal/xsync from github.com/coder/websocket
|
||||||
W 💣 github.com/dblohm7/wingoes from github.com/dblohm7/wingoes/com+
|
W 💣 github.com/dblohm7/wingoes from tailscale.com/net/tshttpproxy+
|
||||||
W 💣 github.com/dblohm7/wingoes/com from tailscale.com/util/osdiag+
|
W 💣 github.com/dblohm7/wingoes/com from tailscale.com/util/osdiag+
|
||||||
W 💣 github.com/dblohm7/wingoes/com/automation from tailscale.com/util/osdiag/internal/wsc
|
W 💣 github.com/dblohm7/wingoes/com/automation from tailscale.com/util/osdiag/internal/wsc
|
||||||
W github.com/dblohm7/wingoes/internal from github.com/dblohm7/wingoes/com
|
W github.com/dblohm7/wingoes/internal from github.com/dblohm7/wingoes/com
|
||||||
@ -28,8 +28,8 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar
|
|||||||
L 💣 github.com/godbus/dbus/v5 from tailscale.com/net/dns
|
L 💣 github.com/godbus/dbus/v5 from tailscale.com/net/dns
|
||||||
github.com/golang/groupcache/lru from tailscale.com/net/dnscache
|
github.com/golang/groupcache/lru from tailscale.com/net/dnscache
|
||||||
github.com/google/btree from gvisor.dev/gvisor/pkg/tcpip/header+
|
github.com/google/btree from gvisor.dev/gvisor/pkg/tcpip/header+
|
||||||
DW github.com/google/uuid from github.com/prometheus-community/pro-bing+
|
D github.com/google/uuid from github.com/prometheus-community/pro-bing
|
||||||
github.com/hdevalence/ed25519consensus from tailscale.com/clientupdate/distsign+
|
github.com/hdevalence/ed25519consensus from tailscale.com/tka
|
||||||
L 💣 github.com/jsimonetti/rtnetlink from tailscale.com/net/netmon
|
L 💣 github.com/jsimonetti/rtnetlink from tailscale.com/net/netmon
|
||||||
L github.com/jsimonetti/rtnetlink/internal/unix from github.com/jsimonetti/rtnetlink
|
L github.com/jsimonetti/rtnetlink/internal/unix from github.com/jsimonetti/rtnetlink
|
||||||
github.com/klauspost/compress from github.com/klauspost/compress/zstd
|
github.com/klauspost/compress from github.com/klauspost/compress/zstd
|
||||||
@ -128,8 +128,6 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar
|
|||||||
tailscale.com/client/tailscale from tailscale.com/internal/client/tailscale
|
tailscale.com/client/tailscale from tailscale.com/internal/client/tailscale
|
||||||
tailscale.com/client/tailscale/apitype from tailscale.com/client/local+
|
tailscale.com/client/tailscale/apitype from tailscale.com/client/local+
|
||||||
tailscale.com/client/web from tailscale.com/ipn/ipnlocal
|
tailscale.com/client/web from tailscale.com/ipn/ipnlocal
|
||||||
tailscale.com/clientupdate from tailscale.com/client/web+
|
|
||||||
LW tailscale.com/clientupdate/distsign from tailscale.com/clientupdate
|
|
||||||
tailscale.com/control/controlbase from tailscale.com/control/controlhttp+
|
tailscale.com/control/controlbase from tailscale.com/control/controlhttp+
|
||||||
tailscale.com/control/controlclient from tailscale.com/ipn/ipnext+
|
tailscale.com/control/controlclient from tailscale.com/ipn/ipnext+
|
||||||
tailscale.com/control/controlhttp from tailscale.com/control/controlclient
|
tailscale.com/control/controlhttp from tailscale.com/control/controlclient
|
||||||
@ -208,7 +206,7 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar
|
|||||||
tailscale.com/net/tlsdial/blockblame from tailscale.com/net/tlsdial
|
tailscale.com/net/tlsdial/blockblame from tailscale.com/net/tlsdial
|
||||||
tailscale.com/net/tsaddr from tailscale.com/client/web+
|
tailscale.com/net/tsaddr from tailscale.com/client/web+
|
||||||
tailscale.com/net/tsdial from tailscale.com/control/controlclient+
|
tailscale.com/net/tsdial from tailscale.com/control/controlclient+
|
||||||
💣 tailscale.com/net/tshttpproxy from tailscale.com/clientupdate/distsign+
|
💣 tailscale.com/net/tshttpproxy from tailscale.com/control/controlclient+
|
||||||
tailscale.com/net/tstun from tailscale.com/tsd+
|
tailscale.com/net/tstun from tailscale.com/tsd+
|
||||||
tailscale.com/net/udprelay/endpoint from tailscale.com/wgengine/magicsock
|
tailscale.com/net/udprelay/endpoint from tailscale.com/wgengine/magicsock
|
||||||
tailscale.com/net/udprelay/status from tailscale.com/client/local
|
tailscale.com/net/udprelay/status from tailscale.com/client/local
|
||||||
@ -237,7 +235,7 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar
|
|||||||
tailscale.com/types/empty from tailscale.com/ipn+
|
tailscale.com/types/empty from tailscale.com/ipn+
|
||||||
tailscale.com/types/ipproto from tailscale.com/ipn+
|
tailscale.com/types/ipproto from tailscale.com/ipn+
|
||||||
tailscale.com/types/key from tailscale.com/client/local+
|
tailscale.com/types/key from tailscale.com/client/local+
|
||||||
tailscale.com/types/lazy from tailscale.com/clientupdate+
|
tailscale.com/types/lazy from tailscale.com/cmd/tsidp+
|
||||||
tailscale.com/types/logger from tailscale.com/appc+
|
tailscale.com/types/logger from tailscale.com/appc+
|
||||||
tailscale.com/types/logid from tailscale.com/ipn/ipnlocal+
|
tailscale.com/types/logid from tailscale.com/ipn/ipnlocal+
|
||||||
tailscale.com/types/mapx from tailscale.com/ipn/ipnext
|
tailscale.com/types/mapx from tailscale.com/ipn/ipnext
|
||||||
@ -256,12 +254,12 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar
|
|||||||
tailscale.com/util/cibuild from tailscale.com/health
|
tailscale.com/util/cibuild from tailscale.com/health
|
||||||
tailscale.com/util/clientmetric from tailscale.com/appc+
|
tailscale.com/util/clientmetric from tailscale.com/appc+
|
||||||
tailscale.com/util/cloudenv from tailscale.com/hostinfo+
|
tailscale.com/util/cloudenv from tailscale.com/hostinfo+
|
||||||
tailscale.com/util/cmpver from tailscale.com/clientupdate+
|
LW tailscale.com/util/cmpver from tailscale.com/net/dns+
|
||||||
tailscale.com/util/ctxkey from tailscale.com/client/tailscale/apitype+
|
tailscale.com/util/ctxkey from tailscale.com/client/tailscale/apitype+
|
||||||
💣 tailscale.com/util/deephash from tailscale.com/ipn/ipnlocal+
|
💣 tailscale.com/util/deephash from tailscale.com/ipn/ipnlocal+
|
||||||
L 💣 tailscale.com/util/dirwalk from tailscale.com/metrics
|
L 💣 tailscale.com/util/dirwalk from tailscale.com/metrics
|
||||||
tailscale.com/util/dnsname from tailscale.com/appc+
|
tailscale.com/util/dnsname from tailscale.com/appc+
|
||||||
tailscale.com/util/eventbus from tailscale.com/ipn/localapi+
|
tailscale.com/util/eventbus from tailscale.com/client/local+
|
||||||
tailscale.com/util/execqueue from tailscale.com/appc+
|
tailscale.com/util/execqueue from tailscale.com/appc+
|
||||||
tailscale.com/util/goroutines from tailscale.com/ipn/ipnlocal
|
tailscale.com/util/goroutines from tailscale.com/ipn/ipnlocal
|
||||||
tailscale.com/util/groupmember from tailscale.com/client/web+
|
tailscale.com/util/groupmember from tailscale.com/client/web+
|
||||||
@ -270,7 +268,7 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar
|
|||||||
tailscale.com/util/lineiter from tailscale.com/hostinfo+
|
tailscale.com/util/lineiter from tailscale.com/hostinfo+
|
||||||
tailscale.com/util/mak from tailscale.com/appc+
|
tailscale.com/util/mak from tailscale.com/appc+
|
||||||
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/clientupdate/distsign+
|
tailscale.com/util/must from tailscale.com/cmd/tsidp+
|
||||||
tailscale.com/util/nocasemaps from tailscale.com/types/ipproto
|
tailscale.com/util/nocasemaps from tailscale.com/types/ipproto
|
||||||
💣 tailscale.com/util/osdiag from tailscale.com/ipn/localapi
|
💣 tailscale.com/util/osdiag from tailscale.com/ipn/localapi
|
||||||
W 💣 tailscale.com/util/osdiag/internal/wsc from tailscale.com/util/osdiag
|
W 💣 tailscale.com/util/osdiag/internal/wsc from tailscale.com/util/osdiag
|
||||||
@ -296,8 +294,8 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar
|
|||||||
tailscale.com/util/truncate from tailscale.com/logtail
|
tailscale.com/util/truncate from tailscale.com/logtail
|
||||||
tailscale.com/util/usermetric from tailscale.com/health+
|
tailscale.com/util/usermetric from tailscale.com/health+
|
||||||
tailscale.com/util/vizerror from tailscale.com/tailcfg+
|
tailscale.com/util/vizerror from tailscale.com/tailcfg+
|
||||||
💣 tailscale.com/util/winutil from tailscale.com/clientupdate+
|
💣 tailscale.com/util/winutil from tailscale.com/hostinfo+
|
||||||
W 💣 tailscale.com/util/winutil/authenticode from tailscale.com/clientupdate+
|
W 💣 tailscale.com/util/winutil/authenticode from tailscale.com/util/osdiag
|
||||||
W 💣 tailscale.com/util/winutil/gp from tailscale.com/net/dns+
|
W 💣 tailscale.com/util/winutil/gp from tailscale.com/net/dns+
|
||||||
W tailscale.com/util/winutil/policy from tailscale.com/ipn/ipnlocal
|
W tailscale.com/util/winutil/policy from tailscale.com/ipn/ipnlocal
|
||||||
W 💣 tailscale.com/util/winutil/winenv from tailscale.com/hostinfo+
|
W 💣 tailscale.com/util/winutil/winenv from tailscale.com/hostinfo+
|
||||||
@ -336,7 +334,7 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar
|
|||||||
golang.org/x/crypto/salsa20/salsa from golang.org/x/crypto/nacl/box+
|
golang.org/x/crypto/salsa20/salsa from golang.org/x/crypto/nacl/box+
|
||||||
LD golang.org/x/crypto/ssh from tailscale.com/ipn/ipnlocal
|
LD golang.org/x/crypto/ssh from tailscale.com/ipn/ipnlocal
|
||||||
LD golang.org/x/crypto/ssh/internal/bcrypt_pbkdf from golang.org/x/crypto/ssh
|
LD golang.org/x/crypto/ssh/internal/bcrypt_pbkdf from golang.org/x/crypto/ssh
|
||||||
golang.org/x/exp/constraints from github.com/dblohm7/wingoes/pe+
|
golang.org/x/exp/constraints from tailscale.com/tsweb/varz+
|
||||||
golang.org/x/exp/maps from tailscale.com/ipn/store/mem+
|
golang.org/x/exp/maps from tailscale.com/ipn/store/mem+
|
||||||
golang.org/x/net/bpf from github.com/mdlayher/genetlink+
|
golang.org/x/net/bpf from github.com/mdlayher/genetlink+
|
||||||
golang.org/x/net/dns/dnsmessage from net+
|
golang.org/x/net/dns/dnsmessage from net+
|
||||||
@ -371,9 +369,8 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar
|
|||||||
golang.org/x/text/unicode/bidi from golang.org/x/net/idna+
|
golang.org/x/text/unicode/bidi from golang.org/x/net/idna+
|
||||||
golang.org/x/text/unicode/norm from golang.org/x/net/idna
|
golang.org/x/text/unicode/norm from golang.org/x/net/idna
|
||||||
golang.org/x/time/rate from gvisor.dev/gvisor/pkg/log+
|
golang.org/x/time/rate from gvisor.dev/gvisor/pkg/log+
|
||||||
archive/tar from tailscale.com/clientupdate
|
|
||||||
bufio from compress/flate+
|
bufio from compress/flate+
|
||||||
bytes from archive/tar+
|
bytes from bufio+
|
||||||
cmp from encoding/json+
|
cmp from encoding/json+
|
||||||
compress/flate from compress/gzip+
|
compress/flate from compress/gzip+
|
||||||
compress/gzip from golang.org/x/net/http2+
|
compress/gzip from golang.org/x/net/http2+
|
||||||
@ -446,7 +443,7 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar
|
|||||||
crypto/x509 from crypto/tls+
|
crypto/x509 from crypto/tls+
|
||||||
D crypto/x509/internal/macos from crypto/x509
|
D crypto/x509/internal/macos from crypto/x509
|
||||||
crypto/x509/pkix from crypto/x509+
|
crypto/x509/pkix from crypto/x509+
|
||||||
DW database/sql/driver from github.com/google/uuid
|
D database/sql/driver from github.com/google/uuid
|
||||||
W debug/dwarf from debug/pe
|
W debug/dwarf from debug/pe
|
||||||
W debug/pe from github.com/dblohm7/wingoes/pe
|
W debug/pe from github.com/dblohm7/wingoes/pe
|
||||||
embed from github.com/tailscale/web-client-prebuilt+
|
embed from github.com/tailscale/web-client-prebuilt+
|
||||||
@ -459,11 +456,11 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar
|
|||||||
encoding/json from expvar+
|
encoding/json from expvar+
|
||||||
encoding/pem from crypto/tls+
|
encoding/pem from crypto/tls+
|
||||||
encoding/xml from github.com/tailscale/goupnp+
|
encoding/xml from github.com/tailscale/goupnp+
|
||||||
errors from archive/tar+
|
errors from bufio+
|
||||||
expvar from tailscale.com/health+
|
expvar from tailscale.com/health+
|
||||||
flag from tailscale.com/cmd/tsidp+
|
flag from tailscale.com/cmd/tsidp+
|
||||||
fmt from archive/tar+
|
fmt from compress/flate+
|
||||||
hash from compress/zlib+
|
hash from crypto+
|
||||||
W hash/adler32 from compress/zlib
|
W hash/adler32 from compress/zlib
|
||||||
hash/crc32 from compress/gzip+
|
hash/crc32 from compress/gzip+
|
||||||
hash/maphash from go4.org/mem
|
hash/maphash from go4.org/mem
|
||||||
@ -480,7 +477,7 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar
|
|||||||
internal/filepathlite from os+
|
internal/filepathlite from os+
|
||||||
internal/fmtsort from fmt+
|
internal/fmtsort from fmt+
|
||||||
internal/goarch from crypto/internal/fips140deps/cpu+
|
internal/goarch from crypto/internal/fips140deps/cpu+
|
||||||
internal/godebug from archive/tar+
|
internal/godebug from crypto/internal/fips140deps/godebug+
|
||||||
internal/godebugs from internal/godebug+
|
internal/godebugs from internal/godebug+
|
||||||
internal/goexperiment from hash/maphash+
|
internal/goexperiment from hash/maphash+
|
||||||
internal/goos from crypto/x509+
|
internal/goos from crypto/x509+
|
||||||
@ -516,14 +513,14 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar
|
|||||||
internal/testlog from os
|
internal/testlog from os
|
||||||
internal/trace/tracev2 from runtime+
|
internal/trace/tracev2 from runtime+
|
||||||
internal/unsafeheader from internal/reflectlite+
|
internal/unsafeheader from internal/reflectlite+
|
||||||
io from archive/tar+
|
io from bufio+
|
||||||
io/fs from archive/tar+
|
io/fs from crypto/x509+
|
||||||
io/ioutil from github.com/digitalocean/go-smbios/smbios+
|
io/ioutil from github.com/digitalocean/go-smbios/smbios+
|
||||||
iter from bytes+
|
iter from bytes+
|
||||||
log from expvar+
|
log from expvar+
|
||||||
log/internal from log
|
log/internal from log
|
||||||
maps from archive/tar+
|
maps from crypto/x509+
|
||||||
math from archive/tar+
|
math from compress/flate+
|
||||||
math/big from crypto/dsa+
|
math/big from crypto/dsa+
|
||||||
math/bits from bytes+
|
math/bits from bytes+
|
||||||
math/rand from github.com/fxamacker/cbor/v2+
|
math/rand from github.com/fxamacker/cbor/v2+
|
||||||
@ -545,28 +542,28 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar
|
|||||||
os from crypto/internal/sysrand+
|
os from crypto/internal/sysrand+
|
||||||
os/exec from github.com/godbus/dbus/v5+
|
os/exec from github.com/godbus/dbus/v5+
|
||||||
os/signal from tailscale.com/cmd/tsidp
|
os/signal from tailscale.com/cmd/tsidp
|
||||||
os/user from archive/tar+
|
os/user from github.com/godbus/dbus/v5+
|
||||||
path from archive/tar+
|
path from debug/dwarf+
|
||||||
path/filepath from archive/tar+
|
path/filepath from crypto/x509+
|
||||||
reflect from archive/tar+
|
reflect from crypto/x509+
|
||||||
regexp from github.com/tailscale/goupnp/httpu+
|
regexp from github.com/tailscale/goupnp/httpu+
|
||||||
regexp/syntax from regexp
|
regexp/syntax from regexp
|
||||||
runtime from archive/tar+
|
runtime from crypto/internal/fips140+
|
||||||
runtime/debug from github.com/coder/websocket/internal/xsync+
|
runtime/debug from github.com/coder/websocket/internal/xsync+
|
||||||
runtime/pprof from net/http/pprof+
|
runtime/pprof from net/http/pprof+
|
||||||
runtime/trace from net/http/pprof
|
runtime/trace from net/http/pprof
|
||||||
slices from archive/tar+
|
slices from crypto/tls+
|
||||||
sort from compress/flate+
|
sort from compress/flate+
|
||||||
strconv from archive/tar+
|
strconv from compress/flate+
|
||||||
strings from archive/tar+
|
strings from bufio+
|
||||||
W structs from internal/syscall/windows
|
W structs from internal/syscall/windows
|
||||||
sync from archive/tar+
|
sync from compress/flate+
|
||||||
sync/atomic from context+
|
sync/atomic from context+
|
||||||
syscall from archive/tar+
|
syscall from crypto/internal/sysrand+
|
||||||
text/tabwriter from runtime/pprof
|
text/tabwriter from runtime/pprof
|
||||||
text/template from html/template
|
text/template from html/template
|
||||||
text/template/parse from html/template+
|
text/template/parse from html/template+
|
||||||
time from archive/tar+
|
time from compress/gzip+
|
||||||
unicode from bytes+
|
unicode from bytes+
|
||||||
unicode/utf16 from crypto/x509+
|
unicode/utf16 from crypto/x509+
|
||||||
unicode/utf8 from bufio+
|
unicode/utf8 from bufio+
|
||||||
|
13
feature/buildfeatures/feature_clientupdate_disabled.go
Normal file
13
feature/buildfeatures/feature_clientupdate_disabled.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// Copyright (c) Tailscale Inc & AUTHORS
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
// Code generated by gen.go; DO NOT EDIT.
|
||||||
|
|
||||||
|
//go:build ts_omit_clientupdate
|
||||||
|
|
||||||
|
package buildfeatures
|
||||||
|
|
||||||
|
// HasClientUpdate is whether the binary was built with support for modular feature "Client auto-update support".
|
||||||
|
// Specifically, it's whether the binary was NOT built with the "ts_omit_clientupdate" build tag.
|
||||||
|
// It's a const so it can be used for dead code elimination.
|
||||||
|
const HasClientUpdate = false
|
13
feature/buildfeatures/feature_clientupdate_enabled.go
Normal file
13
feature/buildfeatures/feature_clientupdate_enabled.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// Copyright (c) Tailscale Inc & AUTHORS
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
// Code generated by gen.go; DO NOT EDIT.
|
||||||
|
|
||||||
|
//go:build !ts_omit_clientupdate
|
||||||
|
|
||||||
|
package buildfeatures
|
||||||
|
|
||||||
|
// HasClientUpdate is whether the binary was built with support for modular feature "Client auto-update support".
|
||||||
|
// Specifically, it's whether the binary was NOT built with the "ts_omit_clientupdate" build tag.
|
||||||
|
// It's a const so it can be used for dead code elimination.
|
||||||
|
const HasClientUpdate = true
|
530
feature/clientupdate/clientupdate.go
Normal file
530
feature/clientupdate/clientupdate.go
Normal file
@ -0,0 +1,530 @@
|
|||||||
|
// Copyright (c) Tailscale Inc & AUTHORS
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
// Package clientupdate enables the client update feature.
|
||||||
|
package clientupdate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"tailscale.com/clientupdate"
|
||||||
|
"tailscale.com/envknob"
|
||||||
|
"tailscale.com/feature"
|
||||||
|
"tailscale.com/ipn"
|
||||||
|
"tailscale.com/ipn/ipnext"
|
||||||
|
"tailscale.com/ipn/ipnlocal"
|
||||||
|
"tailscale.com/ipn/ipnstate"
|
||||||
|
"tailscale.com/ipn/localapi"
|
||||||
|
"tailscale.com/tailcfg"
|
||||||
|
"tailscale.com/types/logger"
|
||||||
|
"tailscale.com/util/httpm"
|
||||||
|
"tailscale.com/version"
|
||||||
|
"tailscale.com/version/distro"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
ipnext.RegisterExtension("clientupdate", newExt)
|
||||||
|
|
||||||
|
// C2N
|
||||||
|
ipnlocal.RegisterC2N("GET /update", handleC2NUpdateGet)
|
||||||
|
ipnlocal.RegisterC2N("POST /update", handleC2NUpdatePost)
|
||||||
|
|
||||||
|
// LocalAPI:
|
||||||
|
localapi.Register("update/install", serveUpdateInstall)
|
||||||
|
localapi.Register("update/progress", serveUpdateProgress)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newExt(logf logger.Logf, sb ipnext.SafeBackend) (ipnext.Extension, error) {
|
||||||
|
return &extension{
|
||||||
|
logf: logf,
|
||||||
|
sb: sb,
|
||||||
|
|
||||||
|
lastSelfUpdateState: ipnstate.UpdateFinished,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type extension struct {
|
||||||
|
logf logger.Logf
|
||||||
|
sb ipnext.SafeBackend
|
||||||
|
|
||||||
|
mu sync.Mutex
|
||||||
|
|
||||||
|
// c2nUpdateStatus is the status of c2n-triggered client update.
|
||||||
|
c2nUpdateStatus updateStatus
|
||||||
|
prefs ipn.PrefsView
|
||||||
|
state ipn.State
|
||||||
|
|
||||||
|
lastSelfUpdateState ipnstate.SelfUpdateStatus
|
||||||
|
selfUpdateProgress []ipnstate.UpdateProgress
|
||||||
|
|
||||||
|
// offlineAutoUpdateCancel stops offline auto-updates when called. It
|
||||||
|
// should be used via stopOfflineAutoUpdate and
|
||||||
|
// maybeStartOfflineAutoUpdate. It is nil when offline auto-updates are
|
||||||
|
// not running.
|
||||||
|
//
|
||||||
|
//lint:ignore U1000 only used in Linux and Windows builds in autoupdate.go
|
||||||
|
offlineAutoUpdateCancel func()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *extension) Name() string { return "clientupdate" }
|
||||||
|
|
||||||
|
func (e *extension) Init(h ipnext.Host) error {
|
||||||
|
|
||||||
|
h.Hooks().ProfileStateChange.Add(e.onChangeProfile)
|
||||||
|
h.Hooks().BackendStateChange.Add(e.onBackendStateChange)
|
||||||
|
|
||||||
|
// TODO(nickkhyl): remove this after the profileManager refactoring.
|
||||||
|
// See tailscale/tailscale#15974.
|
||||||
|
// This same workaround appears in feature/portlist/portlist.go.
|
||||||
|
profile, prefs := h.Profiles().CurrentProfileState()
|
||||||
|
e.onChangeProfile(profile, prefs, false)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *extension) Shutdown() error {
|
||||||
|
e.stopOfflineAutoUpdate()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *extension) onBackendStateChange(newState ipn.State) {
|
||||||
|
e.mu.Lock()
|
||||||
|
defer e.mu.Unlock()
|
||||||
|
e.state = newState
|
||||||
|
e.updateOfflineAutoUpdateLocked()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *extension) onChangeProfile(profile ipn.LoginProfileView, prefs ipn.PrefsView, sameNode bool) {
|
||||||
|
e.mu.Lock()
|
||||||
|
defer e.mu.Unlock()
|
||||||
|
e.prefs = prefs
|
||||||
|
e.updateOfflineAutoUpdateLocked()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *extension) updateOfflineAutoUpdateLocked() {
|
||||||
|
want := e.prefs.Valid() && e.prefs.AutoUpdate().Apply.EqualBool(true) &&
|
||||||
|
e.state != ipn.Running && e.state != ipn.Starting
|
||||||
|
|
||||||
|
cur := e.offlineAutoUpdateCancel != nil
|
||||||
|
|
||||||
|
if want && !cur {
|
||||||
|
e.maybeStartOfflineAutoUpdateLocked(e.prefs)
|
||||||
|
} else if !want && cur {
|
||||||
|
e.stopOfflineAutoUpdateLocked()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type updateStatus struct {
|
||||||
|
started bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *extension) clearSelfUpdateProgress() {
|
||||||
|
e.mu.Lock()
|
||||||
|
defer e.mu.Unlock()
|
||||||
|
e.selfUpdateProgress = make([]ipnstate.UpdateProgress, 0)
|
||||||
|
e.lastSelfUpdateState = ipnstate.UpdateFinished
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *extension) GetSelfUpdateProgress() []ipnstate.UpdateProgress {
|
||||||
|
e.mu.Lock()
|
||||||
|
defer e.mu.Unlock()
|
||||||
|
res := make([]ipnstate.UpdateProgress, len(e.selfUpdateProgress))
|
||||||
|
copy(res, e.selfUpdateProgress)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *extension) DoSelfUpdate() {
|
||||||
|
e.mu.Lock()
|
||||||
|
updateState := e.lastSelfUpdateState
|
||||||
|
e.mu.Unlock()
|
||||||
|
// don't start an update if one is already in progress
|
||||||
|
if updateState == ipnstate.UpdateInProgress {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.clearSelfUpdateProgress()
|
||||||
|
e.pushSelfUpdateProgress(ipnstate.NewUpdateProgress(ipnstate.UpdateInProgress, ""))
|
||||||
|
up, err := clientupdate.NewUpdater(clientupdate.Arguments{
|
||||||
|
Logf: func(format string, args ...any) {
|
||||||
|
e.pushSelfUpdateProgress(ipnstate.NewUpdateProgress(ipnstate.UpdateInProgress, fmt.Sprintf(format, args...)))
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
e.pushSelfUpdateProgress(ipnstate.NewUpdateProgress(ipnstate.UpdateFailed, err.Error()))
|
||||||
|
}
|
||||||
|
err = up.Update()
|
||||||
|
if err != nil {
|
||||||
|
e.pushSelfUpdateProgress(ipnstate.NewUpdateProgress(ipnstate.UpdateFailed, err.Error()))
|
||||||
|
} else {
|
||||||
|
e.pushSelfUpdateProgress(ipnstate.NewUpdateProgress(ipnstate.UpdateFinished, "tailscaled did not restart; please restart Tailscale manually."))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// serveUpdateInstall sends a request to the LocalBackend to start a Tailscale
|
||||||
|
// self-update. A successful response does not indicate whether the update
|
||||||
|
// succeeded, only that the request was accepted. Clients should use
|
||||||
|
// serveUpdateProgress after pinging this endpoint to check how the update is
|
||||||
|
// going.
|
||||||
|
func serveUpdateInstall(h *localapi.Handler, w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != httpm.POST {
|
||||||
|
http.Error(w, "only POST allowed", http.StatusMethodNotAllowed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
b := h.LocalBackend()
|
||||||
|
ext, ok := ipnlocal.GetExt[*extension](b)
|
||||||
|
if !ok {
|
||||||
|
http.Error(w, "clientupdate extension not found", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusAccepted)
|
||||||
|
|
||||||
|
go ext.DoSelfUpdate()
|
||||||
|
}
|
||||||
|
|
||||||
|
// serveUpdateProgress returns the status of an in-progress Tailscale self-update.
|
||||||
|
// This is provided as a slice of ipnstate.UpdateProgress structs with various
|
||||||
|
// log messages in order from oldest to newest. If an update is not in progress,
|
||||||
|
// the returned slice will be empty.
|
||||||
|
func serveUpdateProgress(h *localapi.Handler, w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != httpm.GET {
|
||||||
|
http.Error(w, "only GET allowed", http.StatusMethodNotAllowed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
b := h.LocalBackend()
|
||||||
|
ext, ok := ipnlocal.GetExt[*extension](b)
|
||||||
|
if !ok {
|
||||||
|
http.Error(w, "clientupdate extension not found", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ups := ext.GetSelfUpdateProgress()
|
||||||
|
|
||||||
|
json.NewEncoder(w).Encode(ups)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *extension) pushSelfUpdateProgress(up ipnstate.UpdateProgress) {
|
||||||
|
e.mu.Lock()
|
||||||
|
defer e.mu.Unlock()
|
||||||
|
e.selfUpdateProgress = append(e.selfUpdateProgress, up)
|
||||||
|
e.lastSelfUpdateState = up.Status
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleC2NUpdateGet(b *ipnlocal.LocalBackend, w http.ResponseWriter, r *http.Request) {
|
||||||
|
e, ok := ipnlocal.GetExt[*extension](b)
|
||||||
|
if !ok {
|
||||||
|
http.Error(w, "clientupdate extension not found", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
e.logf("c2n: GET /update received")
|
||||||
|
|
||||||
|
res := e.newC2NUpdateResponse()
|
||||||
|
res.Started = e.c2nUpdateStarted()
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
json.NewEncoder(w).Encode(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleC2NUpdatePost(b *ipnlocal.LocalBackend, w http.ResponseWriter, r *http.Request) {
|
||||||
|
e, ok := ipnlocal.GetExt[*extension](b)
|
||||||
|
if !ok {
|
||||||
|
http.Error(w, "clientupdate extension not found", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.logf("c2n: POST /update received")
|
||||||
|
res := e.newC2NUpdateResponse()
|
||||||
|
defer func() {
|
||||||
|
if res.Err != "" {
|
||||||
|
e.logf("c2n: POST /update failed: %s", res.Err)
|
||||||
|
}
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
json.NewEncoder(w).Encode(res)
|
||||||
|
}()
|
||||||
|
|
||||||
|
if !res.Enabled {
|
||||||
|
res.Err = "not enabled"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !res.Supported {
|
||||||
|
res.Err = "not supported"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not update if we have active inbound SSH connections. Control can set
|
||||||
|
// force=true query parameter to override this.
|
||||||
|
if r.FormValue("force") != "true" && b.ActiveSSHConns() > 0 {
|
||||||
|
res.Err = "not updating due to active SSH connections"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := e.startAutoUpdate("c2n"); err != nil {
|
||||||
|
res.Err = err.Error()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
res.Started = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *extension) newC2NUpdateResponse() tailcfg.C2NUpdateResponse {
|
||||||
|
e.mu.Lock()
|
||||||
|
defer e.mu.Unlock()
|
||||||
|
|
||||||
|
// If NewUpdater does not return an error, we can update the installation.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
var upPref ipn.AutoUpdatePrefs
|
||||||
|
if e.prefs.Valid() {
|
||||||
|
upPref = e.prefs.AutoUpdate()
|
||||||
|
}
|
||||||
|
return tailcfg.C2NUpdateResponse{
|
||||||
|
Enabled: envknob.AllowsRemoteUpdate() || upPref.Apply.EqualBool(true),
|
||||||
|
Supported: feature.CanAutoUpdate() && !version.IsMacSysExt(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *extension) c2nUpdateStarted() bool {
|
||||||
|
e.mu.Lock()
|
||||||
|
defer e.mu.Unlock()
|
||||||
|
return e.c2nUpdateStatus.started
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *extension) setC2NUpdateStarted(v bool) {
|
||||||
|
e.mu.Lock()
|
||||||
|
defer e.mu.Unlock()
|
||||||
|
e.c2nUpdateStatus.started = v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *extension) trySetC2NUpdateStarted() bool {
|
||||||
|
e.mu.Lock()
|
||||||
|
defer e.mu.Unlock()
|
||||||
|
if e.c2nUpdateStatus.started {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
e.c2nUpdateStatus.started = true
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// findCmdTailscale looks for the cmd/tailscale that corresponds to the
|
||||||
|
// currently running cmd/tailscaled. It's up to the caller to verify that the
|
||||||
|
// two match, but this function does its best to find the right one. Notably, it
|
||||||
|
// doesn't use $PATH for security reasons.
|
||||||
|
func findCmdTailscale() (string, error) {
|
||||||
|
self, err := os.Executable()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
var ts string
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "linux":
|
||||||
|
if self == "/usr/sbin/tailscaled" || self == "/usr/bin/tailscaled" {
|
||||||
|
ts = "/usr/bin/tailscale"
|
||||||
|
}
|
||||||
|
if self == "/usr/local/sbin/tailscaled" || self == "/usr/local/bin/tailscaled" {
|
||||||
|
ts = "/usr/local/bin/tailscale"
|
||||||
|
}
|
||||||
|
switch distro.Get() {
|
||||||
|
case 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 distro.Unraid:
|
||||||
|
if self == "/usr/local/emhttp/plugins/tailscale/bin/tailscaled" {
|
||||||
|
ts = "/usr/local/emhttp/plugins/tailscale/bin/tailscale"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "windows":
|
||||||
|
ts = filepath.Join(filepath.Dir(self), "tailscale.exe")
|
||||||
|
case "freebsd", "openbsd":
|
||||||
|
if self == "/usr/local/bin/tailscaled" {
|
||||||
|
ts = "/usr/local/bin/tailscale"
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return "", fmt.Errorf("unsupported OS %v", runtime.GOOS)
|
||||||
|
}
|
||||||
|
if ts != "" && regularFileExists(ts) {
|
||||||
|
return ts, nil
|
||||||
|
}
|
||||||
|
return "", errors.New("tailscale executable not found in expected place")
|
||||||
|
}
|
||||||
|
|
||||||
|
func tailscaleUpdateCmd(cmdTS string) *exec.Cmd {
|
||||||
|
defaultCmd := exec.Command(cmdTS, "update", "--yes")
|
||||||
|
if runtime.GOOS != "linux" {
|
||||||
|
return defaultCmd
|
||||||
|
}
|
||||||
|
if _, err := exec.LookPath("systemd-run"); err != nil {
|
||||||
|
return defaultCmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// When systemd-run is available, use it to run the update command. This
|
||||||
|
// creates a new temporary unit separate from the tailscaled unit. When
|
||||||
|
// tailscaled is restarted during the update, systemd won't kill this
|
||||||
|
// temporary update unit, which could cause unexpected breakage.
|
||||||
|
//
|
||||||
|
// We want to use a few optional flags:
|
||||||
|
// * --wait, to block the update command until completion (added in systemd 232)
|
||||||
|
// * --pipe, to collect stdout/stderr (added in systemd 235)
|
||||||
|
// * --collect, to clean up failed runs from memory (added in systemd 236)
|
||||||
|
//
|
||||||
|
// We need to check the version of systemd to figure out if those flags are
|
||||||
|
// available.
|
||||||
|
//
|
||||||
|
// The output will look like:
|
||||||
|
//
|
||||||
|
// systemd 255 (255.7-1-arch)
|
||||||
|
// +PAM +AUDIT ... other feature flags ...
|
||||||
|
systemdVerOut, err := exec.Command("systemd-run", "--version").Output()
|
||||||
|
if err != nil {
|
||||||
|
return defaultCmd
|
||||||
|
}
|
||||||
|
parts := strings.Fields(string(systemdVerOut))
|
||||||
|
if len(parts) < 2 || parts[0] != "systemd" {
|
||||||
|
return defaultCmd
|
||||||
|
}
|
||||||
|
systemdVer, err := strconv.Atoi(parts[1])
|
||||||
|
if err != nil {
|
||||||
|
return defaultCmd
|
||||||
|
}
|
||||||
|
if systemdVer >= 236 {
|
||||||
|
return exec.Command("systemd-run", "--wait", "--pipe", "--collect", cmdTS, "update", "--yes")
|
||||||
|
} else if systemdVer >= 235 {
|
||||||
|
return exec.Command("systemd-run", "--wait", "--pipe", cmdTS, "update", "--yes")
|
||||||
|
} else if systemdVer >= 232 {
|
||||||
|
return exec.Command("systemd-run", "--wait", cmdTS, "update", "--yes")
|
||||||
|
} else {
|
||||||
|
return exec.Command("systemd-run", cmdTS, "update", "--yes")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func regularFileExists(path string) bool {
|
||||||
|
fi, err := os.Stat(path)
|
||||||
|
return err == nil && fi.Mode().IsRegular()
|
||||||
|
}
|
||||||
|
|
||||||
|
// startAutoUpdate triggers an auto-update attempt. The actual update happens
|
||||||
|
// asynchronously. If another update is in progress, an error is returned.
|
||||||
|
func (e *extension) startAutoUpdate(logPrefix string) (retErr error) {
|
||||||
|
// Check if update was already started, and mark as started.
|
||||||
|
if !e.trySetC2NUpdateStarted() {
|
||||||
|
return errors.New("update already started")
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
// Clear the started flag if something failed.
|
||||||
|
if retErr != nil {
|
||||||
|
e.setC2NUpdateStarted(false)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
cmdTS, err := findCmdTailscale()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to find cmd/tailscale binary: %w", err)
|
||||||
|
}
|
||||||
|
var ver struct {
|
||||||
|
Long string `json:"long"`
|
||||||
|
}
|
||||||
|
out, err := exec.Command(cmdTS, "version", "--json").Output()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to find cmd/tailscale binary: %w", err)
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(out, &ver); err != nil {
|
||||||
|
return fmt.Errorf("invalid JSON from cmd/tailscale version --json: %w", err)
|
||||||
|
}
|
||||||
|
if ver.Long != version.Long() {
|
||||||
|
return fmt.Errorf("cmd/tailscale version %q does not match tailscaled version %q", ver.Long, version.Long())
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := tailscaleUpdateCmd(cmdTS)
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
cmd.Stdout = buf
|
||||||
|
cmd.Stderr = buf
|
||||||
|
e.logf("%s: running %q", logPrefix, strings.Join(cmd.Args, " "))
|
||||||
|
if err := cmd.Start(); err != nil {
|
||||||
|
return fmt.Errorf("failed to start cmd/tailscale update: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
if err := cmd.Wait(); err != nil {
|
||||||
|
e.logf("%s: update command failed: %v, output: %s", logPrefix, err, buf)
|
||||||
|
} else {
|
||||||
|
e.logf("%s: update attempt complete", logPrefix)
|
||||||
|
}
|
||||||
|
e.setC2NUpdateStarted(false)
|
||||||
|
}()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *extension) stopOfflineAutoUpdate() {
|
||||||
|
e.mu.Lock()
|
||||||
|
defer e.mu.Unlock()
|
||||||
|
e.stopOfflineAutoUpdateLocked()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *extension) stopOfflineAutoUpdateLocked() {
|
||||||
|
if e.offlineAutoUpdateCancel == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.logf("offline auto-update: stopping update checks")
|
||||||
|
e.offlineAutoUpdateCancel()
|
||||||
|
e.offlineAutoUpdateCancel = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// e.mu must be held
|
||||||
|
func (e *extension) maybeStartOfflineAutoUpdateLocked(prefs ipn.PrefsView) {
|
||||||
|
if !prefs.Valid() || !prefs.AutoUpdate().Apply.EqualBool(true) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// AutoUpdate.Apply field in prefs can only be true for platforms that
|
||||||
|
// support auto-updates. But check it here again, just in case.
|
||||||
|
if !feature.CanAutoUpdate() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// On macsys, auto-updates are managed by Sparkle.
|
||||||
|
if version.IsMacSysExt() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if e.offlineAutoUpdateCancel != nil {
|
||||||
|
// Already running.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
e.offlineAutoUpdateCancel = cancel
|
||||||
|
|
||||||
|
e.logf("offline auto-update: starting update checks")
|
||||||
|
go e.offlineAutoUpdate(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
const offlineAutoUpdateCheckPeriod = time.Hour
|
||||||
|
|
||||||
|
func (e *extension) offlineAutoUpdate(ctx context.Context) {
|
||||||
|
t := time.NewTicker(offlineAutoUpdateCheckPeriod)
|
||||||
|
defer t.Stop()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
case <-t.C:
|
||||||
|
}
|
||||||
|
if err := e.startAutoUpdate("offline auto-update"); err != nil {
|
||||||
|
e.logf("offline auto-update: failed: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
8
feature/condregister/maybe_clientupdate.go
Normal file
8
feature/condregister/maybe_clientupdate.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// Copyright (c) Tailscale Inc & AUTHORS
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
//go:build !ts_omit_clientupdate
|
||||||
|
|
||||||
|
package condregister
|
||||||
|
|
||||||
|
import _ "tailscale.com/feature/clientupdate"
|
@ -97,6 +97,7 @@ var Features = map[FeatureTag]FeatureMeta{
|
|||||||
"capture": {"Capture", "Packet capture", nil},
|
"capture": {"Capture", "Packet capture", nil},
|
||||||
"cli": {"CLI", "embed the CLI into the tailscaled binary", nil},
|
"cli": {"CLI", "embed the CLI into the tailscaled binary", nil},
|
||||||
"cliconndiag": {"CLIConnDiag", "CLI connection error diagnostics", nil},
|
"cliconndiag": {"CLIConnDiag", "CLI connection error diagnostics", nil},
|
||||||
|
"clientupdate": {"ClientUpdate", "Client auto-update support", nil},
|
||||||
"completion": {"Completion", "CLI shell completion", nil},
|
"completion": {"Completion", "CLI shell completion", nil},
|
||||||
"dbus": {"DBus", "Linux DBus support", nil},
|
"dbus": {"DBus", "Linux DBus support", nil},
|
||||||
"debugeventbus": {"DebugEventBus", "eventbus debug support", nil},
|
"debugeventbus": {"DebugEventBus", "eventbus debug support", nil},
|
||||||
|
17
feature/hooks.go
Normal file
17
feature/hooks.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright (c) Tailscale Inc & AUTHORS
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
package feature
|
||||||
|
|
||||||
|
// HookCanAutoUpdate is a hook for the clientupdate package
|
||||||
|
// to conditionally initialize.
|
||||||
|
var HookCanAutoUpdate Hook[func() bool]
|
||||||
|
|
||||||
|
// CanAutoUpdate reports whether the current binary is built with auto-update
|
||||||
|
// support and, if so, whether the current platform supports it.
|
||||||
|
func CanAutoUpdate() bool {
|
||||||
|
if f, ok := HookCanAutoUpdate.GetOk(); ok {
|
||||||
|
return f()
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
@ -1,65 +0,0 @@
|
|||||||
// Copyright (c) Tailscale Inc & AUTHORS
|
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
|
|
||||||
//go:build linux || windows
|
|
||||||
|
|
||||||
package ipnlocal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"tailscale.com/clientupdate"
|
|
||||||
"tailscale.com/ipn"
|
|
||||||
"tailscale.com/version"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (b *LocalBackend) stopOfflineAutoUpdate() {
|
|
||||||
if b.offlineAutoUpdateCancel != nil {
|
|
||||||
b.logf("offline auto-update: stopping update checks")
|
|
||||||
b.offlineAutoUpdateCancel()
|
|
||||||
b.offlineAutoUpdateCancel = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *LocalBackend) maybeStartOfflineAutoUpdate(prefs ipn.PrefsView) {
|
|
||||||
if !prefs.AutoUpdate().Apply.EqualBool(true) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// AutoUpdate.Apply field in prefs can only be true for platforms that
|
|
||||||
// support auto-updates. But check it here again, just in case.
|
|
||||||
if !clientupdate.CanAutoUpdate() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// On macsys, auto-updates are managed by Sparkle.
|
|
||||||
if version.IsMacSysExt() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if b.offlineAutoUpdateCancel != nil {
|
|
||||||
// Already running.
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
b.offlineAutoUpdateCancel = cancel
|
|
||||||
|
|
||||||
b.logf("offline auto-update: starting update checks")
|
|
||||||
go b.offlineAutoUpdate(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
const offlineAutoUpdateCheckPeriod = time.Hour
|
|
||||||
|
|
||||||
func (b *LocalBackend) offlineAutoUpdate(ctx context.Context) {
|
|
||||||
t := time.NewTicker(offlineAutoUpdateCheckPeriod)
|
|
||||||
defer t.Stop()
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
|
||||||
case <-t.C:
|
|
||||||
}
|
|
||||||
if err := b.startAutoUpdate("offline auto-update"); err != nil {
|
|
||||||
b.logf("offline auto-update: failed: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
// Copyright (c) Tailscale Inc & AUTHORS
|
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
|
|
||||||
//go:build !(linux || windows)
|
|
||||||
|
|
||||||
package ipnlocal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"tailscale.com/ipn"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (b *LocalBackend) stopOfflineAutoUpdate() {
|
|
||||||
// Not supported on this platform.
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *LocalBackend) maybeStartOfflineAutoUpdate(prefs ipn.PrefsView) {
|
|
||||||
// Not supported on this platform.
|
|
||||||
}
|
|
@ -5,23 +5,16 @@ package ipnlocal
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"tailscale.com/clientupdate"
|
|
||||||
"tailscale.com/control/controlclient"
|
"tailscale.com/control/controlclient"
|
||||||
"tailscale.com/envknob"
|
|
||||||
"tailscale.com/ipn"
|
"tailscale.com/ipn"
|
||||||
"tailscale.com/net/sockstats"
|
"tailscale.com/net/sockstats"
|
||||||
"tailscale.com/posture"
|
"tailscale.com/posture"
|
||||||
@ -34,7 +27,6 @@ import (
|
|||||||
"tailscale.com/util/syspolicy/pkey"
|
"tailscale.com/util/syspolicy/pkey"
|
||||||
"tailscale.com/util/syspolicy/ptype"
|
"tailscale.com/util/syspolicy/ptype"
|
||||||
"tailscale.com/version"
|
"tailscale.com/version"
|
||||||
"tailscale.com/version/distro"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// c2nHandlers maps an HTTP method and URI path (without query parameters) to
|
// c2nHandlers maps an HTTP method and URI path (without query parameters) to
|
||||||
@ -60,10 +52,6 @@ var c2nHandlers = map[methodAndPath]c2nHandler{
|
|||||||
// SSH
|
// SSH
|
||||||
req("/ssh/usernames"): handleC2NSSHUsernames,
|
req("/ssh/usernames"): handleC2NSSHUsernames,
|
||||||
|
|
||||||
// Auto-updates.
|
|
||||||
req("GET /update"): handleC2NUpdateGet,
|
|
||||||
req("POST /update"): handleC2NUpdatePost,
|
|
||||||
|
|
||||||
// Device posture.
|
// Device posture.
|
||||||
req("GET /posture/identity"): handleC2NPostureIdentityGet,
|
req("GET /posture/identity"): handleC2NPostureIdentityGet,
|
||||||
|
|
||||||
@ -337,50 +325,6 @@ func handleC2NSetNetfilterKind(b *LocalBackend, w http.ResponseWriter, r *http.R
|
|||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleC2NUpdateGet(b *LocalBackend, w http.ResponseWriter, r *http.Request) {
|
|
||||||
b.logf("c2n: GET /update received")
|
|
||||||
|
|
||||||
res := b.newC2NUpdateResponse()
|
|
||||||
res.Started = b.c2nUpdateStarted()
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
json.NewEncoder(w).Encode(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleC2NUpdatePost(b *LocalBackend, w http.ResponseWriter, r *http.Request) {
|
|
||||||
b.logf("c2n: POST /update received")
|
|
||||||
res := b.newC2NUpdateResponse()
|
|
||||||
defer func() {
|
|
||||||
if res.Err != "" {
|
|
||||||
b.logf("c2n: POST /update failed: %s", res.Err)
|
|
||||||
}
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
json.NewEncoder(w).Encode(res)
|
|
||||||
}()
|
|
||||||
|
|
||||||
if !res.Enabled {
|
|
||||||
res.Err = "not enabled"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !res.Supported {
|
|
||||||
res.Err = "not supported"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do not update if we have active inbound SSH connections. Control can set
|
|
||||||
// force=true query parameter to override this.
|
|
||||||
if r.FormValue("force") != "true" && b.sshServer != nil && b.sshServer.NumActiveConns() > 0 {
|
|
||||||
res.Err = "not updating due to active SSH connections"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := b.startAutoUpdate("c2n"); err != nil {
|
|
||||||
res.Err = err.Error()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
res.Started = true
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleC2NPostureIdentityGet(b *LocalBackend, w http.ResponseWriter, r *http.Request) {
|
func handleC2NPostureIdentityGet(b *LocalBackend, w http.ResponseWriter, r *http.Request) {
|
||||||
b.logf("c2n: GET /posture/identity received")
|
b.logf("c2n: GET /posture/identity received")
|
||||||
|
|
||||||
@ -423,137 +367,3 @@ func handleC2NPostureIdentityGet(b *LocalBackend, w http.ResponseWriter, r *http
|
|||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(w).Encode(res)
|
json.NewEncoder(w).Encode(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LocalBackend) newC2NUpdateResponse() tailcfg.C2NUpdateResponse {
|
|
||||||
// If NewUpdater does not return an error, we can update the installation.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
prefs := b.Prefs().AutoUpdate()
|
|
||||||
return tailcfg.C2NUpdateResponse{
|
|
||||||
Enabled: envknob.AllowsRemoteUpdate() || prefs.Apply.EqualBool(true),
|
|
||||||
Supported: clientupdate.CanAutoUpdate() && !version.IsMacSysExt(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *LocalBackend) c2nUpdateStarted() bool {
|
|
||||||
b.mu.Lock()
|
|
||||||
defer b.mu.Unlock()
|
|
||||||
return b.c2nUpdateStatus.started
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *LocalBackend) setC2NUpdateStarted(v bool) {
|
|
||||||
b.mu.Lock()
|
|
||||||
defer b.mu.Unlock()
|
|
||||||
b.c2nUpdateStatus.started = v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *LocalBackend) trySetC2NUpdateStarted() bool {
|
|
||||||
b.mu.Lock()
|
|
||||||
defer b.mu.Unlock()
|
|
||||||
if b.c2nUpdateStatus.started {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
b.c2nUpdateStatus.started = true
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// findCmdTailscale looks for the cmd/tailscale that corresponds to the
|
|
||||||
// currently running cmd/tailscaled. It's up to the caller to verify that the
|
|
||||||
// two match, but this function does its best to find the right one. Notably, it
|
|
||||||
// doesn't use $PATH for security reasons.
|
|
||||||
func findCmdTailscale() (string, error) {
|
|
||||||
self, err := os.Executable()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
var ts string
|
|
||||||
switch runtime.GOOS {
|
|
||||||
case "linux":
|
|
||||||
if self == "/usr/sbin/tailscaled" || self == "/usr/bin/tailscaled" {
|
|
||||||
ts = "/usr/bin/tailscale"
|
|
||||||
}
|
|
||||||
if self == "/usr/local/sbin/tailscaled" || self == "/usr/local/bin/tailscaled" {
|
|
||||||
ts = "/usr/local/bin/tailscale"
|
|
||||||
}
|
|
||||||
switch distro.Get() {
|
|
||||||
case 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 distro.Unraid:
|
|
||||||
if self == "/usr/local/emhttp/plugins/tailscale/bin/tailscaled" {
|
|
||||||
ts = "/usr/local/emhttp/plugins/tailscale/bin/tailscale"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case "windows":
|
|
||||||
ts = filepath.Join(filepath.Dir(self), "tailscale.exe")
|
|
||||||
case "freebsd", "openbsd":
|
|
||||||
if self == "/usr/local/bin/tailscaled" {
|
|
||||||
ts = "/usr/local/bin/tailscale"
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return "", fmt.Errorf("unsupported OS %v", runtime.GOOS)
|
|
||||||
}
|
|
||||||
if ts != "" && regularFileExists(ts) {
|
|
||||||
return ts, nil
|
|
||||||
}
|
|
||||||
return "", errors.New("tailscale executable not found in expected place")
|
|
||||||
}
|
|
||||||
|
|
||||||
func tailscaleUpdateCmd(cmdTS string) *exec.Cmd {
|
|
||||||
defaultCmd := exec.Command(cmdTS, "update", "--yes")
|
|
||||||
if runtime.GOOS != "linux" {
|
|
||||||
return defaultCmd
|
|
||||||
}
|
|
||||||
if _, err := exec.LookPath("systemd-run"); err != nil {
|
|
||||||
return defaultCmd
|
|
||||||
}
|
|
||||||
|
|
||||||
// When systemd-run is available, use it to run the update command. This
|
|
||||||
// creates a new temporary unit separate from the tailscaled unit. When
|
|
||||||
// tailscaled is restarted during the update, systemd won't kill this
|
|
||||||
// temporary update unit, which could cause unexpected breakage.
|
|
||||||
//
|
|
||||||
// We want to use a few optional flags:
|
|
||||||
// * --wait, to block the update command until completion (added in systemd 232)
|
|
||||||
// * --pipe, to collect stdout/stderr (added in systemd 235)
|
|
||||||
// * --collect, to clean up failed runs from memory (added in systemd 236)
|
|
||||||
//
|
|
||||||
// We need to check the version of systemd to figure out if those flags are
|
|
||||||
// available.
|
|
||||||
//
|
|
||||||
// The output will look like:
|
|
||||||
//
|
|
||||||
// systemd 255 (255.7-1-arch)
|
|
||||||
// +PAM +AUDIT ... other feature flags ...
|
|
||||||
systemdVerOut, err := exec.Command("systemd-run", "--version").Output()
|
|
||||||
if err != nil {
|
|
||||||
return defaultCmd
|
|
||||||
}
|
|
||||||
parts := strings.Fields(string(systemdVerOut))
|
|
||||||
if len(parts) < 2 || parts[0] != "systemd" {
|
|
||||||
return defaultCmd
|
|
||||||
}
|
|
||||||
systemdVer, err := strconv.Atoi(parts[1])
|
|
||||||
if err != nil {
|
|
||||||
return defaultCmd
|
|
||||||
}
|
|
||||||
if systemdVer >= 236 {
|
|
||||||
return exec.Command("systemd-run", "--wait", "--pipe", "--collect", cmdTS, "update", "--yes")
|
|
||||||
} else if systemdVer >= 235 {
|
|
||||||
return exec.Command("systemd-run", "--wait", "--pipe", cmdTS, "update", "--yes")
|
|
||||||
} else if systemdVer >= 232 {
|
|
||||||
return exec.Command("systemd-run", "--wait", cmdTS, "update", "--yes")
|
|
||||||
} else {
|
|
||||||
return exec.Command("systemd-run", cmdTS, "update", "--yes")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func regularFileExists(path string) bool {
|
|
||||||
fi, err := os.Stat(path)
|
|
||||||
return err == nil && fi.Mode().IsRegular()
|
|
||||||
}
|
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
package ipnlocal
|
package ipnlocal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"cmp"
|
"cmp"
|
||||||
"context"
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
@ -25,7 +24,6 @@ import (
|
|||||||
"net/netip"
|
"net/netip"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"slices"
|
"slices"
|
||||||
@ -40,7 +38,6 @@ import (
|
|||||||
"golang.org/x/net/dns/dnsmessage"
|
"golang.org/x/net/dns/dnsmessage"
|
||||||
"tailscale.com/appc"
|
"tailscale.com/appc"
|
||||||
"tailscale.com/client/tailscale/apitype"
|
"tailscale.com/client/tailscale/apitype"
|
||||||
"tailscale.com/clientupdate"
|
|
||||||
"tailscale.com/control/controlclient"
|
"tailscale.com/control/controlclient"
|
||||||
"tailscale.com/control/controlknobs"
|
"tailscale.com/control/controlknobs"
|
||||||
"tailscale.com/drive"
|
"tailscale.com/drive"
|
||||||
@ -302,22 +299,11 @@ type LocalBackend struct {
|
|||||||
notifyWatchers map[string]*watchSession // by session ID
|
notifyWatchers map[string]*watchSession // by session ID
|
||||||
lastStatusTime time.Time // status.AsOf value of the last processed status update
|
lastStatusTime time.Time // status.AsOf value of the last processed status update
|
||||||
componentLogUntil map[string]componentLogState
|
componentLogUntil map[string]componentLogState
|
||||||
// c2nUpdateStatus is the status of c2n-triggered client update.
|
currentUser ipnauth.Actor
|
||||||
c2nUpdateStatus updateStatus
|
|
||||||
currentUser ipnauth.Actor
|
|
||||||
|
|
||||||
selfUpdateProgress []ipnstate.UpdateProgress
|
|
||||||
lastSelfUpdateState ipnstate.SelfUpdateStatus
|
|
||||||
// capForcedNetfilter is the netfilter that control instructs Linux clients
|
// capForcedNetfilter is the netfilter that control instructs Linux clients
|
||||||
// to use, unless overridden locally.
|
// to use, unless overridden locally.
|
||||||
capForcedNetfilter string // TODO(nickkhyl): move to nodeBackend
|
capForcedNetfilter string // TODO(nickkhyl): move to nodeBackend
|
||||||
// offlineAutoUpdateCancel stops offline auto-updates when called. It
|
|
||||||
// should be used via stopOfflineAutoUpdate and
|
|
||||||
// maybeStartOfflineAutoUpdate. It is nil when offline auto-updates are
|
|
||||||
// note running.
|
|
||||||
//
|
|
||||||
//lint:ignore U1000 only used in Linux and Windows builds in autoupdate.go
|
|
||||||
offlineAutoUpdateCancel func()
|
|
||||||
|
|
||||||
// ServeConfig fields. (also guarded by mu)
|
// ServeConfig fields. (also guarded by mu)
|
||||||
lastServeConfJSON mem.RO // last JSON that was parsed into serveConfig
|
lastServeConfJSON mem.RO // last JSON that was parsed into serveConfig
|
||||||
@ -433,10 +419,6 @@ func (b *LocalBackend) NetMon() *netmon.Monitor {
|
|||||||
return b.sys.NetMon.Get()
|
return b.sys.NetMon.Get()
|
||||||
}
|
}
|
||||||
|
|
||||||
type updateStatus struct {
|
|
||||||
started bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type metrics struct {
|
type metrics struct {
|
||||||
// advertisedRoutes is a metric that reports the number of network routes that are advertised by the local node.
|
// advertisedRoutes is a metric that reports the number of network routes that are advertised by the local node.
|
||||||
// This informs the user of how many routes are being advertised by the local node, excluding exit routes.
|
// This informs the user of how many routes are being advertised by the local node, excluding exit routes.
|
||||||
@ -517,8 +499,6 @@ func NewLocalBackend(logf logger.Logf, logID logid.PublicID, sys *tsd.System, lo
|
|||||||
em: newExpiryManager(logf, sys.Bus.Get()),
|
em: newExpiryManager(logf, sys.Bus.Get()),
|
||||||
loginFlags: loginFlags,
|
loginFlags: loginFlags,
|
||||||
clock: clock,
|
clock: clock,
|
||||||
selfUpdateProgress: make([]ipnstate.UpdateProgress, 0),
|
|
||||||
lastSelfUpdateState: ipnstate.UpdateFinished,
|
|
||||||
captiveCtx: captiveCtx,
|
captiveCtx: captiveCtx,
|
||||||
captiveCancel: nil, // so that we start checkCaptivePortalLoop when Running
|
captiveCancel: nil, // so that we start checkCaptivePortalLoop when Running
|
||||||
needsCaptiveDetection: make(chan bool),
|
needsCaptiveDetection: make(chan bool),
|
||||||
@ -1127,7 +1107,6 @@ func (b *LocalBackend) Shutdown() {
|
|||||||
defer cancel()
|
defer cancel()
|
||||||
b.sockstatLogger.Shutdown(ctx)
|
b.sockstatLogger.Shutdown(ctx)
|
||||||
}
|
}
|
||||||
b.stopOfflineAutoUpdate()
|
|
||||||
|
|
||||||
b.unregisterSysPolicyWatch()
|
b.unregisterSysPolicyWatch()
|
||||||
if cc != nil {
|
if cc != nil {
|
||||||
@ -3412,7 +3391,7 @@ func (b *LocalBackend) onTailnetDefaultAutoUpdate(au bool) {
|
|||||||
// can still manually enable auto-updates on this node.
|
// can still manually enable auto-updates on this node.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if clientupdate.CanAutoUpdate() {
|
if buildfeatures.HasClientUpdate && feature.CanAutoUpdate() {
|
||||||
b.logf("using tailnet default auto-update setting: %v", au)
|
b.logf("using tailnet default auto-update setting: %v", au)
|
||||||
prefsClone := prefs.AsStruct()
|
prefsClone := prefs.AsStruct()
|
||||||
prefsClone.AutoUpdate.Apply = opt.NewBool(au)
|
prefsClone.AutoUpdate.Apply = opt.NewBool(au)
|
||||||
@ -4100,7 +4079,12 @@ func (b *LocalBackend) checkFunnelEnabledLocked(p *ipn.Prefs) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *LocalBackend) checkAutoUpdatePrefsLocked(p *ipn.Prefs) error {
|
func (b *LocalBackend) checkAutoUpdatePrefsLocked(p *ipn.Prefs) error {
|
||||||
if p.AutoUpdate.Apply.EqualBool(true) && !clientupdate.CanAutoUpdate() {
|
if !buildfeatures.HasClientUpdate {
|
||||||
|
if p.AutoUpdate.Apply.EqualBool(true) {
|
||||||
|
return errors.New("Auto-update support is disabled in this build")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if p.AutoUpdate.Apply.EqualBool(true) && !feature.CanAutoUpdate() {
|
||||||
return errors.New("Auto-updates are not supported on this platform.")
|
return errors.New("Auto-updates are not supported on this platform.")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -4552,14 +4536,6 @@ func (b *LocalBackend) setPrefsLockedOnEntry(newp *ipn.Prefs, unlock unlockOnce)
|
|||||||
b.resetAlwaysOnOverrideLocked()
|
b.resetAlwaysOnOverrideLocked()
|
||||||
}
|
}
|
||||||
|
|
||||||
if newp.AutoUpdate.Apply.EqualBool(true) {
|
|
||||||
if b.state != ipn.Running {
|
|
||||||
b.maybeStartOfflineAutoUpdate(newp.View())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
b.stopOfflineAutoUpdate()
|
|
||||||
}
|
|
||||||
|
|
||||||
unlock.UnlockEarly()
|
unlock.UnlockEarly()
|
||||||
|
|
||||||
if oldp.ShieldsUp() != newp.ShieldsUp || hostInfoChanged {
|
if oldp.ShieldsUp() != newp.ShieldsUp || hostInfoChanged {
|
||||||
@ -5467,12 +5443,6 @@ func (b *LocalBackend) enterStateLockedOnEntry(newState ipn.State, unlock unlock
|
|||||||
}
|
}
|
||||||
b.pauseOrResumeControlClientLocked()
|
b.pauseOrResumeControlClientLocked()
|
||||||
|
|
||||||
if newState == ipn.Running {
|
|
||||||
b.stopOfflineAutoUpdate()
|
|
||||||
} else {
|
|
||||||
b.maybeStartOfflineAutoUpdate(prefs)
|
|
||||||
}
|
|
||||||
|
|
||||||
unlock.UnlockEarly()
|
unlock.UnlockEarly()
|
||||||
|
|
||||||
// prefs may change irrespective of state; WantRunning should be explicitly
|
// prefs may change irrespective of state; WantRunning should be explicitly
|
||||||
@ -6611,6 +6581,15 @@ func (b *LocalBackend) DoNoiseRequest(req *http.Request) (*http.Response, error)
|
|||||||
return cc.DoNoiseRequest(req)
|
return cc.DoNoiseRequest(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ActiveSSHConns returns the number of active SSH connections,
|
||||||
|
// or 0 if SSH is not linked into the binary or available on the platform.
|
||||||
|
func (b *LocalBackend) ActiveSSHConns() int {
|
||||||
|
if b.sshServer == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return b.sshServer.NumActiveConns()
|
||||||
|
}
|
||||||
|
|
||||||
func (b *LocalBackend) sshServerOrInit() (_ SSHServer, err error) {
|
func (b *LocalBackend) sshServerOrInit() (_ SSHServer, err error) {
|
||||||
b.mu.Lock()
|
b.mu.Lock()
|
||||||
defer b.mu.Unlock()
|
defer b.mu.Unlock()
|
||||||
@ -6941,54 +6920,6 @@ func (b *LocalBackend) DebugBreakDERPConns() error {
|
|||||||
return b.MagicConn().DebugBreakDERPConns()
|
return b.MagicConn().DebugBreakDERPConns()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LocalBackend) pushSelfUpdateProgress(up ipnstate.UpdateProgress) {
|
|
||||||
b.mu.Lock()
|
|
||||||
defer b.mu.Unlock()
|
|
||||||
b.selfUpdateProgress = append(b.selfUpdateProgress, up)
|
|
||||||
b.lastSelfUpdateState = up.Status
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *LocalBackend) clearSelfUpdateProgress() {
|
|
||||||
b.mu.Lock()
|
|
||||||
defer b.mu.Unlock()
|
|
||||||
b.selfUpdateProgress = make([]ipnstate.UpdateProgress, 0)
|
|
||||||
b.lastSelfUpdateState = ipnstate.UpdateFinished
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *LocalBackend) GetSelfUpdateProgress() []ipnstate.UpdateProgress {
|
|
||||||
b.mu.Lock()
|
|
||||||
defer b.mu.Unlock()
|
|
||||||
res := make([]ipnstate.UpdateProgress, len(b.selfUpdateProgress))
|
|
||||||
copy(res, b.selfUpdateProgress)
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *LocalBackend) DoSelfUpdate() {
|
|
||||||
b.mu.Lock()
|
|
||||||
updateState := b.lastSelfUpdateState
|
|
||||||
b.mu.Unlock()
|
|
||||||
// don't start an update if one is already in progress
|
|
||||||
if updateState == ipnstate.UpdateInProgress {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
b.clearSelfUpdateProgress()
|
|
||||||
b.pushSelfUpdateProgress(ipnstate.NewUpdateProgress(ipnstate.UpdateInProgress, ""))
|
|
||||||
up, err := clientupdate.NewUpdater(clientupdate.Arguments{
|
|
||||||
Logf: func(format string, args ...any) {
|
|
||||||
b.pushSelfUpdateProgress(ipnstate.NewUpdateProgress(ipnstate.UpdateInProgress, fmt.Sprintf(format, args...)))
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
b.pushSelfUpdateProgress(ipnstate.NewUpdateProgress(ipnstate.UpdateFailed, err.Error()))
|
|
||||||
}
|
|
||||||
err = up.Update()
|
|
||||||
if err != nil {
|
|
||||||
b.pushSelfUpdateProgress(ipnstate.NewUpdateProgress(ipnstate.UpdateFailed, err.Error()))
|
|
||||||
} else {
|
|
||||||
b.pushSelfUpdateProgress(ipnstate.NewUpdateProgress(ipnstate.UpdateFinished, "tailscaled did not restart; please restart Tailscale manually."))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObserveDNSResponse passes a DNS response from the PeerAPI DNS server to the
|
// ObserveDNSResponse passes a DNS response from the PeerAPI DNS server to the
|
||||||
// App Connector to enable route discovery.
|
// App Connector to enable route discovery.
|
||||||
func (b *LocalBackend) ObserveDNSResponse(res []byte) error {
|
func (b *LocalBackend) ObserveDNSResponse(res []byte) error {
|
||||||
@ -7603,58 +7534,6 @@ func isAllowedAutoExitNodeID(polc policyclient.Client, exitNodeID tailcfg.Stable
|
|||||||
return true // no policy configured; allow all exit nodes
|
return true // no policy configured; allow all exit nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
// startAutoUpdate triggers an auto-update attempt. The actual update happens
|
|
||||||
// asynchronously. If another update is in progress, an error is returned.
|
|
||||||
func (b *LocalBackend) startAutoUpdate(logPrefix string) (retErr error) {
|
|
||||||
// Check if update was already started, and mark as started.
|
|
||||||
if !b.trySetC2NUpdateStarted() {
|
|
||||||
return errors.New("update already started")
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
// Clear the started flag if something failed.
|
|
||||||
if retErr != nil {
|
|
||||||
b.setC2NUpdateStarted(false)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
cmdTS, err := findCmdTailscale()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to find cmd/tailscale binary: %w", err)
|
|
||||||
}
|
|
||||||
var ver struct {
|
|
||||||
Long string `json:"long"`
|
|
||||||
}
|
|
||||||
out, err := exec.Command(cmdTS, "version", "--json").Output()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to find cmd/tailscale binary: %w", err)
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal(out, &ver); err != nil {
|
|
||||||
return fmt.Errorf("invalid JSON from cmd/tailscale version --json: %w", err)
|
|
||||||
}
|
|
||||||
if ver.Long != version.Long() {
|
|
||||||
return fmt.Errorf("cmd/tailscale version %q does not match tailscaled version %q", ver.Long, version.Long())
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd := tailscaleUpdateCmd(cmdTS)
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
cmd.Stdout = buf
|
|
||||||
cmd.Stderr = buf
|
|
||||||
b.logf("%s: running %q", logPrefix, strings.Join(cmd.Args, " "))
|
|
||||||
if err := cmd.Start(); err != nil {
|
|
||||||
return fmt.Errorf("failed to start cmd/tailscale update: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
if err := cmd.Wait(); err != nil {
|
|
||||||
b.logf("%s: update command failed: %v, output: %s", logPrefix, err, buf)
|
|
||||||
} else {
|
|
||||||
b.logf("%s: update attempt complete", logPrefix)
|
|
||||||
}
|
|
||||||
b.setC2NUpdateStarted(false)
|
|
||||||
}()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// srcIPHasCapForFilter is called by the packet filter when evaluating firewall
|
// srcIPHasCapForFilter is called by the packet filter when evaluating firewall
|
||||||
// rules that require a source IP to have a certain node capability.
|
// rules that require a source IP to have a certain node capability.
|
||||||
//
|
//
|
||||||
|
@ -30,10 +30,10 @@ import (
|
|||||||
"golang.org/x/net/dns/dnsmessage"
|
"golang.org/x/net/dns/dnsmessage"
|
||||||
"tailscale.com/appc"
|
"tailscale.com/appc"
|
||||||
"tailscale.com/appc/appctest"
|
"tailscale.com/appc/appctest"
|
||||||
"tailscale.com/clientupdate"
|
|
||||||
"tailscale.com/control/controlclient"
|
"tailscale.com/control/controlclient"
|
||||||
"tailscale.com/drive"
|
"tailscale.com/drive"
|
||||||
"tailscale.com/drive/driveimpl"
|
"tailscale.com/drive/driveimpl"
|
||||||
|
"tailscale.com/feature"
|
||||||
_ "tailscale.com/feature/condregister/portmapper"
|
_ "tailscale.com/feature/condregister/portmapper"
|
||||||
"tailscale.com/health"
|
"tailscale.com/health"
|
||||||
"tailscale.com/hostinfo"
|
"tailscale.com/hostinfo"
|
||||||
@ -3710,7 +3710,7 @@ func TestOnTailnetDefaultAutoUpdate(t *testing.T) {
|
|||||||
// On platforms that don't support auto-update we can never
|
// On platforms that don't support auto-update we can never
|
||||||
// transition to auto-updates being enabled. The value should
|
// transition to auto-updates being enabled. The value should
|
||||||
// remain unchanged after onTailnetDefaultAutoUpdate.
|
// remain unchanged after onTailnetDefaultAutoUpdate.
|
||||||
if !clientupdate.CanAutoUpdate() {
|
if !feature.CanAutoUpdate() {
|
||||||
want = tt.before
|
want = tt.before
|
||||||
}
|
}
|
||||||
if got := b.pm.CurrentPrefs().AutoUpdate().Apply; got != want {
|
if got := b.pm.CurrentPrefs().AutoUpdate().Apply; got != want {
|
||||||
@ -5455,7 +5455,7 @@ func TestEnableAutoUpdates(t *testing.T) {
|
|||||||
})
|
})
|
||||||
// Enabling may fail, depending on which environment we are running this
|
// Enabling may fail, depending on which environment we are running this
|
||||||
// test in.
|
// test in.
|
||||||
wantErr := !clientupdate.CanAutoUpdate()
|
wantErr := !feature.CanAutoUpdate()
|
||||||
gotErr := err != nil
|
gotErr := err != nil
|
||||||
if gotErr != wantErr {
|
if gotErr != wantErr {
|
||||||
t.Fatalf("enabling auto-updates: got error: %v (%v); want error: %v", gotErr, err, wantErr)
|
t.Fatalf("enabling auto-updates: got error: %v (%v); want error: %v", gotErr, err, wantErr)
|
||||||
|
@ -13,8 +13,8 @@ import (
|
|||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"tailscale.com/clientupdate"
|
|
||||||
"tailscale.com/envknob"
|
"tailscale.com/envknob"
|
||||||
|
"tailscale.com/feature"
|
||||||
"tailscale.com/health"
|
"tailscale.com/health"
|
||||||
"tailscale.com/ipn"
|
"tailscale.com/ipn"
|
||||||
"tailscale.com/ipn/ipnext"
|
"tailscale.com/ipn/ipnext"
|
||||||
@ -674,7 +674,7 @@ func (pm *profileManager) loadSavedPrefs(key ipn.StateKey) (ipn.PrefsView, error
|
|||||||
// cause any EditPrefs calls to fail (other than disabling auto-updates).
|
// cause any EditPrefs calls to fail (other than disabling auto-updates).
|
||||||
//
|
//
|
||||||
// Reset AutoUpdate.Apply if we detect such invalid prefs.
|
// Reset AutoUpdate.Apply if we detect such invalid prefs.
|
||||||
if savedPrefs.AutoUpdate.Apply.EqualBool(true) && !clientupdate.CanAutoUpdate() {
|
if savedPrefs.AutoUpdate.Apply.EqualBool(true) && !feature.CanAutoUpdate() {
|
||||||
savedPrefs.AutoUpdate.Apply.Clear()
|
savedPrefs.AutoUpdate.Apply.Clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,8 @@ import (
|
|||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
"github.com/google/go-cmp/cmp/cmpopts"
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||||||
"tailscale.com/clientupdate"
|
_ "tailscale.com/clientupdate" // for feature registration side effects
|
||||||
|
"tailscale.com/feature"
|
||||||
"tailscale.com/health"
|
"tailscale.com/health"
|
||||||
"tailscale.com/ipn"
|
"tailscale.com/ipn"
|
||||||
"tailscale.com/ipn/store/mem"
|
"tailscale.com/ipn/store/mem"
|
||||||
@ -464,7 +465,7 @@ func TestProfileManagement(t *testing.T) {
|
|||||||
wantCurProfile = "user@2.example.com"
|
wantCurProfile = "user@2.example.com"
|
||||||
checkProfiles(t)
|
checkProfiles(t)
|
||||||
|
|
||||||
if !clientupdate.CanAutoUpdate() {
|
if !feature.CanAutoUpdate() {
|
||||||
t.Logf("Save an invalid AutoUpdate pref value")
|
t.Logf("Save an invalid AutoUpdate pref value")
|
||||||
prefs := pm.CurrentPrefs().AsStruct()
|
prefs := pm.CurrentPrefs().AsStruct()
|
||||||
prefs.AutoUpdate.Apply.Set(true)
|
prefs.AutoUpdate.Apply.Set(true)
|
||||||
|
@ -27,8 +27,8 @@ import (
|
|||||||
"golang.org/x/net/dns/dnsmessage"
|
"golang.org/x/net/dns/dnsmessage"
|
||||||
"tailscale.com/appc"
|
"tailscale.com/appc"
|
||||||
"tailscale.com/client/tailscale/apitype"
|
"tailscale.com/client/tailscale/apitype"
|
||||||
"tailscale.com/clientupdate"
|
|
||||||
"tailscale.com/envknob"
|
"tailscale.com/envknob"
|
||||||
|
"tailscale.com/feature"
|
||||||
"tailscale.com/feature/buildfeatures"
|
"tailscale.com/feature/buildfeatures"
|
||||||
"tailscale.com/health/healthmsg"
|
"tailscale.com/health/healthmsg"
|
||||||
"tailscale.com/hostinfo"
|
"tailscale.com/hostinfo"
|
||||||
@ -120,8 +120,6 @@ var handler = map[string]LocalAPIHandler{
|
|||||||
"status": (*Handler).serveStatus,
|
"status": (*Handler).serveStatus,
|
||||||
"suggest-exit-node": (*Handler).serveSuggestExitNode,
|
"suggest-exit-node": (*Handler).serveSuggestExitNode,
|
||||||
"update/check": (*Handler).serveUpdateCheck,
|
"update/check": (*Handler).serveUpdateCheck,
|
||||||
"update/install": (*Handler).serveUpdateInstall,
|
|
||||||
"update/progress": (*Handler).serveUpdateProgress,
|
|
||||||
"upload-client-metrics": (*Handler).serveUploadClientMetrics,
|
"upload-client-metrics": (*Handler).serveUploadClientMetrics,
|
||||||
"usermetrics": (*Handler).serveUserMetrics,
|
"usermetrics": (*Handler).serveUserMetrics,
|
||||||
"watch-ipn-bus": (*Handler).serveWatchIPNBus,
|
"watch-ipn-bus": (*Handler).serveWatchIPNBus,
|
||||||
@ -1897,7 +1895,7 @@ func (h *Handler) serveUpdateCheck(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !clientupdate.CanAutoUpdate() {
|
if !feature.CanAutoUpdate() {
|
||||||
// if we don't support auto-update, just say that we're up to date
|
// if we don't support auto-update, just say that we're up to date
|
||||||
json.NewEncoder(w).Encode(tailcfg.ClientVersion{RunningLatest: true})
|
json.NewEncoder(w).Encode(tailcfg.ClientVersion{RunningLatest: true})
|
||||||
return
|
return
|
||||||
@ -1915,37 +1913,6 @@ func (h *Handler) serveUpdateCheck(w http.ResponseWriter, r *http.Request) {
|
|||||||
json.NewEncoder(w).Encode(cv)
|
json.NewEncoder(w).Encode(cv)
|
||||||
}
|
}
|
||||||
|
|
||||||
// serveUpdateInstall sends a request to the LocalBackend to start a Tailscale
|
|
||||||
// self-update. A successful response does not indicate whether the update
|
|
||||||
// succeeded, only that the request was accepted. Clients should use
|
|
||||||
// serveUpdateProgress after pinging this endpoint to check how the update is
|
|
||||||
// going.
|
|
||||||
func (h *Handler) serveUpdateInstall(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method != httpm.POST {
|
|
||||||
http.Error(w, "only POST allowed", http.StatusMethodNotAllowed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
w.WriteHeader(http.StatusAccepted)
|
|
||||||
|
|
||||||
go h.b.DoSelfUpdate()
|
|
||||||
}
|
|
||||||
|
|
||||||
// serveUpdateProgress returns the status of an in-progress Tailscale self-update.
|
|
||||||
// This is provided as a slice of ipnstate.UpdateProgress structs with various
|
|
||||||
// log messages in order from oldest to newest. If an update is not in progress,
|
|
||||||
// the returned slice will be empty.
|
|
||||||
func (h *Handler) serveUpdateProgress(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method != httpm.GET {
|
|
||||||
http.Error(w, "only GET allowed", http.StatusMethodNotAllowed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ups := h.b.GetSelfUpdateProgress()
|
|
||||||
|
|
||||||
json.NewEncoder(w).Encode(ups)
|
|
||||||
}
|
|
||||||
|
|
||||||
// serveDNSOSConfig serves the current system DNS configuration as a JSON object, if
|
// serveDNSOSConfig serves the current system DNS configuration as a JSON object, if
|
||||||
// supported by the OS.
|
// supported by the OS.
|
||||||
func (h *Handler) serveDNSOSConfig(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) serveDNSOSConfig(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -9,7 +9,7 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
|
|||||||
LDW github.com/coder/websocket/internal/errd from github.com/coder/websocket
|
LDW github.com/coder/websocket/internal/errd from github.com/coder/websocket
|
||||||
LDW github.com/coder/websocket/internal/util from github.com/coder/websocket
|
LDW github.com/coder/websocket/internal/util from github.com/coder/websocket
|
||||||
LDW github.com/coder/websocket/internal/xsync from github.com/coder/websocket
|
LDW github.com/coder/websocket/internal/xsync from github.com/coder/websocket
|
||||||
W 💣 github.com/dblohm7/wingoes from github.com/dblohm7/wingoes/com+
|
W 💣 github.com/dblohm7/wingoes from tailscale.com/net/tshttpproxy+
|
||||||
W 💣 github.com/dblohm7/wingoes/com from tailscale.com/util/osdiag+
|
W 💣 github.com/dblohm7/wingoes/com from tailscale.com/util/osdiag+
|
||||||
W 💣 github.com/dblohm7/wingoes/com/automation from tailscale.com/util/osdiag/internal/wsc
|
W 💣 github.com/dblohm7/wingoes/com/automation from tailscale.com/util/osdiag/internal/wsc
|
||||||
W github.com/dblohm7/wingoes/internal from github.com/dblohm7/wingoes/com
|
W github.com/dblohm7/wingoes/internal from github.com/dblohm7/wingoes/com
|
||||||
@ -28,8 +28,8 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
|
|||||||
L 💣 github.com/godbus/dbus/v5 from tailscale.com/net/dns
|
L 💣 github.com/godbus/dbus/v5 from tailscale.com/net/dns
|
||||||
github.com/golang/groupcache/lru from tailscale.com/net/dnscache
|
github.com/golang/groupcache/lru from tailscale.com/net/dnscache
|
||||||
github.com/google/btree from gvisor.dev/gvisor/pkg/tcpip/header+
|
github.com/google/btree from gvisor.dev/gvisor/pkg/tcpip/header+
|
||||||
DWI github.com/google/uuid from github.com/prometheus-community/pro-bing+
|
DI github.com/google/uuid from github.com/prometheus-community/pro-bing
|
||||||
github.com/hdevalence/ed25519consensus from tailscale.com/clientupdate/distsign+
|
github.com/hdevalence/ed25519consensus from tailscale.com/tka
|
||||||
L 💣 github.com/jsimonetti/rtnetlink from tailscale.com/net/netmon
|
L 💣 github.com/jsimonetti/rtnetlink from tailscale.com/net/netmon
|
||||||
L github.com/jsimonetti/rtnetlink/internal/unix from github.com/jsimonetti/rtnetlink
|
L github.com/jsimonetti/rtnetlink/internal/unix from github.com/jsimonetti/rtnetlink
|
||||||
github.com/klauspost/compress from github.com/klauspost/compress/zstd
|
github.com/klauspost/compress from github.com/klauspost/compress/zstd
|
||||||
@ -124,8 +124,6 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
|
|||||||
tailscale.com/client/tailscale from tailscale.com/internal/client/tailscale
|
tailscale.com/client/tailscale from tailscale.com/internal/client/tailscale
|
||||||
tailscale.com/client/tailscale/apitype from tailscale.com/client/local+
|
tailscale.com/client/tailscale/apitype from tailscale.com/client/local+
|
||||||
LDW tailscale.com/client/web from tailscale.com/ipn/ipnlocal
|
LDW tailscale.com/client/web from tailscale.com/ipn/ipnlocal
|
||||||
tailscale.com/clientupdate from tailscale.com/client/web+
|
|
||||||
LW tailscale.com/clientupdate/distsign from tailscale.com/clientupdate
|
|
||||||
tailscale.com/control/controlbase from tailscale.com/control/controlhttp+
|
tailscale.com/control/controlbase from tailscale.com/control/controlhttp+
|
||||||
tailscale.com/control/controlclient from tailscale.com/ipn/ipnext+
|
tailscale.com/control/controlclient from tailscale.com/ipn/ipnext+
|
||||||
tailscale.com/control/controlhttp from tailscale.com/control/controlclient
|
tailscale.com/control/controlhttp from tailscale.com/control/controlclient
|
||||||
@ -204,7 +202,7 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
|
|||||||
tailscale.com/net/tlsdial/blockblame from tailscale.com/net/tlsdial
|
tailscale.com/net/tlsdial/blockblame from tailscale.com/net/tlsdial
|
||||||
tailscale.com/net/tsaddr from tailscale.com/client/web+
|
tailscale.com/net/tsaddr from tailscale.com/client/web+
|
||||||
tailscale.com/net/tsdial from tailscale.com/control/controlclient+
|
tailscale.com/net/tsdial from tailscale.com/control/controlclient+
|
||||||
💣 tailscale.com/net/tshttpproxy from tailscale.com/clientupdate/distsign+
|
💣 tailscale.com/net/tshttpproxy from tailscale.com/control/controlclient+
|
||||||
tailscale.com/net/tstun from tailscale.com/tsd+
|
tailscale.com/net/tstun from tailscale.com/tsd+
|
||||||
tailscale.com/net/udprelay/endpoint from tailscale.com/wgengine/magicsock
|
tailscale.com/net/udprelay/endpoint from tailscale.com/wgengine/magicsock
|
||||||
tailscale.com/net/udprelay/status from tailscale.com/client/local
|
tailscale.com/net/udprelay/status from tailscale.com/client/local
|
||||||
@ -232,7 +230,7 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
|
|||||||
tailscale.com/types/empty from tailscale.com/ipn+
|
tailscale.com/types/empty from tailscale.com/ipn+
|
||||||
tailscale.com/types/ipproto from tailscale.com/ipn+
|
tailscale.com/types/ipproto from tailscale.com/ipn+
|
||||||
tailscale.com/types/key from tailscale.com/client/local+
|
tailscale.com/types/key from tailscale.com/client/local+
|
||||||
tailscale.com/types/lazy from tailscale.com/clientupdate+
|
tailscale.com/types/lazy from tailscale.com/hostinfo+
|
||||||
tailscale.com/types/logger from tailscale.com/appc+
|
tailscale.com/types/logger from tailscale.com/appc+
|
||||||
tailscale.com/types/logid from tailscale.com/ipn/ipnlocal+
|
tailscale.com/types/logid from tailscale.com/ipn/ipnlocal+
|
||||||
tailscale.com/types/mapx from tailscale.com/ipn/ipnext
|
tailscale.com/types/mapx from tailscale.com/ipn/ipnext
|
||||||
@ -251,12 +249,12 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
|
|||||||
tailscale.com/util/cibuild from tailscale.com/health
|
tailscale.com/util/cibuild from tailscale.com/health
|
||||||
tailscale.com/util/clientmetric from tailscale.com/appc+
|
tailscale.com/util/clientmetric from tailscale.com/appc+
|
||||||
tailscale.com/util/cloudenv from tailscale.com/hostinfo+
|
tailscale.com/util/cloudenv from tailscale.com/hostinfo+
|
||||||
tailscale.com/util/cmpver from tailscale.com/clientupdate+
|
LW tailscale.com/util/cmpver from tailscale.com/net/dns+
|
||||||
tailscale.com/util/ctxkey from tailscale.com/client/tailscale/apitype+
|
tailscale.com/util/ctxkey from tailscale.com/client/tailscale/apitype+
|
||||||
💣 tailscale.com/util/deephash from tailscale.com/ipn/ipnlocal+
|
💣 tailscale.com/util/deephash from tailscale.com/ipn/ipnlocal+
|
||||||
LA 💣 tailscale.com/util/dirwalk from tailscale.com/metrics
|
LA 💣 tailscale.com/util/dirwalk from tailscale.com/metrics
|
||||||
tailscale.com/util/dnsname from tailscale.com/appc+
|
tailscale.com/util/dnsname from tailscale.com/appc+
|
||||||
tailscale.com/util/eventbus from tailscale.com/ipn/localapi+
|
tailscale.com/util/eventbus from tailscale.com/client/local+
|
||||||
tailscale.com/util/execqueue from tailscale.com/appc+
|
tailscale.com/util/execqueue from tailscale.com/appc+
|
||||||
tailscale.com/util/goroutines from tailscale.com/ipn/ipnlocal
|
tailscale.com/util/goroutines from tailscale.com/ipn/ipnlocal
|
||||||
tailscale.com/util/groupmember from tailscale.com/client/web+
|
tailscale.com/util/groupmember from tailscale.com/client/web+
|
||||||
@ -265,7 +263,7 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
|
|||||||
tailscale.com/util/lineiter from tailscale.com/hostinfo+
|
tailscale.com/util/lineiter from tailscale.com/hostinfo+
|
||||||
tailscale.com/util/mak from tailscale.com/appc+
|
tailscale.com/util/mak from tailscale.com/appc+
|
||||||
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/clientupdate/distsign+
|
tailscale.com/util/must from tailscale.com/logpolicy+
|
||||||
tailscale.com/util/nocasemaps from tailscale.com/types/ipproto
|
tailscale.com/util/nocasemaps from tailscale.com/types/ipproto
|
||||||
💣 tailscale.com/util/osdiag from tailscale.com/ipn/localapi
|
💣 tailscale.com/util/osdiag from tailscale.com/ipn/localapi
|
||||||
W 💣 tailscale.com/util/osdiag/internal/wsc from tailscale.com/util/osdiag
|
W 💣 tailscale.com/util/osdiag/internal/wsc from tailscale.com/util/osdiag
|
||||||
@ -291,8 +289,8 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
|
|||||||
tailscale.com/util/truncate from tailscale.com/logtail
|
tailscale.com/util/truncate from tailscale.com/logtail
|
||||||
tailscale.com/util/usermetric from tailscale.com/health+
|
tailscale.com/util/usermetric from tailscale.com/health+
|
||||||
tailscale.com/util/vizerror from tailscale.com/tailcfg+
|
tailscale.com/util/vizerror from tailscale.com/tailcfg+
|
||||||
💣 tailscale.com/util/winutil from tailscale.com/clientupdate+
|
💣 tailscale.com/util/winutil from tailscale.com/hostinfo+
|
||||||
W 💣 tailscale.com/util/winutil/authenticode from tailscale.com/clientupdate+
|
W 💣 tailscale.com/util/winutil/authenticode from tailscale.com/util/osdiag
|
||||||
W 💣 tailscale.com/util/winutil/gp from tailscale.com/net/dns+
|
W 💣 tailscale.com/util/winutil/gp from tailscale.com/net/dns+
|
||||||
W tailscale.com/util/winutil/policy from tailscale.com/ipn/ipnlocal
|
W tailscale.com/util/winutil/policy from tailscale.com/ipn/ipnlocal
|
||||||
W 💣 tailscale.com/util/winutil/winenv from tailscale.com/hostinfo+
|
W 💣 tailscale.com/util/winutil/winenv from tailscale.com/hostinfo+
|
||||||
@ -329,7 +327,7 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
|
|||||||
golang.org/x/crypto/salsa20/salsa from golang.org/x/crypto/nacl/box+
|
golang.org/x/crypto/salsa20/salsa from golang.org/x/crypto/nacl/box+
|
||||||
LD golang.org/x/crypto/ssh from tailscale.com/ipn/ipnlocal
|
LD golang.org/x/crypto/ssh from tailscale.com/ipn/ipnlocal
|
||||||
LD golang.org/x/crypto/ssh/internal/bcrypt_pbkdf from golang.org/x/crypto/ssh
|
LD golang.org/x/crypto/ssh/internal/bcrypt_pbkdf from golang.org/x/crypto/ssh
|
||||||
golang.org/x/exp/constraints from github.com/dblohm7/wingoes/pe+
|
golang.org/x/exp/constraints from tailscale.com/tsweb/varz+
|
||||||
golang.org/x/exp/maps from tailscale.com/ipn/store/mem+
|
golang.org/x/exp/maps from tailscale.com/ipn/store/mem+
|
||||||
golang.org/x/net/bpf from github.com/mdlayher/genetlink+
|
golang.org/x/net/bpf from github.com/mdlayher/genetlink+
|
||||||
golang.org/x/net/dns/dnsmessage from net+
|
golang.org/x/net/dns/dnsmessage from net+
|
||||||
@ -364,9 +362,8 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
|
|||||||
golang.org/x/text/unicode/bidi from golang.org/x/net/idna+
|
golang.org/x/text/unicode/bidi from golang.org/x/net/idna+
|
||||||
golang.org/x/text/unicode/norm from golang.org/x/net/idna
|
golang.org/x/text/unicode/norm from golang.org/x/net/idna
|
||||||
golang.org/x/time/rate from gvisor.dev/gvisor/pkg/log+
|
golang.org/x/time/rate from gvisor.dev/gvisor/pkg/log+
|
||||||
archive/tar from tailscale.com/clientupdate
|
|
||||||
bufio from compress/flate+
|
bufio from compress/flate+
|
||||||
bytes from archive/tar+
|
bytes from bufio+
|
||||||
cmp from encoding/json+
|
cmp from encoding/json+
|
||||||
compress/flate from compress/gzip+
|
compress/flate from compress/gzip+
|
||||||
compress/gzip from golang.org/x/net/http2+
|
compress/gzip from golang.org/x/net/http2+
|
||||||
@ -439,7 +436,7 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
|
|||||||
crypto/x509 from crypto/tls+
|
crypto/x509 from crypto/tls+
|
||||||
DI crypto/x509/internal/macos from crypto/x509
|
DI crypto/x509/internal/macos from crypto/x509
|
||||||
crypto/x509/pkix from crypto/x509+
|
crypto/x509/pkix from crypto/x509+
|
||||||
DWI database/sql/driver from github.com/google/uuid
|
DI database/sql/driver from github.com/google/uuid
|
||||||
W debug/dwarf from debug/pe
|
W debug/dwarf from debug/pe
|
||||||
W debug/pe from github.com/dblohm7/wingoes/pe
|
W debug/pe from github.com/dblohm7/wingoes/pe
|
||||||
embed from github.com/tailscale/web-client-prebuilt+
|
embed from github.com/tailscale/web-client-prebuilt+
|
||||||
@ -452,11 +449,11 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
|
|||||||
encoding/json from expvar+
|
encoding/json from expvar+
|
||||||
encoding/pem from crypto/tls+
|
encoding/pem from crypto/tls+
|
||||||
encoding/xml from github.com/tailscale/goupnp+
|
encoding/xml from github.com/tailscale/goupnp+
|
||||||
errors from archive/tar+
|
errors from bufio+
|
||||||
expvar from tailscale.com/health+
|
expvar from tailscale.com/health+
|
||||||
flag from tailscale.com/util/testenv
|
flag from tailscale.com/util/testenv
|
||||||
fmt from archive/tar+
|
fmt from compress/flate+
|
||||||
hash from compress/zlib+
|
hash from crypto+
|
||||||
W hash/adler32 from compress/zlib
|
W hash/adler32 from compress/zlib
|
||||||
hash/crc32 from compress/gzip+
|
hash/crc32 from compress/gzip+
|
||||||
hash/maphash from go4.org/mem
|
hash/maphash from go4.org/mem
|
||||||
@ -473,7 +470,7 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
|
|||||||
internal/filepathlite from os+
|
internal/filepathlite from os+
|
||||||
internal/fmtsort from fmt+
|
internal/fmtsort from fmt+
|
||||||
internal/goarch from crypto/internal/fips140deps/cpu+
|
internal/goarch from crypto/internal/fips140deps/cpu+
|
||||||
internal/godebug from archive/tar+
|
internal/godebug from crypto/internal/fips140deps/godebug+
|
||||||
internal/godebugs from internal/godebug+
|
internal/godebugs from internal/godebug+
|
||||||
internal/goexperiment from hash/maphash+
|
internal/goexperiment from hash/maphash+
|
||||||
internal/goos from crypto/x509+
|
internal/goos from crypto/x509+
|
||||||
@ -509,14 +506,14 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
|
|||||||
internal/testlog from os
|
internal/testlog from os
|
||||||
internal/trace/tracev2 from runtime+
|
internal/trace/tracev2 from runtime+
|
||||||
internal/unsafeheader from internal/reflectlite+
|
internal/unsafeheader from internal/reflectlite+
|
||||||
io from archive/tar+
|
io from bufio+
|
||||||
io/fs from archive/tar+
|
io/fs from crypto/x509+
|
||||||
io/ioutil from github.com/digitalocean/go-smbios/smbios+
|
io/ioutil from github.com/digitalocean/go-smbios/smbios+
|
||||||
iter from bytes+
|
iter from bytes+
|
||||||
log from expvar+
|
log from expvar+
|
||||||
log/internal from log
|
log/internal from log
|
||||||
maps from archive/tar+
|
maps from crypto/x509+
|
||||||
math from archive/tar+
|
math from compress/flate+
|
||||||
math/big from crypto/dsa+
|
math/big from crypto/dsa+
|
||||||
math/bits from bytes+
|
math/bits from bytes+
|
||||||
math/rand from github.com/fxamacker/cbor/v2+
|
math/rand from github.com/fxamacker/cbor/v2+
|
||||||
@ -537,28 +534,28 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
|
|||||||
net/url from crypto/x509+
|
net/url from crypto/x509+
|
||||||
os from crypto/internal/sysrand+
|
os from crypto/internal/sysrand+
|
||||||
os/exec from github.com/godbus/dbus/v5+
|
os/exec from github.com/godbus/dbus/v5+
|
||||||
os/user from archive/tar+
|
os/user from github.com/godbus/dbus/v5+
|
||||||
path from archive/tar+
|
path from debug/dwarf+
|
||||||
path/filepath from archive/tar+
|
path/filepath from crypto/x509+
|
||||||
reflect from archive/tar+
|
reflect from crypto/x509+
|
||||||
regexp from github.com/tailscale/goupnp/httpu+
|
regexp from github.com/tailscale/goupnp/httpu+
|
||||||
regexp/syntax from regexp
|
regexp/syntax from regexp
|
||||||
runtime from archive/tar+
|
runtime from crypto/internal/fips140+
|
||||||
runtime/debug from github.com/coder/websocket/internal/xsync+
|
runtime/debug from github.com/coder/websocket/internal/xsync+
|
||||||
runtime/pprof from net/http/pprof+
|
runtime/pprof from net/http/pprof+
|
||||||
runtime/trace from net/http/pprof
|
runtime/trace from net/http/pprof
|
||||||
slices from archive/tar+
|
slices from crypto/tls+
|
||||||
sort from compress/flate+
|
sort from compress/flate+
|
||||||
strconv from archive/tar+
|
strconv from compress/flate+
|
||||||
strings from archive/tar+
|
strings from bufio+
|
||||||
W structs from internal/syscall/windows
|
W structs from internal/syscall/windows
|
||||||
sync from archive/tar+
|
sync from compress/flate+
|
||||||
sync/atomic from context+
|
sync/atomic from context+
|
||||||
syscall from archive/tar+
|
syscall from crypto/internal/sysrand+
|
||||||
text/tabwriter from runtime/pprof
|
text/tabwriter from runtime/pprof
|
||||||
LDW text/template from html/template
|
LDW text/template from html/template
|
||||||
LDW text/template/parse from html/template+
|
LDW text/template/parse from html/template+
|
||||||
time from archive/tar+
|
time from compress/gzip+
|
||||||
unicode from bytes+
|
unicode from bytes+
|
||||||
unicode/utf16 from crypto/x509+
|
unicode/utf16 from crypto/x509+
|
||||||
unicode/utf8 from bufio+
|
unicode/utf8 from bufio+
|
||||||
|
@ -33,8 +33,9 @@ import (
|
|||||||
"go4.org/mem"
|
"go4.org/mem"
|
||||||
"tailscale.com/client/local"
|
"tailscale.com/client/local"
|
||||||
"tailscale.com/client/tailscale"
|
"tailscale.com/client/tailscale"
|
||||||
"tailscale.com/clientupdate"
|
|
||||||
"tailscale.com/cmd/testwrapper/flakytest"
|
"tailscale.com/cmd/testwrapper/flakytest"
|
||||||
|
"tailscale.com/feature"
|
||||||
|
_ "tailscale.com/feature/clientupdate"
|
||||||
"tailscale.com/hostinfo"
|
"tailscale.com/hostinfo"
|
||||||
"tailscale.com/ipn"
|
"tailscale.com/ipn"
|
||||||
"tailscale.com/net/tsaddr"
|
"tailscale.com/net/tsaddr"
|
||||||
@ -1125,7 +1126,7 @@ func TestLogoutRemovesAllPeers(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAutoUpdateDefaults(t *testing.T) {
|
func TestAutoUpdateDefaults(t *testing.T) {
|
||||||
if !clientupdate.CanAutoUpdate() {
|
if !feature.CanAutoUpdate() {
|
||||||
t.Skip("auto-updates not supported on this platform")
|
t.Skip("auto-updates not supported on this platform")
|
||||||
}
|
}
|
||||||
tstest.Shard(t)
|
tstest.Shard(t)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user