summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBrad Fitzpatrick <bradfitz@tailscale.com>2025-01-23 18:40:17 -0800
committerBrad Fitzpatrick <brad@danga.com>2025-01-23 18:51:16 -0800
commit61bea750928b291d5e7bca4ea87d64d503d8a7ac (patch)
treed47fa9bdbeb30c49d6244f6673a9a6a0fcb08a36
parentf0db47338e61dbf803cbfe3beba936282fa04c2a (diff)
downloadtailscale-61bea750928b291d5e7bca4ea87d64d503d8a7ac.tar.xz
tailscale-61bea750928b291d5e7bca4ea87d64d503d8a7ac.zip
cmd/tailscale: fix, test some recent doc inconsistencies
3dabea0fc2c added some docs with inconsistent usage docs. This fixes them, and adds a test. It also adds some other tests and fixes other verb tense inconsistencies. Updates tailscale/corp#25278 Change-Id: I94c2a8940791bddd7c35c1c3d5fb791a317370c2 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
-rw-r--r--cmd/tailscale/cli/cli_test.go43
-rw-r--r--cmd/tailscale/cli/configure_apple.go12
-rw-r--r--cmd/tailscale/cli/debug.go8
-rw-r--r--cmd/tailscale/cli/dns.go2
-rw-r--r--cmd/tailscale/cli/exitnode.go2
-rw-r--r--cmd/tailscale/cli/metrics.go4
-rw-r--r--cmd/tailscale/cli/network-lock.go19
-rw-r--r--cmd/tailscale/cli/switch.go2
-rw-r--r--cmd/tailscale/cli/syspolicy.go4
9 files changed, 68 insertions, 28 deletions
diff --git a/cmd/tailscale/cli/cli_test.go b/cmd/tailscale/cli/cli_test.go
index dccb69876..6f43814e8 100644
--- a/cmd/tailscale/cli/cli_test.go
+++ b/cmd/tailscale/cli/cli_test.go
@@ -17,6 +17,7 @@ import (
qt "github.com/frankban/quicktest"
"github.com/google/go-cmp/cmp"
+ "github.com/peterbourgon/ff/v3/ffcli"
"tailscale.com/envknob"
"tailscale.com/health/healthmsg"
"tailscale.com/ipn"
@@ -1525,3 +1526,45 @@ func TestHelpAlias(t *testing.T) {
t.Fatalf("Run: %v", err)
}
}
+
+func TestDocs(t *testing.T) {
+ root := newRootCmd()
+ check := func(t *testing.T, c *ffcli.Command) {
+ shortVerb, _, ok := strings.Cut(c.ShortHelp, " ")
+ if !ok || shortVerb == "" {
+ t.Errorf("couldn't find verb+space in ShortHelp")
+ } else {
+ if strings.HasSuffix(shortVerb, ".") {
+ t.Errorf("ShortHelp shouldn't end in period; got %q", c.ShortHelp)
+ }
+ if b := shortVerb[0]; b >= 'a' && b <= 'z' {
+ t.Errorf("ShortHelp should start with upper-case letter; got %q", c.ShortHelp)
+ }
+ if strings.HasSuffix(shortVerb, "s") && shortVerb != "Does" {
+ t.Errorf("verb %q ending in 's' is unexpected, from %q", shortVerb, c.ShortHelp)
+ }
+ }
+
+ name := t.Name()
+ wantPfx := strings.ReplaceAll(strings.TrimPrefix(name, "TestDocs/"), "/", " ")
+ switch name {
+ case "TestDocs/tailscale/completion/bash",
+ "TestDocs/tailscale/completion/zsh":
+ wantPfx = "" // special-case exceptions
+ }
+ if !strings.HasPrefix(c.ShortUsage, wantPfx) {
+ t.Errorf("ShortUsage should start with %q; got %q", wantPfx, c.ShortUsage)
+ }
+ }
+
+ var walk func(t *testing.T, c *ffcli.Command)
+ walk = func(t *testing.T, c *ffcli.Command) {
+ t.Run(c.Name, func(t *testing.T) {
+ check(t, c)
+ for _, sub := range c.Subcommands {
+ walk(t, sub)
+ }
+ })
+ }
+ walk(t, root)
+}
diff --git a/cmd/tailscale/cli/configure_apple.go b/cmd/tailscale/cli/configure_apple.go
index edd9ec1ab..c0d99b90a 100644
--- a/cmd/tailscale/cli/configure_apple.go
+++ b/cmd/tailscale/cli/configure_apple.go
@@ -27,28 +27,28 @@ func sysExtCmd() *ffcli.Command {
return &ffcli.Command{
Name: "sysext",
ShortUsage: "tailscale configure sysext [activate|deactivate|status]",
- ShortHelp: "Manages the system extension for macOS (Standalone variant)",
+ ShortHelp: "Manage the system extension for macOS (Standalone variant)",
LongHelp: "The sysext set of commands provides a way to activate, deactivate, or manage the state of the Tailscale system extension on macOS. " +
"This is only relevant if you are running the Standalone variant of the Tailscale client for macOS. " +
"To access more detailed information about system extensions installed on this Mac, run 'systemextensionsctl list'.",
Subcommands: []*ffcli.Command{
{
Name: "activate",
- ShortUsage: "tailscale sysext activate",
+ ShortUsage: "tailscale configure sysext activate",
ShortHelp: "Register the Tailscale system extension with macOS.",
LongHelp: "This command registers the Tailscale system extension with macOS. To run Tailscale, you'll also need to install the VPN configuration separately (run `tailscale configure vpn-config install`). After running this command, you need to approve the extension in System Settings > Login Items and Extensions > Network Extensions.",
Exec: requiresStandalone,
},
{
Name: "deactivate",
- ShortUsage: "tailscale sysext deactivate",
+ ShortUsage: "tailscale configure sysext deactivate",
ShortHelp: "Deactivate the Tailscale system extension on macOS",
LongHelp: "This command deactivates the Tailscale system extension on macOS. To completely remove Tailscale, you'll also need to delete the VPN configuration separately (use `tailscale configure vpn-config uninstall`).",
Exec: requiresStandalone,
},
{
Name: "status",
- ShortUsage: "tailscale sysext status",
+ ShortUsage: "tailscale configure sysext status",
ShortHelp: "Print the enablement status of the Tailscale system extension",
LongHelp: "This command prints the enablement status of the Tailscale system extension. If the extension is not enabled, run `tailscale sysext activate` to enable it.",
Exec: requiresStandalone,
@@ -69,14 +69,14 @@ func vpnConfigCmd() *ffcli.Command {
Subcommands: []*ffcli.Command{
{
Name: "install",
- ShortUsage: "tailscale mac-vpn install",
+ ShortUsage: "tailscale configure mac-vpn install",
ShortHelp: "Write the Tailscale VPN configuration to the macOS settings",
LongHelp: "This command writes the Tailscale VPN configuration to the macOS settings. This is the entry that appears in System Settings > VPN. If you are running the Standalone variant of the client, you'll also need to install the system extension separately (run `tailscale configure sysext activate`).",
Exec: requiresGUI,
},
{
Name: "uninstall",
- ShortUsage: "tailscale mac-vpn uninstall",
+ ShortUsage: "tailscale configure mac-vpn uninstall",
ShortHelp: "Delete the Tailscale VPN configuration from the macOS settings",
LongHelp: "This command removes the Tailscale VPN configuration from the macOS settings. This is the entry that appears in System Settings > VPN. If you are running the Standalone variant of the client, you'll also need to deactivate the system extension separately (run `tailscale configure sysext deactivate`).",
Exec: requiresGUI,
diff --git a/cmd/tailscale/cli/debug.go b/cmd/tailscale/cli/debug.go
index 04b343e76..f84dd25f0 100644
--- a/cmd/tailscale/cli/debug.go
+++ b/cmd/tailscale/cli/debug.go
@@ -289,7 +289,7 @@ var debugCmd = &ffcli.Command{
Name: "capture",
ShortUsage: "tailscale debug capture",
Exec: runCapture,
- ShortHelp: "Streams pcaps for debugging",
+ ShortHelp: "Stream pcaps for debugging",
FlagSet: (func() *flag.FlagSet {
fs := newFlagSet("capture")
fs.StringVar(&captureArgs.outFile, "o", "", "path to stream the pcap (or - for stdout), leave empty to start wireshark")
@@ -315,13 +315,13 @@ var debugCmd = &ffcli.Command{
Name: "peer-endpoint-changes",
ShortUsage: "tailscale debug peer-endpoint-changes <hostname-or-IP>",
Exec: runPeerEndpointChanges,
- ShortHelp: "Prints debug information about a peer's endpoint changes",
+ ShortHelp: "Print debug information about a peer's endpoint changes",
},
{
Name: "dial-types",
ShortUsage: "tailscale debug dial-types <hostname-or-IP> <port>",
Exec: runDebugDialTypes,
- ShortHelp: "Prints debug information about connecting to a given host or IP",
+ ShortHelp: "Print debug information about connecting to a given host or IP",
FlagSet: (func() *flag.FlagSet {
fs := newFlagSet("dial-types")
fs.StringVar(&debugDialTypesArgs.network, "network", "tcp", `network type to dial ("tcp", "udp", etc.)`)
@@ -342,7 +342,7 @@ var debugCmd = &ffcli.Command{
{
Name: "go-buildinfo",
ShortUsage: "tailscale debug go-buildinfo",
- ShortHelp: "Prints Go's runtime/debug.BuildInfo",
+ ShortHelp: "Print Go's runtime/debug.BuildInfo",
Exec: runGoBuildInfo,
},
},
diff --git a/cmd/tailscale/cli/dns.go b/cmd/tailscale/cli/dns.go
index 042ce1a94..402f0cedf 100644
--- a/cmd/tailscale/cli/dns.go
+++ b/cmd/tailscale/cli/dns.go
@@ -20,7 +20,7 @@ var dnsCmd = &ffcli.Command{
Name: "status",
ShortUsage: "tailscale dns status [--all]",
Exec: runDNSStatus,
- ShortHelp: "Prints the current DNS status and configuration",
+ ShortHelp: "Print the current DNS status and configuration",
LongHelp: dnsStatusLongHelp(),
FlagSet: (func() *flag.FlagSet {
fs := newFlagSet("status")
diff --git a/cmd/tailscale/cli/exitnode.go b/cmd/tailscale/cli/exitnode.go
index 941c6be8d..ad7a8ccee 100644
--- a/cmd/tailscale/cli/exitnode.go
+++ b/cmd/tailscale/cli/exitnode.go
@@ -41,7 +41,7 @@ func exitNodeCmd() *ffcli.Command {
{
Name: "suggest",
ShortUsage: "tailscale exit-node suggest",
- ShortHelp: "Suggests the best available exit node",
+ ShortHelp: "Suggest the best available exit node",
Exec: runExitNodeSuggest,
}},
(func() []*ffcli.Command {
diff --git a/cmd/tailscale/cli/metrics.go b/cmd/tailscale/cli/metrics.go
index d5fe9ad81..dbdedd5a6 100644
--- a/cmd/tailscale/cli/metrics.go
+++ b/cmd/tailscale/cli/metrics.go
@@ -33,13 +33,13 @@ https://tailscale.com/s/client-metrics
Name: "print",
ShortUsage: "tailscale metrics print",
Exec: runMetricsPrint,
- ShortHelp: "Prints current metric values in the Prometheus text exposition format",
+ ShortHelp: "Print current metric values in Prometheus text format",
},
{
Name: "write",
ShortUsage: "tailscale metrics write <path>",
Exec: runMetricsWrite,
- ShortHelp: "Writes metric values to a file",
+ ShortHelp: "Write metric values to a file",
LongHelp: strings.TrimSpace(`
The 'tailscale metrics write' command writes metric values to a text file provided as its
diff --git a/cmd/tailscale/cli/network-lock.go b/cmd/tailscale/cli/network-lock.go
index 45f989f10..c77767074 100644
--- a/cmd/tailscale/cli/network-lock.go
+++ b/cmd/tailscale/cli/network-lock.go
@@ -191,8 +191,7 @@ var nlStatusArgs struct {
var nlStatusCmd = &ffcli.Command{
Name: "status",
ShortUsage: "tailscale lock status",
- ShortHelp: "Outputs the state of tailnet lock",
- LongHelp: "Outputs the state of tailnet lock",
+ ShortHelp: "Output the state of tailnet lock",
Exec: runNetworkLockStatus,
FlagSet: (func() *flag.FlagSet {
fs := newFlagSet("lock status")
@@ -293,8 +292,7 @@ func runNetworkLockStatus(ctx context.Context, args []string) error {
var nlAddCmd = &ffcli.Command{
Name: "add",
ShortUsage: "tailscale lock add <public-key>...",
- ShortHelp: "Adds one or more trusted signing keys to tailnet lock",
- LongHelp: "Adds one or more trusted signing keys to tailnet lock",
+ ShortHelp: "Add one or more trusted signing keys to tailnet lock",
Exec: func(ctx context.Context, args []string) error {
return runNetworkLockModify(ctx, args, nil)
},
@@ -307,8 +305,7 @@ var nlRemoveArgs struct {
var nlRemoveCmd = &ffcli.Command{
Name: "remove",
ShortUsage: "tailscale lock remove [--re-sign=false] <public-key>...",
- ShortHelp: "Removes one or more trusted signing keys from tailnet lock",
- LongHelp: "Removes one or more trusted signing keys from tailnet lock",
+ ShortHelp: "Remove one or more trusted signing keys from tailnet lock",
Exec: runNetworkLockRemove,
FlagSet: (func() *flag.FlagSet {
fs := newFlagSet("lock remove")
@@ -448,7 +445,7 @@ func runNetworkLockModify(ctx context.Context, addArgs, removeArgs []string) err
var nlSignCmd = &ffcli.Command{
Name: "sign",
ShortUsage: "tailscale lock sign <node-key> [<rotation-key>]\ntailscale lock sign <auth-key>",
- ShortHelp: "Signs a node or pre-approved auth key",
+ ShortHelp: "Sign a node or pre-approved auth key",
LongHelp: `Either:
- signs a node key and transmits the signature to the coordination
server, or
@@ -510,7 +507,7 @@ func runNetworkLockSign(ctx context.Context, args []string) error {
var nlDisableCmd = &ffcli.Command{
Name: "disable",
ShortUsage: "tailscale lock disable <disablement-secret>",
- ShortHelp: "Consumes a disablement secret to shut down tailnet lock for the tailnet",
+ ShortHelp: "Consume a disablement secret to shut down tailnet lock for the tailnet",
LongHelp: strings.TrimSpace(`
The 'tailscale lock disable' command uses the specified disablement
@@ -539,7 +536,7 @@ func runNetworkLockDisable(ctx context.Context, args []string) error {
var nlLocalDisableCmd = &ffcli.Command{
Name: "local-disable",
ShortUsage: "tailscale lock local-disable",
- ShortHelp: "Disables tailnet lock for this node only",
+ ShortHelp: "Disable tailnet lock for this node only",
LongHelp: strings.TrimSpace(`
The 'tailscale lock local-disable' command disables tailnet lock for only
@@ -561,8 +558,8 @@ func runNetworkLockLocalDisable(ctx context.Context, args []string) error {
var nlDisablementKDFCmd = &ffcli.Command{
Name: "disablement-kdf",
ShortUsage: "tailscale lock disablement-kdf <hex-encoded-disablement-secret>",
- ShortHelp: "Computes a disablement value from a disablement secret (advanced users only)",
- LongHelp: "Computes a disablement value from a disablement secret (advanced users only)",
+ ShortHelp: "Compute a disablement value from a disablement secret (advanced users only)",
+ LongHelp: "Compute a disablement value from a disablement secret (advanced users only)",
Exec: runNetworkLockDisablementKDF,
}
diff --git a/cmd/tailscale/cli/switch.go b/cmd/tailscale/cli/switch.go
index 731492daa..af8b51326 100644
--- a/cmd/tailscale/cli/switch.go
+++ b/cmd/tailscale/cli/switch.go
@@ -20,7 +20,7 @@ import (
var switchCmd = &ffcli.Command{
Name: "switch",
ShortUsage: "tailscale switch <id>",
- ShortHelp: "Switches to a different Tailscale account",
+ ShortHelp: "Switch to a different Tailscale account",
LongHelp: `"tailscale switch" switches between logged in accounts. You can
use the ID that's returned from 'tailnet switch -list'
to pick which profile you want to switch to. Alternatively, you
diff --git a/cmd/tailscale/cli/syspolicy.go b/cmd/tailscale/cli/syspolicy.go
index 0e903db39..a71952a9f 100644
--- a/cmd/tailscale/cli/syspolicy.go
+++ b/cmd/tailscale/cli/syspolicy.go
@@ -31,7 +31,7 @@ var syspolicyCmd = &ffcli.Command{
Name: "list",
ShortUsage: "tailscale syspolicy list",
Exec: runSysPolicyList,
- ShortHelp: "Prints effective policy settings",
+ ShortHelp: "Print effective policy settings",
LongHelp: "The 'tailscale syspolicy list' subcommand displays the effective policy settings and their sources (e.g., MDM or environment variables).",
FlagSet: (func() *flag.FlagSet {
fs := newFlagSet("syspolicy list")
@@ -43,7 +43,7 @@ var syspolicyCmd = &ffcli.Command{
Name: "reload",
ShortUsage: "tailscale syspolicy reload",
Exec: runSysPolicyReload,
- ShortHelp: "Forces a reload of policy settings, even if no changes are detected, and prints the result",
+ ShortHelp: "Force a reload of policy settings, even if no changes are detected, and prints the result",
LongHelp: "The 'tailscale syspolicy reload' subcommand forces a reload of policy settings, even if no changes are detected, and prints the result.",
FlagSet: (func() *flag.FlagSet {
fs := newFlagSet("syspolicy reload")