cmd/tailscale/cli/jsonoutput: improve doc comments and add examples (#19993)
This patch: 1. Removes hardcoded mentions of a `--json` flag from the documentation for JSONSchemaVersion, because the type could be used for anything. 2. Removes `code` formatting because Go doc comments don’t support this syntax. 3. Fixes [links] in doc comments so they link to the types’ online documentation. 4. Checks that JSONSchemaVersion satisfies the flag.Value interface. 5. Adds documentation examples for using both JSONSchemaVersion and ResponseEnvelope. Updates #17613 Updates #18750 Signed-off-by: Simon Law <sfllaw@tailscale.com>
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
package jsonoutput
|
package jsonoutput
|
||||||
|
|
||||||
// DNSResolverInfo is the JSON form of [dnstype.Resolver].
|
// DNSResolverInfo is the JSON form of [tailscale.com/types/dnstype.Resolver].
|
||||||
type DNSResolverInfo struct {
|
type DNSResolverInfo struct {
|
||||||
// Addr is a plain IP, IP:port, DoH URL, or HTTP-over-WireGuard URL.
|
// Addr is a plain IP, IP:port, DoH URL, or HTTP-over-WireGuard URL.
|
||||||
Addr string
|
Addr string
|
||||||
@@ -13,7 +13,7 @@ type DNSResolverInfo struct {
|
|||||||
BootstrapResolution []string `json:",omitempty"`
|
BootstrapResolution []string `json:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DNSExtraRecord is the JSON form of [tailcfg.DNSRecord].
|
// DNSExtraRecord is the JSON form of [tailscale.com/tailcfg.DNSRecord].
|
||||||
type DNSExtraRecord struct {
|
type DNSExtraRecord struct {
|
||||||
Name string
|
Name string
|
||||||
Type string `json:",omitempty"` // empty means A or AAAA, depending on Value
|
Type string `json:",omitempty"` // empty means A or AAAA, depending on Value
|
||||||
@@ -21,7 +21,7 @@ type DNSExtraRecord struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DNSSystemConfig is the OS DNS configuration as observed by Tailscale,
|
// DNSSystemConfig is the OS DNS configuration as observed by Tailscale,
|
||||||
// mirroring [net/dns.OSConfig].
|
// mirroring [tailscale.com/net/dns.OSConfig].
|
||||||
type DNSSystemConfig struct {
|
type DNSSystemConfig struct {
|
||||||
Nameservers []string `json:",omitzero"`
|
Nameservers []string `json:",omitzero"`
|
||||||
SearchDomains []string `json:",omitzero"`
|
SearchDomains []string `json:",omitzero"`
|
||||||
@@ -33,7 +33,8 @@ type DNSSystemConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DNSTailnetInfo describes MagicDNS configuration for the tailnet,
|
// DNSTailnetInfo describes MagicDNS configuration for the tailnet,
|
||||||
// combining [ipnstate.TailnetStatus] and [ipnstate.PeerStatus].
|
// combining [tailscale.com/ipn/ipnstate.TailnetStatus]
|
||||||
|
// and [tailscale.com/ipn/ipnstate.PeerStatus].
|
||||||
type DNSTailnetInfo struct {
|
type DNSTailnetInfo struct {
|
||||||
// MagicDNSEnabled is whether MagicDNS is enabled for the
|
// MagicDNSEnabled is whether MagicDNS is enabled for the
|
||||||
// tailnet. The device may still not use it if
|
// tailnet. The device may still not use it if
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
// Copyright (c) Tailscale Inc & contributors
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
package jsonoutput_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"tailscale.com/cmd/tailscale/cli/jsonoutput"
|
||||||
|
)
|
||||||
|
|
||||||
|
var args struct {
|
||||||
|
json jsonoutput.JSONSchemaVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleJSONSchemaVersion() {
|
||||||
|
fs := flag.NewFlagSet("ExampleJSONSchemaVersion", flag.ExitOnError)
|
||||||
|
fs.Var(&args.json, "json", "output in JSON format")
|
||||||
|
|
||||||
|
fs.Parse([]string{"-json=2"})
|
||||||
|
fmt.Printf(`{set: %t, value: %d}`, args.json.IsSet, args.json.Value)
|
||||||
|
// Output:
|
||||||
|
// {set: true, value: 2}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
// Copyright (c) Tailscale Inc & contributors
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
package jsonoutput_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"tailscale.com/cmd/tailscale/cli/jsonoutput"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Hello struct {
|
||||||
|
jsonoutput.ResponseEnvelope
|
||||||
|
Greeting string
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleResponseEnvelope() {
|
||||||
|
hi := Hello{
|
||||||
|
ResponseEnvelope: jsonoutput.ResponseEnvelope{SchemaVersion: "1"},
|
||||||
|
Greeting: "Hello, world",
|
||||||
|
}
|
||||||
|
out, err := json.MarshalIndent(hi, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Printf("%s\n", out)
|
||||||
|
// Output:
|
||||||
|
// {
|
||||||
|
// "SchemaVersion": "1",
|
||||||
|
// "Greeting": "Hello, world"
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -5,32 +5,40 @@
|
|||||||
// This allows us to provide stable output to scripts/clients, but also make
|
// This allows us to provide stable output to scripts/clients, but also make
|
||||||
// breaking changes to the output when it's useful.
|
// breaking changes to the output when it's useful.
|
||||||
//
|
//
|
||||||
// Historically we only used `--json` as a boolean flag, so changing the output
|
// Historically we only used a boolean -json flag, so changing the output
|
||||||
// could break scripts that rely on the existing format.
|
// could break scripts that rely on the existing format.
|
||||||
//
|
//
|
||||||
// This package allows callers to pass a version number to `--json` and get
|
// This package provides a [JSONSchemaVersion] flag type that allows callers
|
||||||
// a consistent output. We'll bump the version when we make a breaking change
|
// to pass either a boolean or a version number and get a consistent output.
|
||||||
// that's likely to break scripts that rely on the existing output, e.g. if
|
// We'll bump the version when we make a breaking change
|
||||||
// we remove a field or change the type/format.
|
// that's likely to break scripts that rely on the existing output,
|
||||||
//
|
// e.g. if we remove a field or change the type/format.
|
||||||
// Passing just the boolean flag `--json` will always return v1, to preserve
|
// Passing just the boolean flag will always return 1, to preserve
|
||||||
// compatibility with scripts written before we versioned our output.
|
// compatibility with scripts written before we versioned our output.
|
||||||
|
//
|
||||||
|
// This package also provides [ResponseEnvelope] which is used to provide the
|
||||||
|
// set of fields common to all versioned JSON output.
|
||||||
package jsonoutput
|
package jsonoutput
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// JSONSchemaVersion implements flag.Value, and tracks whether the CLI has
|
var _ flag.Value = &JSONSchemaVersion{}
|
||||||
// been called with `--json`, and if so, with what value.
|
|
||||||
|
// JSONSchemaVersion implements the [flag.Value] interface,
|
||||||
|
// tracking whether the flag has been set or cleared, and its value when set.
|
||||||
type JSONSchemaVersion struct {
|
type JSONSchemaVersion struct {
|
||||||
// IsSet tracks if the flag was provided at all.
|
// IsSet tracks if the flag was set or cleared.
|
||||||
|
// This flag is true when set by -name or -name=true or -name=INT,
|
||||||
|
// otherwise it is false when cleared by -name=false.
|
||||||
IsSet bool
|
IsSet bool
|
||||||
|
|
||||||
// Value tracks the desired schema version, which defaults to 1 if
|
// Value tracks the desired schema version, as set by the -name=INT flag.
|
||||||
// the user passes `--json` without an argument.
|
// The version defaults to 1 when implicitly set by -name or -name=true.
|
||||||
Value int
|
Value int
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,8 +75,9 @@ func (v *JSONSchemaVersion) Set(s string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsBoolFlag tells the flag package that JSONSchemaVersion can be set
|
// IsBoolFlag reports that this [flag.Value] can be set without an argument.
|
||||||
// without an argument.
|
// This is the magic interface that makes -name equivalent to -name=true
|
||||||
|
// rather than using the next command-line argument.
|
||||||
func (v *JSONSchemaVersion) IsBoolFlag() bool {
|
func (v *JSONSchemaVersion) IsBoolFlag() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user