cli: fix builder persistent flag

Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
CrazyMax 2021-11-04 18:52:11 +01:00
parent 4c938c77ba
commit eab0e6a8fe
No known key found for this signature in database
GPG Key ID: 3248E46B6BB8C7F7
34 changed files with 277 additions and 172 deletions

View File

@ -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
}

View File

@ -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")

View File

@ -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

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
}
}

View File

@ -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 |
<!---MARKER_GEN_END-->
## Examples
### <a name="builder"></a> Override the configured builder instance (--builder)
You can also use the `BUILDX_BUILDER` environment variable.

View File

@ -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
### <a name="builder"></a> Override the configured builder instance (--builder)
Same as [`buildx --builder`](buildx.md#builder).
### <a name="file"></a> Specify a build definition file (-f, --file)
By default, `buildx bake` looks for build definition files in the current

View File

@ -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 well document a subset of the new flags.
## Examples
### <a name="builder"></a> Override the configured builder instance (--builder)
Same as [`buildx --builder`](buildx.md#builder).
### <a name="platform"></a> Set the target platforms for the build (--platform)
```

View File

@ -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`) |

View File

@ -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 |
<!---MARKER_GEN_END-->
## Examples
### <a name="builder"></a> Override the configured builder instance (--builder)
Same as [`buildx --builder`](buildx.md#builder).

View File

@ -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 |
<!---MARKER_GEN_END-->
@ -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
### <a name="builder"></a> Override the configured builder instance (--builder)
Same as [`buildx --builder`](buildx.md#builder).

View File

@ -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.
### <a name="builder"></a> Override the configured builder instance (--builder)
Same as [`buildx --builder`](buildx.md#builder).
### <a name="dry-run"></a> Show final image instead of pushing (--dry-run)
Use the `--dry-run` flag to not push the image, just show it.

View File

@ -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
### <a name="builder"></a> Override the configured builder instance (--builder)
Same as [`buildx --builder`](buildx.md#builder).
### <a name="raw"></a> Show original, unformatted JSON manifest (--raw)
Use the `--raw` option to print the original JSON bytes instead of the formatted

View File

@ -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 |
<!---MARKER_GEN_END-->
@ -23,6 +23,19 @@ Shows information about the current or specified builder.
## Examples
### <a name="bootstrap"></a> 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`).
### <a name="builder"></a> 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
```
### <a name="bootstrap"></a> 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`).

View File

@ -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
<!---MARKER_GEN_END-->
## Examples
### <a name="builder"></a> Override the configured builder instance (--builder)
Same as [`buildx --builder`](buildx.md#builder).

View File

@ -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
### <a name="builder"></a> Override the configured builder instance (--builder)
Same as [`buildx --builder`](buildx.md#builder).
### <a name="keep-state"></a> Keep BuildKit state (--keep-state)
Keep BuildKit state, so it can be reused by a new builder with the same name.

View File

@ -7,6 +7,12 @@ docker buildx stop [NAME]
<!---MARKER_GEN_START-->
Stop builder instance
### Options
| Name | Description |
| --- | --- |
| [`--builder string`](#builder) | Override the configured builder instance |
<!---MARKER_GEN_END-->
@ -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
### <a name="builder"></a> Override the configured builder instance (--builder)
Same as [`buildx --builder`](buildx.md#builder).

View File

@ -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
### <a name="builder"></a> Override the configured builder instance (--builder)
Same as [`buildx --builder`](buildx.md#builder).

2
go.mod
View File

@ -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

4
go.sum
View File

@ -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=

View File

@ -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)
}
}

View File

@ -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

View File

@ -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
}

View File

@ -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, "<!---MARKER_GEN_END-->")
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] + "<!---MARKER_GEN_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")

View File

@ -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

View File

@ -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

View File

@ -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=

2
vendor/modules.txt vendored
View File

@ -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