diff --git a/client/tailscale/tailscale.go b/client/tailscale/tailscale.go index e5e22020a..e74c8b3fe 100644 --- a/client/tailscale/tailscale.go +++ b/client/tailscale/tailscale.go @@ -17,7 +17,6 @@ "net" "net/http" "net/url" - "os" "strconv" "strings" "time" @@ -86,6 +85,15 @@ func bestError(err error, body []byte) error { return err } +var onVersionMismatch func(clientVer, serverVer string) + +// SetVersionMismatchHandler sets f as the version mismatch handler +// to be called when the client (the current process) has a version +// number that doesn't match the server's declared version. +func SetVersionMismatchHandler(f func(clientVer, serverVer string)) { + onVersionMismatch = f +} + func send(ctx context.Context, method, path string, wantStatus int, body io.Reader) ([]byte, error) { req, err := http.NewRequestWithContext(ctx, method, "http://local-tailscaled.sock"+path, body) if err != nil { @@ -96,8 +104,8 @@ func send(ctx context.Context, method, path string, wantStatus int, body io.Read return nil, err } defer res.Body.Close() - if server := res.Header.Get("Tailscale-Version"); server != version.Long { - fmt.Fprintf(os.Stderr, "Warning: client version %q != tailscaled server version %q\n", version.Long, server) + if server := res.Header.Get("Tailscale-Version"); server != "" && server != version.Long && onVersionMismatch != nil { + onVersionMismatch(version.Long, server) } slurp, err := ioutil.ReadAll(res.Body) if err != nil { diff --git a/cmd/tailscale/cli/cli.go b/cmd/tailscale/cli/cli.go index 264a52691..8d38e89b9 100644 --- a/cmd/tailscale/cli/cli.go +++ b/cmd/tailscale/cli/cli.go @@ -19,6 +19,7 @@ "runtime" "strconv" "strings" + "sync" "syscall" "text/tabwriter" @@ -82,6 +83,13 @@ func Run(args []string) error { args = []string{"version"} } + var warnOnce sync.Once + tailscale.SetVersionMismatchHandler(func(clientVer, serverVer string) { + warnOnce.Do(func() { + fmt.Fprintf(os.Stderr, "Warning: client version %q != tailscaled server version %q\n", clientVer, serverVer) + }) + }) + rootfs := flag.NewFlagSet("tailscale", flag.ExitOnError) rootfs.StringVar(&rootArgs.socket, "socket", paths.DefaultTailscaledSocket(), "path to tailscaled's unix socket")