cmd/tailscale/cli,ipn: mention available update in "tailscale status" (#9205)

Cache the last `ClientVersion` value that was received from coordination
server and pass it in the localapi `/status` response.
When running `tailscale status`, print a message if `RunningAsLatest` is
`false`.

Updates #6907

Signed-off-by: Andrew Lytvynov <awly@tailscale.com>
This commit is contained in:
Andrew Lytvynov 2023-09-08 14:27:49 -07:00 committed by GitHub
parent 1073b56e18
commit d23b8ffb13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 16 additions and 1 deletions

View File

@ -236,6 +236,9 @@ func runStatus(ctx context.Context, args []string) error {
printHealth() printHealth()
} }
printFunnelStatus(ctx) printFunnelStatus(ctx)
if cv := st.ClientVersion; cv != nil && !cv.RunningLatest && cv.LatestVersion != "" {
printf("# New Tailscale version is available: %q, run `tailscale update` to update.\n", cv.LatestVersion)
}
return nil return nil
} }

View File

@ -268,6 +268,9 @@ type LocalBackend struct {
// at the moment that tkaSyncLock is taken). // at the moment that tkaSyncLock is taken).
tkaSyncLock sync.Mutex tkaSyncLock sync.Mutex
clock tstime.Clock clock tstime.Clock
// Last ClientVersion received in MapResponse, guarded by mu.
lastClientVersion *tailcfg.ClientVersion
} }
type updateStatus struct { type updateStatus struct {
@ -671,6 +674,9 @@ func (b *LocalBackend) updateStatus(sb *ipnstate.StatusBuilder, extraLocked func
s.TUN = !b.sys.IsNetstack() s.TUN = !b.sys.IsNetstack()
s.BackendState = b.state.String() s.BackendState = b.state.String()
s.AuthURL = b.authURLSticky s.AuthURL = b.authURLSticky
if prefs := b.pm.CurrentPrefs(); prefs.Valid() && prefs.AutoUpdate().Check {
s.ClientVersion = b.lastClientVersion
}
if err := health.OverallError(); err != nil { if err := health.OverallError(); err != nil {
switch e := err.(type) { switch e := err.(type) {
case multierr.Error: case multierr.Error:
@ -2181,6 +2187,9 @@ func (b *LocalBackend) tellClientToBrowseToURL(url string) {
// onClientVersion is called on MapResponse updates when a MapResponse contains // onClientVersion is called on MapResponse updates when a MapResponse contains
// a non-nil ClientVersion message. // a non-nil ClientVersion message.
func (b *LocalBackend) onClientVersion(v *tailcfg.ClientVersion) { func (b *LocalBackend) onClientVersion(v *tailcfg.ClientVersion) {
b.mu.Lock()
b.lastClientVersion = v
b.mu.Unlock()
switch runtime.GOOS { switch runtime.GOOS {
case "darwin", "ios": case "darwin", "ios":
// These auto-update well enough, and we haven't converted the // These auto-update well enough, and we haven't converted the

View File

@ -71,6 +71,8 @@ type Status struct {
Peer map[key.NodePublic]*PeerStatus Peer map[key.NodePublic]*PeerStatus
User map[tailcfg.UserID]tailcfg.UserProfile User map[tailcfg.UserID]tailcfg.UserProfile
ClientVersion *tailcfg.ClientVersion
} }
// TKAKey describes a key trusted by network lock. // TKAKey describes a key trusted by network lock.

View File

@ -110,7 +110,8 @@
// - 70: 2023-08-16: removed most Debug fields; added NodeAttrDisable*, NodeAttrDebug* instead // - 70: 2023-08-16: removed most Debug fields; added NodeAttrDisable*, NodeAttrDebug* instead
// - 71: 2023-08-17: added NodeAttrOneCGNATEnable, NodeAttrOneCGNATDisable // - 71: 2023-08-17: added NodeAttrOneCGNATEnable, NodeAttrOneCGNATDisable
// - 72: 2023-08-23: TS-2023-006 UPnP issue fixed; UPnP can now be used again // - 72: 2023-08-23: TS-2023-006 UPnP issue fixed; UPnP can now be used again
const CurrentCapabilityVersion CapabilityVersion = 72 // - 73: 2023-09-01: Non-Windows clients expect to receive ClientVersion
const CurrentCapabilityVersion CapabilityVersion = 73
type StableID string type StableID string