From be16cc0d3d62193c8541d77befb76def799bf2a8 Mon Sep 17 00:00:00 2001 From: Simon Law Date: Mon, 1 Jun 2026 10:25:33 -0700 Subject: [PATCH] =?UTF-8?q?cmd/tailscale/cli/jsonoutput:=20extract=20route?= =?UTF-8?q?check=E2=80=99s=20output=20format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In PR #19641, we added the `tailscale routecheck` command that supports both `--format=json` and `--format=json-line`. To allow other packages to import and unmarshal that JSON structure, this patch exports that format in a new tsroutecheckjsonv0 package. Updates #17366 Updates tailscale/corp#33033 Signed-off-by: Simon Law --- cmd/tailscale/cli/routecheck.go | 15 +++++----- cmd/tailscale/depaware.txt | 1 + .../tsroutecheckjsonv0/tsroutecheck.go | 28 +++++++++++++++++++ 3 files changed, 36 insertions(+), 8 deletions(-) create mode 100644 cmd/tailscale/tsroutecheckjsonv0/tsroutecheck.go diff --git a/cmd/tailscale/cli/routecheck.go b/cmd/tailscale/cli/routecheck.go index 679c174be..ade301c70 100644 --- a/cmd/tailscale/cli/routecheck.go +++ b/cmd/tailscale/cli/routecheck.go @@ -13,12 +13,13 @@ "slices" "strings" "text/tabwriter" - "time" jsonv2 "github.com/go-json-experiment/json" "github.com/go-json-experiment/json/jsontext" "github.com/peterbourgon/ff/v3/ffcli" + "tailscale.com/cmd/tailscale/cli/jsonoutput" + "tailscale.com/cmd/tailscale/tsroutecheckjsonv0" "tailscale.com/net/routecheck" "tailscale.com/tstime" ) @@ -41,13 +42,14 @@ func init() { var routecheckFlagSet = func() *flag.FlagSet { fs := newFlagSet("routecheck") fs.BoolVar(&routecheckArgs.probe, "probe", false, "probe now to generate a new reachability report") - fs.StringVar(&routecheckArgs.format, "format", "", `output format: empty (for human-readable), "json" or "json-line"`) + fs.Var(&routecheckArgs.format, "format", `output format: empty (for human-readable), "json" or "json-line"`) + fs.Var(routecheckArgs.format.JSONBool(), "json", "output in JSON format") return fs }() var routecheckArgs struct { probe bool - format string + format jsonoutput.Format } func runRoutecheck(ctx context.Context, args []string) error { @@ -67,7 +69,7 @@ func runRoutecheck(ctx context.Context, args []string) error { func printRouteCheckReport(rp *routecheck.Report) error { var enc *jsontext.Encoder - switch routecheckArgs.format { + switch routecheckArgs.format.String() { case "": case "json": enc = jsontext.NewEncoder(Stdout, jsontext.WithIndent("\t")) @@ -90,10 +92,7 @@ func printRouteCheckReport(rp *routecheck.Report) error { } if enc != nil { - out := struct { - Done time.Time `json:"done"` - Routes routecheck.RoutablePrefixes `json:"routes"` - }{ + out := tsroutecheckjsonv0.ReportResponse{ Done: rp.Done, Routes: routes, } diff --git a/cmd/tailscale/depaware.txt b/cmd/tailscale/depaware.txt index 0a61b4564..58760a804 100644 --- a/cmd/tailscale/depaware.txt +++ b/cmd/tailscale/depaware.txt @@ -184,6 +184,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep tailscale.com/cmd/tailscale/cli/ffcomplete from tailscale.com/cmd/tailscale/cli tailscale.com/cmd/tailscale/cli/ffcomplete/internal from tailscale.com/cmd/tailscale/cli/ffcomplete tailscale.com/cmd/tailscale/cli/jsonoutput from tailscale.com/cmd/tailscale/cli + tailscale.com/cmd/tailscale/tsroutecheckjsonv0 from tailscale.com/cmd/tailscale/cli tailscale.com/control/controlbase from tailscale.com/control/controlhttp+ tailscale.com/control/controlhttp from tailscale.com/control/ts2021 tailscale.com/control/controlhttp/controlhttpcommon from tailscale.com/control/controlhttp diff --git a/cmd/tailscale/tsroutecheckjsonv0/tsroutecheck.go b/cmd/tailscale/tsroutecheckjsonv0/tsroutecheck.go new file mode 100644 index 000000000..f9dd89348 --- /dev/null +++ b/cmd/tailscale/tsroutecheckjsonv0/tsroutecheck.go @@ -0,0 +1,28 @@ +// Copyright (c) Tailscale Inc & contributors +// SPDX-License-Identifier: BSD-3-Clause + +//go:build !ts_omit_routecheck + +// Package tsroutecheckjsonv0 provides types for unmarshalling the JSON output of the +// "tailscale routecheck --json" command: +// +// - [ReportResponse] will unmarshal the output of "tailscale routecheck --json" +// +// # WARNING: unstable +// +// Format is "v0" and is subject to change. +// There is no guarantee of backwards or forwards compatibility. +package tsroutecheckjsonv0 + +import ( + "time" + + "tailscale.com/net/routecheck" +) + +// ReportResponse is the JSON form of [routecheck.Report]. +// Experimental: This output is not yet stable: tailscale/tailscale#17366. +type ReportResponse struct { + Done time.Time `json:"done"` + Routes routecheck.RoutablePrefixes `json:"routes"` +}