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 <awly@tailscale.com>
pull/8775/head
Andrew Lytvynov 1 year ago committed by GitHub
parent b4c1f039b6
commit f57cc19ba2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -874,6 +874,10 @@ func requestedTailscaleVersion(ver, track string) (string, error) {
if ver != "" { if ver != "" {
return ver, nil 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) url := fmt.Sprintf("https://pkgs.tailscale.com/%s/?mode=json&os=%s", track, runtime.GOOS)
res, err := http.Get(url) res, err := http.Get(url)
if err != nil { if err != nil {

@ -23,14 +23,16 @@ var versionCmd = &ffcli.Command{
fs := newFlagSet("version") fs := newFlagSet("version")
fs.BoolVar(&versionArgs.daemon, "daemon", false, "also print local node's daemon 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.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 return fs
})(), })(),
Exec: runVersion, Exec: runVersion,
} }
var versionArgs struct { var versionArgs struct {
daemon bool // also check local node's daemon version daemon bool // also check local node's daemon version
json bool json bool
upstream bool
} }
func runVersion(ctx context.Context, args []string) error { 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 { if versionArgs.json {
m := version.GetMeta() m := version.GetMeta()
if st != nil { if st != nil {
m.DaemonLong = st.Version m.DaemonLong = st.Version
} }
out := struct {
version.Meta
Upstream string `json:"upstream,omitempty"`
}{
Meta: m,
Upstream: upstreamVer,
}
e := json.NewEncoder(os.Stdout) e := json.NewEncoder(os.Stdout)
e.SetIndent("", "\t") e.SetIndent("", "\t")
return e.Encode(m) return e.Encode(out)
} }
if st == nil { if st == nil {
outln(version.String()) outln(version.String())
if versionArgs.upstream {
printf(" upstream: %s\n", upstreamVer)
}
return nil return nil
} }
printf("Client: %s\n", version.String()) printf("Client: %s\n", version.String())
printf("Daemon: %s\n", st.Version) printf("Daemon: %s\n", st.Version)
if versionArgs.upstream {
printf("Upstream: %s\n", upstreamVer)
}
return nil return nil
} }

Loading…
Cancel
Save