diff --git a/commands/create.go b/commands/create.go index 4bd29c58..7dc27f27 100644 --- a/commands/create.go +++ b/commands/create.go @@ -13,6 +13,7 @@ import ( "github.com/docker/buildx/driver" "github.com/docker/buildx/store" "github.com/docker/buildx/store/storeutil" + "github.com/docker/buildx/util/cobrautil" "github.com/docker/cli/cli" "github.com/docker/cli/cli/command" "github.com/google/shlex" @@ -238,7 +239,8 @@ func createCmd(dockerCli command.Cli) *cobra.Command { flags.BoolVar(&options.actionLeave, "leave", false, "Remove a node from builder instead of changing it") flags.BoolVar(&options.use, "use", false, "Set the current builder instance") - _ = flags + // hide builder persistent flag for this command + cobrautil.HideInheritedFlags(cmd, "builder") return cmd } diff --git a/commands/imagetools/create.go b/commands/imagetools/create.go index cbcb84b1..c42d4715 100644 --- a/commands/imagetools/create.go +++ b/commands/imagetools/create.go @@ -261,7 +261,6 @@ func createCmd(dockerCli command.Cli, opts RootOptions) *cobra.Command { } flags := cmd.Flags() - flags.StringArrayVarP(&options.files, "file", "f", []string{}, "Read source descriptor from file") flags.StringArrayVarP(&options.tags, "tag", "t", []string{}, "Set reference for new image") flags.BoolVar(&options.dryrun, "dry-run", false, "Show final image instead of pushing") diff --git a/commands/imagetools/inspect.go b/commands/imagetools/inspect.go index 9f06793a..7a6892f3 100644 --- a/commands/imagetools/inspect.go +++ b/commands/imagetools/inspect.go @@ -85,7 +85,6 @@ func inspectCmd(dockerCli command.Cli, rootOpts RootOptions) *cobra.Command { } flags := cmd.Flags() - flags.BoolVar(&options.raw, "raw", false, "Show original JSON manifest") return cmd diff --git a/commands/inspect.go b/commands/inspect.go index 4e9e826e..ecb1c616 100644 --- a/commands/inspect.go +++ b/commands/inspect.go @@ -132,10 +132,7 @@ func inspectCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command { } flags := cmd.Flags() - flags.BoolVar(&options.bootstrap, "bootstrap", false, "Ensure builder has booted before inspecting") - _ = flags - return cmd } diff --git a/commands/install.go b/commands/install.go index 95cdc427..e760a749 100644 --- a/commands/install.go +++ b/commands/install.go @@ -3,6 +3,7 @@ package commands import ( "os" + "github.com/docker/buildx/util/cobrautil" "github.com/docker/cli/cli" "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/config" @@ -48,5 +49,8 @@ func installCmd(dockerCli command.Cli) *cobra.Command { Hidden: true, } + // hide builder persistent flag for this command + cobrautil.HideInheritedFlags(cmd, "builder") + return cmd } diff --git a/commands/ls.go b/commands/ls.go index efc20d5d..25c87782 100644 --- a/commands/ls.go +++ b/commands/ls.go @@ -11,6 +11,7 @@ import ( "github.com/docker/buildx/store" "github.com/docker/buildx/store/storeutil" + "github.com/docker/buildx/util/cobrautil" "github.com/docker/buildx/util/platformutil" "github.com/docker/cli/cli" "github.com/docker/cli/cli/command" @@ -148,5 +149,8 @@ func lsCmd(dockerCli command.Cli) *cobra.Command { }, } + // hide builder persistent flag for this command + cobrautil.HideInheritedFlags(cmd, "builder") + return cmd } diff --git a/commands/stop.go b/commands/stop.go index 43b6c570..a5fe5a45 100644 --- a/commands/stop.go +++ b/commands/stop.go @@ -62,12 +62,6 @@ func stopCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command { }, } - flags := cmd.Flags() - - // flags.StringArrayVarP(&options.outputs, "output", "o", []string{}, "Output destination (format: type=local,dest=path)") - - _ = flags - return cmd } diff --git a/commands/uninstall.go b/commands/uninstall.go index 0375f9c7..f5b000eb 100644 --- a/commands/uninstall.go +++ b/commands/uninstall.go @@ -3,6 +3,7 @@ package commands import ( "os" + "github.com/docker/buildx/util/cobrautil" "github.com/docker/cli/cli" "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/config" @@ -54,5 +55,8 @@ func uninstallCmd(dockerCli command.Cli) *cobra.Command { Hidden: true, } + // hide builder persistent flag for this command + cobrautil.HideInheritedFlags(cmd, "builder") + return cmd } diff --git a/commands/use.go b/commands/use.go index 425857a1..71320135 100644 --- a/commands/use.go +++ b/commands/use.go @@ -80,11 +80,8 @@ func useCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command { } flags := cmd.Flags() - flags.BoolVar(&options.isGlobal, "global", false, "Builder persists context changes") flags.BoolVar(&options.isDefault, "default", false, "Set builder as default for current context") - _ = flags - return cmd } diff --git a/commands/version.go b/commands/version.go index d0e8f395..91cfe136 100644 --- a/commands/version.go +++ b/commands/version.go @@ -3,6 +3,7 @@ package commands import ( "fmt" + "github.com/docker/buildx/util/cobrautil" "github.com/docker/buildx/version" "github.com/docker/cli/cli" "github.com/docker/cli/cli/command" @@ -23,5 +24,9 @@ func versionCmd(dockerCli command.Cli) *cobra.Command { return runVersion(dockerCli) }, } + + // hide builder persistent flag for this command + cobrautil.HideInheritedFlags(cmd, "builder") + return cmd } diff --git a/docs/generate.go b/docs/generate.go index 6caff755..dee56cc7 100644 --- a/docs/generate.go +++ b/docs/generate.go @@ -3,7 +3,6 @@ package main import ( "log" "os" - "path/filepath" "github.com/docker/buildx/commands" clidocstool "github.com/docker/cli-docs-tool" @@ -40,27 +39,28 @@ func gen(opts *options) error { } cmd.AddCommand(commands.NewRootCmd("buildx", true, dockerCLI)) - clidocstool.DisableFlagsInUseLine(cmd) - cwd, _ := os.Getwd() - source := filepath.Join(cwd, opts.source) - - if err = os.MkdirAll(source, 0755); err != nil { + c, err := clidocstool.New(clidocstool.Options{ + Root: cmd, + SourceDir: opts.source, + Plugin: true, + }) + if err != nil { return err } for _, format := range opts.formats { switch format { case "md": - if err = clidocstool.GenMarkdownTree(cmd, source); err != nil { + if err = c.GenMarkdownTree(cmd); err != nil { return err } case "yaml": - if err = clidocstool.GenYamlTree(cmd, source); err != nil { + if err = c.GenYamlTree(cmd); err != nil { return err } default: - return errors.Errorf("unknwown doc format %q", format) + return errors.Errorf("unknown format %q", format) } } diff --git a/docs/reference/buildx.md b/docs/reference/buildx.md index e797d9e2..1b385012 100644 --- a/docs/reference/buildx.md +++ b/docs/reference/buildx.md @@ -27,5 +27,17 @@ Extended build capabilities with BuildKit | [`version`](buildx_version.md) | Show buildx version information | +### Options + +| Name | Description | +| --- | --- | +| [`--builder string`](#builder) | Override the configured builder instance | + + +## Examples + +### Override the configured builder instance (--builder) + +You can also use the `BUILDX_BUILDER` environment variable. diff --git a/docs/reference/buildx_bake.md b/docs/reference/buildx_bake.md index a9e1a53e..0bb3f22f 100644 --- a/docs/reference/buildx_bake.md +++ b/docs/reference/buildx_bake.md @@ -15,7 +15,7 @@ Build from a file | Name | Description | | --- | --- | -| `--builder string` | Override the configured builder instance | +| [`--builder string`](#builder) | Override the configured builder instance | | [`-f`](#file), [`--file stringArray`](#file) | Build definition file | | `--load` | Shorthand for `--set=*.output=type=docker` | | `--metadata-file string` | Write build result metadata to the file | @@ -43,6 +43,10 @@ command and extending the functionality further. ## Examples +### Override the configured builder instance (--builder) + +Same as [`buildx --builder`](buildx.md#builder). + ### Specify a build definition file (-f, --file) By default, `buildx bake` looks for build definition files in the current diff --git a/docs/reference/buildx_build.md b/docs/reference/buildx_build.md index 7d139cd6..e426cd5c 100644 --- a/docs/reference/buildx_build.md +++ b/docs/reference/buildx_build.md @@ -18,7 +18,7 @@ Start a build | [`--add-host stringSlice`](https://docs.docker.com/engine/reference/commandline/build/#add-entries-to-container-hosts-file---add-host) | Add a custom host-to-IP mapping (format: `host:ip`) | | [`--allow stringSlice`](#allow) | Allow extra privileged entitlement (e.g., `network.host`, `security.insecure`) | | [`--build-arg stringArray`](https://docs.docker.com/engine/reference/commandline/build/#set-build-time-variables---build-arg) | Set build-time variables | -| `--builder string` | Override the configured builder instance | +| [`--builder string`](#builder) | Override the configured builder instance | | [`--cache-from stringArray`](#cache-from) | External cache sources (e.g., `user/app:cache`, `type=local,src=path/to/dir`) | | [`--cache-to stringArray`](#cache-to) | Cache export destinations (e.g., `user/app:cache`, `type=local,dest=path/to/dir`) | | [`--cgroup-parent string`](https://docs.docker.com/engine/reference/commandline/build/#use-a-custom-parent-cgroup---cgroup-parent) | Optional parent cgroup for the container | @@ -56,6 +56,10 @@ here we’ll document a subset of the new flags. ## Examples +### Override the configured builder instance (--builder) + +Same as [`buildx --builder`](buildx.md#builder). + ### Set the target platforms for the build (--platform) ``` diff --git a/docs/reference/buildx_create.md b/docs/reference/buildx_create.md index 8a1d189e..8c47ef2d 100644 --- a/docs/reference/buildx_create.md +++ b/docs/reference/buildx_create.md @@ -13,7 +13,6 @@ Create a new builder instance | --- | --- | | [`--append`](#append) | Append a node to builder instead of changing it | | `--bootstrap` | Boot builder after creation | -| `--builder string` | Override the configured builder instance | | [`--buildkitd-flags string`](#buildkitd-flags) | Flags for buildkitd daemon | | [`--config string`](#config) | BuildKit config file | | [`--driver string`](#driver) | Driver to use (available: `docker`, `docker-container`, `kubernetes`) | diff --git a/docs/reference/buildx_du.md b/docs/reference/buildx_du.md index 15da02b4..e44ce199 100644 --- a/docs/reference/buildx_du.md +++ b/docs/reference/buildx_du.md @@ -11,9 +11,15 @@ Disk usage | Name | Description | | --- | --- | -| `--builder string` | Override the configured builder instance | +| [`--builder string`](#builder) | Override the configured builder instance | | `--filter filter` | Provide filter values | | `--verbose` | Provide a more verbose output | - \ No newline at end of file + + +## Examples + +### Override the configured builder instance (--builder) + +Same as [`buildx --builder`](buildx.md#builder). diff --git a/docs/reference/buildx_imagetools.md b/docs/reference/buildx_imagetools.md index 3d6b42fb..e7992ff8 100644 --- a/docs/reference/buildx_imagetools.md +++ b/docs/reference/buildx_imagetools.md @@ -15,6 +15,12 @@ Commands to work on images in registry | [`inspect`](buildx_imagetools_inspect.md) | Show details of image in the registry | +### Options + +| Name | Description | +| --- | --- | +| [`--builder string`](#builder) | Override the configured builder instance | + @@ -22,3 +28,9 @@ Commands to work on images in registry Imagetools contains commands for working with manifest lists in the registry. These commands are useful for inspecting multi-platform build results. + +## Examples + +### Override the configured builder instance (--builder) + +Same as [`buildx --builder`](buildx.md#builder). diff --git a/docs/reference/buildx_imagetools_create.md b/docs/reference/buildx_imagetools_create.md index eee671a4..4251ad5e 100644 --- a/docs/reference/buildx_imagetools_create.md +++ b/docs/reference/buildx_imagetools_create.md @@ -12,7 +12,7 @@ Create a new image based on source images | Name | Description | | --- | --- | | [`--append`](#append) | Append to existing manifest | -| `--builder string` | Override the configured builder instance | +| [`--builder string`](#builder) | Override the configured builder instance | | [`--dry-run`](#dry-run) | Show final image instead of pushing | | [`-f`](#file), [`--file stringArray`](#file) | Read source descriptor from file | | [`-t`](#tag), [`--tag stringArray`](#tag) | Set reference for new image | @@ -37,6 +37,10 @@ specified, create performs a carbon copy. Use the `--append` flag to append the new sources to an existing manifest list in the destination. +### Override the configured builder instance (--builder) + +Same as [`buildx --builder`](buildx.md#builder). + ### Show final image instead of pushing (--dry-run) Use the `--dry-run` flag to not push the image, just show it. diff --git a/docs/reference/buildx_imagetools_inspect.md b/docs/reference/buildx_imagetools_inspect.md index e1af7a67..f6ea01ac 100644 --- a/docs/reference/buildx_imagetools_inspect.md +++ b/docs/reference/buildx_imagetools_inspect.md @@ -11,7 +11,7 @@ Show details of image in the registry | Name | Description | | --- | --- | -| `--builder string` | Override the configured builder instance | +| [`--builder string`](#builder) | Override the configured builder instance | | [`--raw`](#raw) | Show original JSON manifest | @@ -41,6 +41,12 @@ Manifests: ... ``` +## Examples + +### Override the configured builder instance (--builder) + +Same as [`buildx --builder`](buildx.md#builder). + ### Show original, unformatted JSON manifest (--raw) Use the `--raw` option to print the original JSON bytes instead of the formatted diff --git a/docs/reference/buildx_inspect.md b/docs/reference/buildx_inspect.md index 85e5d96b..b659bd91 100644 --- a/docs/reference/buildx_inspect.md +++ b/docs/reference/buildx_inspect.md @@ -12,7 +12,7 @@ Inspect current builder instance | Name | Description | | --- | --- | | [`--bootstrap`](#bootstrap) | Ensure builder has booted before inspecting | -| `--builder string` | Override the configured builder instance | +| [`--builder string`](#builder) | Override the configured builder instance | @@ -23,6 +23,19 @@ Shows information about the current or specified builder. ## Examples +### Ensure that the builder is running before inspecting (--bootstrap) + +Use the `--bootstrap` option to ensure that the builder is running before +inspecting it. If the driver is `docker-container`, then `--bootstrap` starts +the buildkit container and waits until it is operational. Bootstrapping is +automatically done during build, and therefore not necessary. The same BuildKit +container is used during the lifetime of the associated builder node (as +displayed in `buildx ls`). + +### Override the configured builder instance (--builder) + +Same as [`buildx --builder`](buildx.md#builder). + ### Get information about a builder instance By default, `inspect` shows information about the current builder. Specify the @@ -47,12 +60,3 @@ Endpoint: ssh://ubuntu@1.2.3.4 Status: running Platforms: linux/arm64, linux/arm/v7, linux/arm/v6 ``` - -### Ensure that the builder is running before inspecting (--bootstrap) - -Use the `--bootstrap` option to ensure that the builder is running before -inspecting it. If the driver is `docker-container`, then `--bootstrap` starts -the buildkit container and waits until it is operational. Bootstrapping is -automatically done during build, and therefore not necessary. The same BuildKit -container is used during the lifetime of the associated builder node (as -displayed in `buildx ls`). diff --git a/docs/reference/buildx_prune.md b/docs/reference/buildx_prune.md index a3a9cf5b..67a6d8c2 100644 --- a/docs/reference/buildx_prune.md +++ b/docs/reference/buildx_prune.md @@ -12,7 +12,7 @@ Remove build cache | Name | Description | | --- | --- | | `-a`, `--all` | Remove all unused images, not just dangling ones | -| `--builder string` | Override the configured builder instance | +| [`--builder string`](#builder) | Override the configured builder instance | | `--filter filter` | Provide filter values (e.g., `until=24h`) | | `-f`, `--force` | Do not prompt for confirmation | | `--keep-storage bytes` | Amount of disk space to keep for cache | @@ -21,3 +21,8 @@ Remove build cache +## Examples + +### Override the configured builder instance (--builder) + +Same as [`buildx --builder`](buildx.md#builder). diff --git a/docs/reference/buildx_rm.md b/docs/reference/buildx_rm.md index f846eb2a..8f4895a6 100644 --- a/docs/reference/buildx_rm.md +++ b/docs/reference/buildx_rm.md @@ -11,7 +11,7 @@ Remove a builder instance | Name | Description | | --- | --- | -| `--builder string` | Override the configured builder instance | +| [`--builder string`](#builder) | Override the configured builder instance | | [`--keep-state`](#keep-state) | Keep BuildKit state | @@ -24,6 +24,10 @@ default builder. ## Examples +### Override the configured builder instance (--builder) + +Same as [`buildx --builder`](buildx.md#builder). + ### Keep BuildKit state (--keep-state) Keep BuildKit state, so it can be reused by a new builder with the same name. diff --git a/docs/reference/buildx_stop.md b/docs/reference/buildx_stop.md index 23db3040..c34d7124 100644 --- a/docs/reference/buildx_stop.md +++ b/docs/reference/buildx_stop.md @@ -7,6 +7,12 @@ docker buildx stop [NAME] Stop builder instance +### Options + +| Name | Description | +| --- | --- | +| [`--builder string`](#builder) | Override the configured builder instance | + @@ -14,3 +20,9 @@ Stop builder instance Stops the specified or current builder. This will not prevent buildx build to restart the builder. The implementation of stop depends on the driver. + +## Examples + +### Override the configured builder instance (--builder) + +Same as [`buildx --builder`](buildx.md#builder). diff --git a/docs/reference/buildx_use.md b/docs/reference/buildx_use.md index 541016ed..fe38a075 100644 --- a/docs/reference/buildx_use.md +++ b/docs/reference/buildx_use.md @@ -11,7 +11,7 @@ Set the current builder instance | Name | Description | | --- | --- | -| `--builder string` | Override the configured builder instance | +| [`--builder string`](#builder) | Override the configured builder instance | | `--default` | Set builder as default for current context | | `--global` | Builder persists context changes | @@ -23,3 +23,9 @@ Set the current builder instance Switches the current builder instance. Build commands invoked after this command will run on a specified builder. Alternatively, a context name can be used to switch to the default builder of that context. + +## Examples + +### Override the configured builder instance (--builder) + +Same as [`buildx --builder`](buildx.md#builder). diff --git a/go.mod b/go.mod index 304e0238..9a12ccb8 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/containerd/console v1.0.3 github.com/containerd/containerd v1.5.5 github.com/docker/cli v20.10.8+incompatible - github.com/docker/cli-docs-tool v0.1.1 + github.com/docker/cli-docs-tool v0.2.1 github.com/docker/compose-on-kubernetes v0.4.19-0.20190128150448-356b2919c496 // indirect github.com/docker/distribution v2.7.1+incompatible github.com/docker/docker v20.10.7+incompatible diff --git a/go.sum b/go.sum index 45b1988c..836d69f8 100644 --- a/go.sum +++ b/go.sum @@ -410,8 +410,8 @@ github.com/distribution/distribution/v3 v3.0.0-20210316161203-a01c71e2477e/go.mo github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/docker/cli v20.10.3-0.20210702143511-f782d1355eff+incompatible h1:CaaxCD/l9Dxogu6lxf7AQautlv3sHULrasPadayp0fM= github.com/docker/cli v20.10.3-0.20210702143511-f782d1355eff+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/cli-docs-tool v0.1.1 h1:c6vuTMvogCkSFQCXIr6Mb4gFgUpdZ+28YMbCBfaQLik= -github.com/docker/cli-docs-tool v0.1.1/go.mod h1:oMzPNt1wC3TcxuY22GMnOODNOxkwGH51gV3AhqAjFQ4= +github.com/docker/cli-docs-tool v0.2.1 h1:ffZhhdws6kE+dCKHLMlYROZz8z01RtWbz+g4xz0eBIU= +github.com/docker/cli-docs-tool v0.2.1/go.mod h1:rgW5KKdNpLMBIuH4WQ/1RNh38nH+/Ay5jgL4P0ZMPpY= github.com/docker/compose-on-kubernetes v0.4.19-0.20190128150448-356b2919c496 h1:90ytrX1dbzL7Uf/hHiuWwvywC+gikHv4hkAy4CwRTbs= github.com/docker/compose-on-kubernetes v0.4.19-0.20190128150448-356b2919c496/go.mod h1:iT2pYfi580XlpaV4KmK0T6+4/9+XoKmk/fhoDod1emE= github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= diff --git a/util/cobrautil/cobrautil.go b/util/cobrautil/cobrautil.go new file mode 100644 index 00000000..9b53dffe --- /dev/null +++ b/util/cobrautil/cobrautil.go @@ -0,0 +1,14 @@ +package cobrautil + +import "github.com/spf13/cobra" + +// HideInheritedFlags hides inherited flags +func HideInheritedFlags(cmd *cobra.Command, hidden ...string) { + for _, h := range hidden { + // we could use cmd.SetHelpFunc to override the helper + // but, it's not enough because we also want the generated + // docs to be updated, so we override the flag instead + cmd.Flags().String(h, "", "") + _ = cmd.Flags().MarkHidden(h) + } +} diff --git a/vendor/github.com/docker/cli-docs-tool/README.md b/vendor/github.com/docker/cli-docs-tool/README.md index a7f82b48..3dc8aa9f 100644 --- a/vendor/github.com/docker/cli-docs-tool/README.md +++ b/vendor/github.com/docker/cli-docs-tool/README.md @@ -41,61 +41,10 @@ require ( ) ``` -Next, create a file named `docgen.go` inside that directory containing the -following Go code: +Next, create a file named `main.go` inside that directory containing the +following Go code from [`example/main.go`](example/main.go). -```go -package main - -import ( - "log" - "os" - "path/filepath" - - "github.com/docker/buildx/commands" - "github.com/docker/cli/cli/command" - clidocstool "github.com/docker/cli-docs-tool" - "github.com/spf13/cobra" -) - -const sourcePath = "docs/" - -func main() { - log.SetFlags(0) - - dockerCLI, err := command.NewDockerCli() - if err != nil { - log.Printf("ERROR: %+v", err) - } - - cmd := &cobra.Command{ - Use: "docker [OPTIONS] COMMAND [ARG...]", - Short: "The base command for the Docker CLI.", - DisableAutoGenTag: true, - } - - cmd.AddCommand(commands.NewRootCmd("buildx", true, dockerCLI)) - clidocstool.DisableFlagsInUseLine(cmd) - - cwd, _ := os.Getwd() - source := filepath.Join(cwd, sourcePath) - - // Make sure "source" folder is created first - if err = os.MkdirAll(source, 0755); err != nil { - log.Printf("ERROR: %+v", err) - } - - // Generate Markdown and YAML documentation to "source" folder - if err = clidocstool.GenTree(cmd, source); err != nil { - log.Printf("ERROR: %+v", err) - } -} -``` - -Here we create a new instance of Docker CLI with `command.NewDockerCli` and a -subcommand `commands.NewRootCmd` for `buildx`. - -Finally, we generate Markdown and YAML documentation with `clidocstool.GenTree`. +Running this example should produce the following output: ```console $ go run main.go diff --git a/vendor/github.com/docker/cli-docs-tool/clidocstool.go b/vendor/github.com/docker/cli-docs-tool/clidocstool.go index b353f597..9dfb8004 100644 --- a/vendor/github.com/docker/cli-docs-tool/clidocstool.go +++ b/vendor/github.com/docker/cli-docs-tool/clidocstool.go @@ -15,38 +15,90 @@ package clidocstool import ( + "errors" + "io" + "os" + "github.com/spf13/cobra" ) -// GenTree creates yaml and markdown structured ref files for this command -// and all descendants in the directory given. This function will just -// call GenMarkdownTree and GenYamlTree functions successively. -func GenTree(cmd *cobra.Command, dir string) error { +const ( + // AnnotationExternalUrl specifies an external link annotation + AnnotationExternalUrl = "docs.external.url" +) + +// Options defines options for cli-docs-tool +type Options struct { + Root *cobra.Command + SourceDir string + TargetDir string + Plugin bool +} + +// Client represents an active cli-docs-tool object +type Client struct { + root *cobra.Command + source string + target string + plugin bool +} + +// New initializes a new cli-docs-tool client +func New(opts Options) (*Client, error) { + if opts.Root == nil { + return nil, errors.New("root cmd required") + } + if len(opts.SourceDir) == 0 { + return nil, errors.New("source dir required") + } + c := &Client{ + root: opts.Root, + source: opts.SourceDir, + plugin: opts.Plugin, + } + if len(opts.TargetDir) == 0 { + c.target = c.source + } else { + c.target = opts.TargetDir + } + if err := os.MkdirAll(c.target, 0755); err != nil { + return nil, err + } + return c, nil +} + +// GenAllTree creates all structured ref files for this command and +// all descendants in the directory given. +func (c *Client) GenAllTree() error { var err error - if err = GenMarkdownTree(cmd, dir); err != nil { + if err = c.GenMarkdownTree(c.root); err != nil { return err } - if err = GenYamlTree(cmd, dir); err != nil { + if err = c.GenYamlTree(c.root); err != nil { return err } return nil } -// VisitAll will traverse all commands from the root. -// This is different from the VisitAll of cobra.Command where only parents -// are checked. -func VisitAll(root *cobra.Command, fn func(*cobra.Command)) { - for _, cmd := range root.Commands() { - VisitAll(cmd, fn) +func fileExists(f string) bool { + info, err := os.Stat(f) + if os.IsNotExist(err) { + return false } - fn(root) + return !info.IsDir() } -// DisableFlagsInUseLine sets the DisableFlagsInUseLine flag on all -// commands within the tree rooted at cmd. -func DisableFlagsInUseLine(cmd *cobra.Command) { - VisitAll(cmd, func(ccmd *cobra.Command) { - // do not add a `[flags]` to the end of the usage line. - ccmd.DisableFlagsInUseLine = true - }) +func copyFile(src string, dst string) error { + sf, err := os.Open(src) + if err != nil { + return err + } + defer sf.Close() + df, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY, 0o600) + if err != nil { + return err + } + defer df.Close() + _, err = io.Copy(df, sf) + return err } diff --git a/vendor/github.com/docker/cli-docs-tool/clidocstool_md.go b/vendor/github.com/docker/cli-docs-tool/clidocstool_md.go index dc2723a8..7b1d6ec0 100644 --- a/vendor/github.com/docker/cli-docs-tool/clidocstool_md.go +++ b/vendor/github.com/docker/cli-docs-tool/clidocstool_md.go @@ -24,28 +24,34 @@ import ( "strings" "text/template" - "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/pflag" ) // GenMarkdownTree will generate a markdown page for this command and all // descendants in the directory given. -func GenMarkdownTree(cmd *cobra.Command, dir string) error { - for _, c := range cmd.Commands() { - if err := GenMarkdownTree(c, dir); err != nil { +func (c *Client) GenMarkdownTree(cmd *cobra.Command) error { + for _, sc := range cmd.Commands() { + if err := c.GenMarkdownTree(sc); err != nil { return err } } - if !cmd.HasParent() { + + // always disable the addition of [flags] to the usage + cmd.DisableFlagsInUseLine = true + + // Skip the root command altogether, to prevent generating a useless + // md file for plugins. + if c.plugin && !cmd.HasParent() { return nil } log.Printf("INFO: Generating Markdown for %q", cmd.CommandPath()) mdFile := mdFilename(cmd) - fullPath := filepath.Join(dir, mdFile) + sourcePath := filepath.Join(c.source, mdFile) + targetPath := filepath.Join(c.target, mdFile) - if _, err := os.Stat(fullPath); os.IsNotExist(err) { + if !fileExists(sourcePath) { var icBuf bytes.Buffer icTpl, err := template.New("ic").Option("missingkey=error").Parse(`# {{ .Command }} @@ -63,12 +69,14 @@ func GenMarkdownTree(cmd *cobra.Command, dir string) error { }); err != nil { return err } - if err = ioutil.WriteFile(fullPath, icBuf.Bytes(), 0644); err != nil { + if err = ioutil.WriteFile(targetPath, icBuf.Bytes(), 0644); err != nil { return err } + } else if err := copyFile(sourcePath, targetPath); err != nil { + return err } - content, err := ioutil.ReadFile(fullPath) + content, err := ioutil.ReadFile(targetPath) if err != nil { return err } @@ -79,10 +87,10 @@ func GenMarkdownTree(cmd *cobra.Command, dir string) error { end := strings.Index(cs, "") if start == -1 { - return errors.Errorf("no start marker in %s", mdFile) + return fmt.Errorf("no start marker in %s", mdFile) } if end == -1 { - return errors.Errorf("no end marker in %s", mdFile) + return fmt.Errorf("no end marker in %s", mdFile) } out, err := mdCmdOutput(cmd, cs) @@ -91,12 +99,12 @@ func GenMarkdownTree(cmd *cobra.Command, dir string) error { } cont := cs[:start] + "" + "\n" + out + "\n" + cs[end:] - fi, err := os.Stat(fullPath) + fi, err := os.Stat(targetPath) if err != nil { return err } - if err := ioutil.WriteFile(fullPath, []byte(cont), fi.Mode()); err != nil { - return errors.Wrapf(err, "failed to write %s", fullPath) + if err = ioutil.WriteFile(targetPath, []byte(cont), fi.Mode()); err != nil { + return fmt.Errorf("failed to write %s: %w", targetPath, err) } return nil @@ -112,7 +120,7 @@ func mdFilename(cmd *cobra.Command) string { func mdMakeLink(txt, link string, f *pflag.Flag, isAnchor bool) string { link = "#" + link - annotations, ok := f.Annotations["docs.external.url"] + annotations, ok := f.Annotations[AnnotationExternalUrl] if ok && len(annotations) > 0 { link = annotations[0] } else { @@ -153,11 +161,10 @@ func mdCmdOutput(cmd *cobra.Command, old string) (string, error) { fmt.Fprint(b, "\n\n") } - hasFlags := cmd.Flags().HasAvailableFlags() - + // add inherited flags before checking for flags availability cmd.Flags().AddFlagSet(cmd.InheritedFlags()) - if hasFlags { + if cmd.Flags().HasAvailableFlags() { fmt.Fprint(b, "### Options\n\n") fmt.Fprint(b, "| Name | Description |\n") fmt.Fprint(b, "| --- | --- |\n") diff --git a/vendor/github.com/docker/cli-docs-tool/clidocstool_yaml.go b/vendor/github.com/docker/cli-docs-tool/clidocstool_yaml.go index bd46f815..91ccf623 100644 --- a/vendor/github.com/docker/cli-docs-tool/clidocstool_yaml.go +++ b/vendor/github.com/docker/cli-docs-tool/clidocstool_yaml.go @@ -74,62 +74,61 @@ type cmdDoc struct { // correctly if your command names have `-` in them. If you have `cmd` with two // subcmds, `sub` and `sub-third`, and `sub` has a subcommand called `third` // it is undefined which help output will be in the file `cmd-sub-third.1`. -func GenYamlTree(cmd *cobra.Command, dir string) error { +func (c *Client) GenYamlTree(cmd *cobra.Command) error { emptyStr := func(s string) string { return "" } - if err := loadLongDescription(cmd, dir); err != nil { + if err := c.loadLongDescription(cmd); err != nil { return err } - return GenYamlTreeCustom(cmd, dir, emptyStr) + return c.genYamlTreeCustom(cmd, emptyStr) } -// GenYamlTreeCustom creates yaml structured ref files. -func GenYamlTreeCustom(cmd *cobra.Command, dir string, filePrepender func(string) string) error { - for _, c := range cmd.Commands() { - if !c.Runnable() && !c.HasAvailableSubCommands() { +// genYamlTreeCustom creates yaml structured ref files. +func (c *Client) genYamlTreeCustom(cmd *cobra.Command, filePrepender func(string) string) error { + for _, sc := range cmd.Commands() { + if !sc.Runnable() && !sc.HasAvailableSubCommands() { // skip non-runnable commands without subcommands // but *do* generate YAML for hidden and deprecated commands // the YAML will have those included as metadata, so that the // documentation repository can decide whether or not to present them continue } - if err := GenYamlTreeCustom(c, dir, filePrepender); err != nil { + if err := c.genYamlTreeCustom(sc, filePrepender); err != nil { return err } } - // TODO: conditionally skip the root command (for plugins) - // + // always disable the addition of [flags] to the usage + cmd.DisableFlagsInUseLine = true + // The "root" command used in the generator is just a "stub", and only has a // list of subcommands, but not (e.g.) global options/flags. We should fix // that, so that the YAML file for the docker "root" command contains the // global flags. - // - // If we're using this code to generate YAML docs for a plugin, the root- - // command is even less useful; in that case, the root command represents - // the "docker" command, and is a "dummy" with no flags, and only a single - // subcommand (the plugin's top command). For plugins, we should skip the - // root command altogether, to prevent generating a useless YAML file. - if !cmd.HasParent() { + + // Skip the root command altogether, to prevent generating a useless + // YAML file for plugins. + if c.plugin && !cmd.HasParent() { return nil } + log.Printf("INFO: Generating YAML for %q", cmd.CommandPath()) basename := strings.Replace(cmd.CommandPath(), " ", "_", -1) + ".yaml" - filename := filepath.Join(dir, basename) - f, err := os.Create(filename) + target := filepath.Join(c.target, basename) + f, err := os.Create(target) if err != nil { return err } defer f.Close() - if _, err := io.WriteString(f, filePrepender(filename)); err != nil { + if _, err := io.WriteString(f, filePrepender(target)); err != nil { return err } - return GenYamlCustom(cmd, f) + return c.genYamlCustom(cmd, f) } -// GenYamlCustom creates custom yaml output. +// genYamlCustom creates custom yaml output. // nolint: gocyclo -func GenYamlCustom(cmd *cobra.Command, w io.Writer) error { +func (c *Client) genYamlCustom(cmd *cobra.Command, w io.Writer) error { const ( // shortMaxWidth is the maximum width for the "Short" description before // we force YAML to use multi-line syntax. The goal is to make the total @@ -144,6 +143,10 @@ func GenYamlCustom(cmd *cobra.Command, w io.Writer) error { longMaxWidth = 74 ) + // necessary to add inherited flags otherwise some + // fields are not properly declared like usage + cmd.Flags().AddFlagSet(cmd.InheritedFlags()) + cliDoc := cmdDoc{ Name: cmd.CommandPath(), Aliases: strings.Join(cmd.Aliases, ", "), @@ -263,7 +266,7 @@ func genFlagResult(flags *pflag.FlagSet, anchors map[string]struct{}) []cmdOptio Deprecated: len(flag.Deprecated) > 0, } - if v, ok := flag.Annotations["docs.external.url"]; ok && len(v) > 0 { + if v, ok := flag.Annotations[AnnotationExternalUrl]; ok && len(v) > 0 { opt.DetailsURL = strings.TrimPrefix(v[0], "https://docs.docker.com") } else if _, ok = anchors[flag.Name]; ok { opt.DetailsURL = "#" + flag.Name @@ -338,15 +341,15 @@ func hasSeeAlso(cmd *cobra.Command) bool { } // loadLongDescription gets long descriptions and examples from markdown. -func loadLongDescription(parentCmd *cobra.Command, path string) error { +func (c *Client) loadLongDescription(parentCmd *cobra.Command) error { for _, cmd := range parentCmd.Commands() { if cmd.HasSubCommands() { - if err := loadLongDescription(cmd, path); err != nil { + if err := c.loadLongDescription(cmd); err != nil { return err } } name := cmd.CommandPath() - if i := strings.Index(name, " "); i >= 0 { + if i := strings.Index(name, " "); c.plugin && i >= 0 { // remove root command / binary name name = name[i+1:] } @@ -354,8 +357,8 @@ func loadLongDescription(parentCmd *cobra.Command, path string) error { continue } mdFile := strings.ReplaceAll(name, " ", "_") + ".md" - fullPath := filepath.Join(path, mdFile) - content, err := ioutil.ReadFile(fullPath) + sourcePath := filepath.Join(c.source, mdFile) + content, err := ioutil.ReadFile(sourcePath) if os.IsNotExist(err) { log.Printf("WARN: %s does not exist, skipping Markdown examples for YAML doc\n", mdFile) continue diff --git a/vendor/github.com/docker/cli-docs-tool/go.mod b/vendor/github.com/docker/cli-docs-tool/go.mod index f2dcdaef..9252b68f 100644 --- a/vendor/github.com/docker/cli-docs-tool/go.mod +++ b/vendor/github.com/docker/cli-docs-tool/go.mod @@ -3,7 +3,6 @@ module github.com/docker/cli-docs-tool go 1.16 require ( - github.com/pkg/errors v0.9.1 github.com/spf13/cobra v1.2.1 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.7.0 diff --git a/vendor/github.com/docker/cli-docs-tool/go.sum b/vendor/github.com/docker/cli-docs-tool/go.sum index c6628350..f94ce98e 100644 --- a/vendor/github.com/docker/cli-docs-tool/go.sum +++ b/vendor/github.com/docker/cli-docs-tool/go.sum @@ -191,8 +191,6 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= diff --git a/vendor/modules.txt b/vendor/modules.txt index 23aa87f9..31e79da1 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -100,7 +100,7 @@ github.com/docker/cli/cli/streams github.com/docker/cli/cli/trust github.com/docker/cli/cli/version github.com/docker/cli/opts -# github.com/docker/cli-docs-tool v0.1.1 +# github.com/docker/cli-docs-tool v0.2.1 ## explicit github.com/docker/cli-docs-tool # github.com/docker/compose-on-kubernetes v0.4.19-0.20190128150448-356b2919c496