From f57cc19ba2673ea07c2dd8465fb5535b4916d86a Mon Sep 17 00:00:00 2001 From: Andrew Lytvynov Date: Wed, 2 Aug 2023 08:24:18 -0700 Subject: [PATCH] cmd/tailscale/cli: add latest version output to "tailscale version" (#8700) Add optional `--upstream` flag to `tailscale version` to fetch the latest upstream release version from `pkgs.tailscale.com`. This is useful to diagnose `tailscale update` behavior or write other tooling. Example output: $ tailscale version --upstream --json { "majorMinorPatch": "1.47.35", "short": "1.47.35", "long": "1.47.35-t6afffece8", "unstableBranch": true, "gitCommit": "6afffece8a32509aa7a4dc2972415ec58d8316de", "cap": 66, "upstream": "1.45.61" } Fixes #8669 RELNOTE=adds "tailscale version --upstream" Signed-off-by: Andrew Lytvynov --- cmd/tailscale/cli/update.go | 4 ++++ cmd/tailscale/cli/version.go | 33 ++++++++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/cmd/tailscale/cli/update.go b/cmd/tailscale/cli/update.go index 3e9050cec..36b55b785 100644 --- a/cmd/tailscale/cli/update.go +++ b/cmd/tailscale/cli/update.go @@ -874,6 +874,10 @@ func requestedTailscaleVersion(ver, track string) (string, error) { if ver != "" { return ver, nil } + return latestTailscaleVersion(track) +} + +func latestTailscaleVersion(track string) (string, error) { url := fmt.Sprintf("https://pkgs.tailscale.com/%s/?mode=json&os=%s", track, runtime.GOOS) res, err := http.Get(url) if err != nil { diff --git a/cmd/tailscale/cli/version.go b/cmd/tailscale/cli/version.go index eed5bec63..89ccf6f1d 100644 --- a/cmd/tailscale/cli/version.go +++ b/cmd/tailscale/cli/version.go @@ -23,14 +23,16 @@ fs := newFlagSet("version") fs.BoolVar(&versionArgs.daemon, "daemon", false, "also print local node's daemon version") fs.BoolVar(&versionArgs.json, "json", false, "output in JSON format") + fs.BoolVar(&versionArgs.upstream, "upstream", false, "fetch and print the latest upstream release version from pkgs.tailscale.com") return fs })(), Exec: runVersion, } var versionArgs struct { - daemon bool // also check local node's daemon version - json bool + daemon bool // also check local node's daemon version + json bool + upstream bool } func runVersion(ctx context.Context, args []string) error { @@ -47,21 +49,46 @@ func runVersion(ctx context.Context, args []string) error { } } + var upstreamVer string + if versionArgs.upstream { + track := "stable" + if version.IsUnstableBuild() { + track = "unstable" + } + upstreamVer, err = latestTailscaleVersion(track) + if err != nil { + return err + } + } + if versionArgs.json { m := version.GetMeta() if st != nil { m.DaemonLong = st.Version } + out := struct { + version.Meta + Upstream string `json:"upstream,omitempty"` + }{ + Meta: m, + Upstream: upstreamVer, + } e := json.NewEncoder(os.Stdout) e.SetIndent("", "\t") - return e.Encode(m) + return e.Encode(out) } if st == nil { outln(version.String()) + if versionArgs.upstream { + printf(" upstream: %s\n", upstreamVer) + } return nil } printf("Client: %s\n", version.String()) printf("Daemon: %s\n", st.Version) + if versionArgs.upstream { + printf("Upstream: %s\n", upstreamVer) + } return nil }