cobra/doc/md_docs_test.go

126 lines
3.5 KiB
Go
Raw Normal View History

2023-03-05 19:28:31 -07:00
// Copyright 2013-2023 The Cobra Authors
2022-09-16 04:55:56 -07:00
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package doc
Auto generation of markdown docs! An example from the kubernetes project, for the `kubectl config` command, which as subcommands, and flags, and all sorts of stuff, it will generate markdown like so: config modifies .kubeconfig files config modifies .kubeconfig files using subcommands like "kubectl config set current-context my-context" ``` kubectl config SUBCOMMAND ``` ``` --envvar=false: use the .kubeconfig from $KUBECONFIG --global=false: use the .kubeconfig from /home/username -h, --help=false: help for config --kubeconfig="": use a particular .kubeconfig file --local=false: use the .kubeconfig in the current directory ``` ``` --alsologtostderr=false: log to standard error as well as files --api-version="": The API version to use when talking to the server -a, --auth-path="": Path to the auth info file. If missing, prompt the user. Only used if using https. --certificate-authority="": Path to a cert. file for the certificate authority. --client-certificate="": Path to a client key file for TLS. --client-key="": Path to a client key file for TLS. --cluster="": The name of the kubeconfig cluster to use --context="": The name of the kubeconfig context to use --insecure-skip-tls-verify=false: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure. --log_backtrace_at=:0: when logging hits line file:N, emit a stack trace --log_dir=: If non-empty, write log files in this directory --log_flush_frequency=5s: Maximum number of seconds between log flushes --logtostderr=true: log to standard error instead of files --match-server-version=false: Require server version to match client version --namespace="": If present, the namespace scope for this CLI request. --password="": Password for basic authentication to the API server. -s, --server="": The address and port of the Kubernetes API server --stderrthreshold=2: logs at or above this threshold go to stderr --token="": Bearer token for authentication to the API server. --user="": The name of the kubeconfig user to use --username="": Username for basic authentication to the API server. --v=0: log level for V logs --validate=false: If true, use a schema to validate the input before sending it --vmodule=: comma-separated list of pattern=N settings for file-filtered logging ``` * [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager * [kubectl config set](kubectl_config_set.md) - Sets an individual value in a .kubeconfig file * [kubectl config set-cluster](kubectl_config_set-cluster.md) - Sets a cluster entry in .kubeconfig * [kubectl config set-context](kubectl_config_set-context.md) - Sets a context entry in .kubeconfig * [kubectl config set-credentials](kubectl_config_set-credentials.md) - Sets a user entry in .kubeconfig * [kubectl config unset](kubectl_config_unset.md) - Unsets an individual value in a .kubeconfig file * [kubectl config use-context](kubectl_config_use-context.md) - Sets the current-context in a .kubeconfig file * [kubectl config view](kubectl_config_view.md) - displays merged .kubeconfig settings or a specified .kubeconfig file.
2015-04-06 20:38:51 -07:00
import (
"bytes"
"os"
"path/filepath"
Auto generation of markdown docs! An example from the kubernetes project, for the `kubectl config` command, which as subcommands, and flags, and all sorts of stuff, it will generate markdown like so: config modifies .kubeconfig files config modifies .kubeconfig files using subcommands like "kubectl config set current-context my-context" ``` kubectl config SUBCOMMAND ``` ``` --envvar=false: use the .kubeconfig from $KUBECONFIG --global=false: use the .kubeconfig from /home/username -h, --help=false: help for config --kubeconfig="": use a particular .kubeconfig file --local=false: use the .kubeconfig in the current directory ``` ``` --alsologtostderr=false: log to standard error as well as files --api-version="": The API version to use when talking to the server -a, --auth-path="": Path to the auth info file. If missing, prompt the user. Only used if using https. --certificate-authority="": Path to a cert. file for the certificate authority. --client-certificate="": Path to a client key file for TLS. --client-key="": Path to a client key file for TLS. --cluster="": The name of the kubeconfig cluster to use --context="": The name of the kubeconfig context to use --insecure-skip-tls-verify=false: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure. --log_backtrace_at=:0: when logging hits line file:N, emit a stack trace --log_dir=: If non-empty, write log files in this directory --log_flush_frequency=5s: Maximum number of seconds between log flushes --logtostderr=true: log to standard error instead of files --match-server-version=false: Require server version to match client version --namespace="": If present, the namespace scope for this CLI request. --password="": Password for basic authentication to the API server. -s, --server="": The address and port of the Kubernetes API server --stderrthreshold=2: logs at or above this threshold go to stderr --token="": Bearer token for authentication to the API server. --user="": The name of the kubeconfig user to use --username="": Username for basic authentication to the API server. --v=0: log level for V logs --validate=false: If true, use a schema to validate the input before sending it --vmodule=: comma-separated list of pattern=N settings for file-filtered logging ``` * [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager * [kubectl config set](kubectl_config_set.md) - Sets an individual value in a .kubeconfig file * [kubectl config set-cluster](kubectl_config_set-cluster.md) - Sets a cluster entry in .kubeconfig * [kubectl config set-context](kubectl_config_set-context.md) - Sets a context entry in .kubeconfig * [kubectl config set-credentials](kubectl_config_set-credentials.md) - Sets a user entry in .kubeconfig * [kubectl config unset](kubectl_config_unset.md) - Unsets an individual value in a .kubeconfig file * [kubectl config use-context](kubectl_config_use-context.md) - Sets the current-context in a .kubeconfig file * [kubectl config view](kubectl_config_view.md) - displays merged .kubeconfig settings or a specified .kubeconfig file.
2015-04-06 20:38:51 -07:00
"testing"
"github.com/spf13/cobra"
)
Auto generation of markdown docs! An example from the kubernetes project, for the `kubectl config` command, which as subcommands, and flags, and all sorts of stuff, it will generate markdown like so: config modifies .kubeconfig files config modifies .kubeconfig files using subcommands like "kubectl config set current-context my-context" ``` kubectl config SUBCOMMAND ``` ``` --envvar=false: use the .kubeconfig from $KUBECONFIG --global=false: use the .kubeconfig from /home/username -h, --help=false: help for config --kubeconfig="": use a particular .kubeconfig file --local=false: use the .kubeconfig in the current directory ``` ``` --alsologtostderr=false: log to standard error as well as files --api-version="": The API version to use when talking to the server -a, --auth-path="": Path to the auth info file. If missing, prompt the user. Only used if using https. --certificate-authority="": Path to a cert. file for the certificate authority. --client-certificate="": Path to a client key file for TLS. --client-key="": Path to a client key file for TLS. --cluster="": The name of the kubeconfig cluster to use --context="": The name of the kubeconfig context to use --insecure-skip-tls-verify=false: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure. --log_backtrace_at=:0: when logging hits line file:N, emit a stack trace --log_dir=: If non-empty, write log files in this directory --log_flush_frequency=5s: Maximum number of seconds between log flushes --logtostderr=true: log to standard error instead of files --match-server-version=false: Require server version to match client version --namespace="": If present, the namespace scope for this CLI request. --password="": Password for basic authentication to the API server. -s, --server="": The address and port of the Kubernetes API server --stderrthreshold=2: logs at or above this threshold go to stderr --token="": Bearer token for authentication to the API server. --user="": The name of the kubeconfig user to use --username="": Username for basic authentication to the API server. --v=0: log level for V logs --validate=false: If true, use a schema to validate the input before sending it --vmodule=: comma-separated list of pattern=N settings for file-filtered logging ``` * [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager * [kubectl config set](kubectl_config_set.md) - Sets an individual value in a .kubeconfig file * [kubectl config set-cluster](kubectl_config_set-cluster.md) - Sets a cluster entry in .kubeconfig * [kubectl config set-context](kubectl_config_set-context.md) - Sets a context entry in .kubeconfig * [kubectl config set-credentials](kubectl_config_set-credentials.md) - Sets a user entry in .kubeconfig * [kubectl config unset](kubectl_config_unset.md) - Unsets an individual value in a .kubeconfig file * [kubectl config use-context](kubectl_config_use-context.md) - Sets the current-context in a .kubeconfig file * [kubectl config view](kubectl_config_view.md) - displays merged .kubeconfig settings or a specified .kubeconfig file.
2015-04-06 20:38:51 -07:00
func TestGenMdDoc(t *testing.T) {
2017-11-02 08:22:38 -07:00
// We generate on subcommand so we have both subcommands and parents.
buf := new(bytes.Buffer)
if err := GenMarkdown(echoCmd, buf); err != nil {
t.Fatal(err)
}
2017-11-02 08:22:38 -07:00
output := buf.String()
checkStringContains(t, output, echoCmd.Long)
checkStringContains(t, output, echoCmd.Example)
checkStringContains(t, output, "boolone")
checkStringContains(t, output, "rootflag")
checkStringContains(t, output, rootCmd.Short)
checkStringContains(t, output, echoSubCmd.Short)
checkStringOmits(t, output, deprecatedCmd.Short)
checkStringContains(t, output, "Options inherited from parent commands")
}
func TestGenMdDocWithNoLongOrSynopsis(t *testing.T) {
// We generate on subcommand so we have both subcommands and parents.
buf := new(bytes.Buffer)
if err := GenMarkdown(dummyCmd, buf); err != nil {
t.Fatal(err)
}
output := buf.String()
checkStringContains(t, output, dummyCmd.Example)
checkStringContains(t, output, dummyCmd.Short)
checkStringContains(t, output, "Options inherited from parent commands")
checkStringOmits(t, output, "### Synopsis")
}
func TestGenMdNoHiddenParents(t *testing.T) {
// We generate on subcommand so we have both subcommands and parents.
for _, name := range []string{"rootflag", "strtwo"} {
f := rootCmd.PersistentFlags().Lookup(name)
f.Hidden = true
defer func() { f.Hidden = false }()
}
buf := new(bytes.Buffer)
if err := GenMarkdown(echoCmd, buf); err != nil {
t.Fatal(err)
}
output := buf.String()
checkStringContains(t, output, echoCmd.Long)
checkStringContains(t, output, echoCmd.Example)
checkStringContains(t, output, "boolone")
checkStringOmits(t, output, "rootflag")
checkStringContains(t, output, rootCmd.Short)
checkStringContains(t, output, echoSubCmd.Short)
checkStringOmits(t, output, deprecatedCmd.Short)
checkStringOmits(t, output, "Options inherited from parent commands")
Auto generation of markdown docs! An example from the kubernetes project, for the `kubectl config` command, which as subcommands, and flags, and all sorts of stuff, it will generate markdown like so: config modifies .kubeconfig files config modifies .kubeconfig files using subcommands like "kubectl config set current-context my-context" ``` kubectl config SUBCOMMAND ``` ``` --envvar=false: use the .kubeconfig from $KUBECONFIG --global=false: use the .kubeconfig from /home/username -h, --help=false: help for config --kubeconfig="": use a particular .kubeconfig file --local=false: use the .kubeconfig in the current directory ``` ``` --alsologtostderr=false: log to standard error as well as files --api-version="": The API version to use when talking to the server -a, --auth-path="": Path to the auth info file. If missing, prompt the user. Only used if using https. --certificate-authority="": Path to a cert. file for the certificate authority. --client-certificate="": Path to a client key file for TLS. --client-key="": Path to a client key file for TLS. --cluster="": The name of the kubeconfig cluster to use --context="": The name of the kubeconfig context to use --insecure-skip-tls-verify=false: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure. --log_backtrace_at=:0: when logging hits line file:N, emit a stack trace --log_dir=: If non-empty, write log files in this directory --log_flush_frequency=5s: Maximum number of seconds between log flushes --logtostderr=true: log to standard error instead of files --match-server-version=false: Require server version to match client version --namespace="": If present, the namespace scope for this CLI request. --password="": Password for basic authentication to the API server. -s, --server="": The address and port of the Kubernetes API server --stderrthreshold=2: logs at or above this threshold go to stderr --token="": Bearer token for authentication to the API server. --user="": The name of the kubeconfig user to use --username="": Username for basic authentication to the API server. --v=0: log level for V logs --validate=false: If true, use a schema to validate the input before sending it --vmodule=: comma-separated list of pattern=N settings for file-filtered logging ``` * [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager * [kubectl config set](kubectl_config_set.md) - Sets an individual value in a .kubeconfig file * [kubectl config set-cluster](kubectl_config_set-cluster.md) - Sets a cluster entry in .kubeconfig * [kubectl config set-context](kubectl_config_set-context.md) - Sets a context entry in .kubeconfig * [kubectl config set-credentials](kubectl_config_set-credentials.md) - Sets a user entry in .kubeconfig * [kubectl config unset](kubectl_config_unset.md) - Unsets an individual value in a .kubeconfig file * [kubectl config use-context](kubectl_config_use-context.md) - Sets the current-context in a .kubeconfig file * [kubectl config view](kubectl_config_view.md) - displays merged .kubeconfig settings or a specified .kubeconfig file.
2015-04-06 20:38:51 -07:00
}
func TestGenMdNoTag(t *testing.T) {
2017-11-02 08:22:38 -07:00
rootCmd.DisableAutoGenTag = true
defer func() { rootCmd.DisableAutoGenTag = false }()
2017-11-02 08:22:38 -07:00
buf := new(bytes.Buffer)
if err := GenMarkdown(rootCmd, buf); err != nil {
t.Fatal(err)
}
2017-11-02 08:22:38 -07:00
output := buf.String()
2017-11-02 08:22:38 -07:00
checkStringOmits(t, output, "Auto generated")
}
func TestGenMdTree(t *testing.T) {
2017-11-02 08:22:38 -07:00
c := &cobra.Command{Use: "do [OPTIONS] arg1 arg2"}
tmpdir, err := os.MkdirTemp("", "test-gen-md-tree")
if err != nil {
2017-11-02 08:22:38 -07:00
t.Fatalf("Failed to create tmpdir: %v", err)
}
defer os.RemoveAll(tmpdir)
2017-11-02 08:22:38 -07:00
if err := GenMarkdownTree(c, tmpdir); err != nil {
t.Fatalf("GenMarkdownTree failed: %v", err)
}
if _, err := os.Stat(filepath.Join(tmpdir, "do.md")); err != nil {
t.Fatalf("Expected file 'do.md' to exist")
}
}
func BenchmarkGenMarkdownToFile(b *testing.B) {
file, err := os.CreateTemp("", "")
if err != nil {
b.Fatal(err)
}
defer os.Remove(file.Name())
defer file.Close()
b.ResetTimer()
for i := 0; i < b.N; i++ {
2017-11-02 08:22:38 -07:00
if err := GenMarkdown(rootCmd, file); err != nil {
b.Fatal(err)
}
}
}