mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-05-18 00:47:48 +08:00
vendor: github.com/docker/cli v28.0.2
full diff: https://github.com/docker/cli/compare/v28.0.1...v28.0.2 Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
882ef0db91
commit
db4b96e62c
2
go.mod
2
go.mod
@ -17,7 +17,7 @@ require (
|
|||||||
github.com/creack/pty v1.1.24
|
github.com/creack/pty v1.1.24
|
||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/distribution/reference v0.6.0
|
github.com/distribution/reference v0.6.0
|
||||||
github.com/docker/cli v28.0.1+incompatible
|
github.com/docker/cli v28.0.2+incompatible
|
||||||
github.com/docker/cli-docs-tool v0.9.0
|
github.com/docker/cli-docs-tool v0.9.0
|
||||||
github.com/docker/docker v28.0.2+incompatible
|
github.com/docker/docker v28.0.2+incompatible
|
||||||
github.com/docker/go-units v0.5.0
|
github.com/docker/go-units v0.5.0
|
||||||
|
4
go.sum
4
go.sum
@ -122,8 +122,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
|||||||
github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||||
github.com/docker/cli v28.0.1+incompatible h1:g0h5NQNda3/CxIsaZfH4Tyf6vpxFth7PYl3hgCPOKzs=
|
github.com/docker/cli v28.0.2+incompatible h1:cRPZ77FK3/IXTAIQQj1vmhlxiLS5m+MIUDwS6f57lrE=
|
||||||
github.com/docker/cli v28.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
github.com/docker/cli v28.0.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||||
github.com/docker/cli-docs-tool v0.9.0 h1:CVwQbE+ZziwlPqrJ7LRyUF6GvCA+6gj7MTCsayaK9t0=
|
github.com/docker/cli-docs-tool v0.9.0 h1:CVwQbE+ZziwlPqrJ7LRyUF6GvCA+6gj7MTCsayaK9t0=
|
||||||
github.com/docker/cli-docs-tool v0.9.0/go.mod h1:ClrwlNW+UioiRyH9GiAOe1o3J/TsY3Tr1ipoypjAUtc=
|
github.com/docker/cli-docs-tool v0.9.0/go.mod h1:ClrwlNW+UioiRyH9GiAOe1o3J/TsY3Tr1ipoypjAUtc=
|
||||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
|
30
vendor/github.com/docker/cli/cli-plugins/manager/annotations.go
generated
vendored
Normal file
30
vendor/github.com/docker/cli/cli-plugins/manager/annotations.go
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package manager
|
||||||
|
|
||||||
|
import "github.com/docker/cli/cli-plugins/metadata"
|
||||||
|
|
||||||
|
const (
|
||||||
|
// CommandAnnotationPlugin is added to every stub command added by
|
||||||
|
// AddPluginCommandStubs with the value "true" and so can be
|
||||||
|
// used to distinguish plugin stubs from regular commands.
|
||||||
|
CommandAnnotationPlugin = metadata.CommandAnnotationPlugin
|
||||||
|
|
||||||
|
// CommandAnnotationPluginVendor is added to every stub command
|
||||||
|
// added by AddPluginCommandStubs and contains the vendor of
|
||||||
|
// that plugin.
|
||||||
|
CommandAnnotationPluginVendor = metadata.CommandAnnotationPluginVendor
|
||||||
|
|
||||||
|
// CommandAnnotationPluginVersion is added to every stub command
|
||||||
|
// added by AddPluginCommandStubs and contains the version of
|
||||||
|
// that plugin.
|
||||||
|
CommandAnnotationPluginVersion = metadata.CommandAnnotationPluginVersion
|
||||||
|
|
||||||
|
// CommandAnnotationPluginInvalid is added to any stub command
|
||||||
|
// added by AddPluginCommandStubs for an invalid command (that
|
||||||
|
// is, one which failed it's candidate test) and contains the
|
||||||
|
// reason for the failure.
|
||||||
|
CommandAnnotationPluginInvalid = metadata.CommandAnnotationPluginInvalid
|
||||||
|
|
||||||
|
// CommandAnnotationPluginCommandPath is added to overwrite the
|
||||||
|
// command path for a plugin invocation.
|
||||||
|
CommandAnnotationPluginCommandPath = metadata.CommandAnnotationPluginCommandPath
|
||||||
|
)
|
8
vendor/github.com/docker/cli/cli-plugins/manager/candidate.go
generated
vendored
8
vendor/github.com/docker/cli/cli-plugins/manager/candidate.go
generated
vendored
@ -1,6 +1,10 @@
|
|||||||
package manager
|
package manager
|
||||||
|
|
||||||
import "os/exec"
|
import (
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
|
"github.com/docker/cli/cli-plugins/metadata"
|
||||||
|
)
|
||||||
|
|
||||||
// Candidate represents a possible plugin candidate, for mocking purposes
|
// Candidate represents a possible plugin candidate, for mocking purposes
|
||||||
type Candidate interface {
|
type Candidate interface {
|
||||||
@ -17,5 +21,5 @@ func (c *candidate) Path() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *candidate) Metadata() ([]byte, error) {
|
func (c *candidate) Metadata() ([]byte, error) {
|
||||||
return exec.Command(c.path, MetadataSubcommandName).Output() // #nosec G204 -- ignore "Subprocess launched with a potential tainted input or cmd arguments"
|
return exec.Command(c.path, metadata.MetadataSubcommandName).Output() // #nosec G204 -- ignore "Subprocess launched with a potential tainted input or cmd arguments"
|
||||||
}
|
}
|
||||||
|
88
vendor/github.com/docker/cli/cli-plugins/manager/cobra.go
generated
vendored
88
vendor/github.com/docker/cli/cli-plugins/manager/cobra.go
generated
vendored
@ -2,41 +2,12 @@ package manager
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/docker/cli/cli/command"
|
"github.com/docker/cli/cli-plugins/metadata"
|
||||||
|
"github.com/docker/cli/cli/config"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"go.opentelemetry.io/otel/attribute"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// CommandAnnotationPlugin is added to every stub command added by
|
|
||||||
// AddPluginCommandStubs with the value "true" and so can be
|
|
||||||
// used to distinguish plugin stubs from regular commands.
|
|
||||||
CommandAnnotationPlugin = "com.docker.cli.plugin"
|
|
||||||
|
|
||||||
// CommandAnnotationPluginVendor is added to every stub command
|
|
||||||
// added by AddPluginCommandStubs and contains the vendor of
|
|
||||||
// that plugin.
|
|
||||||
CommandAnnotationPluginVendor = "com.docker.cli.plugin.vendor"
|
|
||||||
|
|
||||||
// CommandAnnotationPluginVersion is added to every stub command
|
|
||||||
// added by AddPluginCommandStubs and contains the version of
|
|
||||||
// that plugin.
|
|
||||||
CommandAnnotationPluginVersion = "com.docker.cli.plugin.version"
|
|
||||||
|
|
||||||
// CommandAnnotationPluginInvalid is added to any stub command
|
|
||||||
// added by AddPluginCommandStubs for an invalid command (that
|
|
||||||
// is, one which failed it's candidate test) and contains the
|
|
||||||
// reason for the failure.
|
|
||||||
CommandAnnotationPluginInvalid = "com.docker.cli.plugin-invalid"
|
|
||||||
|
|
||||||
// CommandAnnotationPluginCommandPath is added to overwrite the
|
|
||||||
// command path for a plugin invocation.
|
|
||||||
CommandAnnotationPluginCommandPath = "com.docker.cli.plugin.command_path"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var pluginCommandStubsOnce sync.Once
|
var pluginCommandStubsOnce sync.Once
|
||||||
@ -44,10 +15,10 @@ var pluginCommandStubsOnce sync.Once
|
|||||||
// AddPluginCommandStubs adds a stub cobra.Commands for each valid and invalid
|
// AddPluginCommandStubs adds a stub cobra.Commands for each valid and invalid
|
||||||
// plugin. The command stubs will have several annotations added, see
|
// plugin. The command stubs will have several annotations added, see
|
||||||
// `CommandAnnotationPlugin*`.
|
// `CommandAnnotationPlugin*`.
|
||||||
func AddPluginCommandStubs(dockerCli command.Cli, rootCmd *cobra.Command) (err error) {
|
func AddPluginCommandStubs(dockerCLI config.Provider, rootCmd *cobra.Command) (err error) {
|
||||||
pluginCommandStubsOnce.Do(func() {
|
pluginCommandStubsOnce.Do(func() {
|
||||||
var plugins []Plugin
|
var plugins []Plugin
|
||||||
plugins, err = ListPlugins(dockerCli, rootCmd)
|
plugins, err = ListPlugins(dockerCLI, rootCmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -57,12 +28,12 @@ func AddPluginCommandStubs(dockerCli command.Cli, rootCmd *cobra.Command) (err e
|
|||||||
vendor = "unknown"
|
vendor = "unknown"
|
||||||
}
|
}
|
||||||
annotations := map[string]string{
|
annotations := map[string]string{
|
||||||
CommandAnnotationPlugin: "true",
|
metadata.CommandAnnotationPlugin: "true",
|
||||||
CommandAnnotationPluginVendor: vendor,
|
metadata.CommandAnnotationPluginVendor: vendor,
|
||||||
CommandAnnotationPluginVersion: p.Version,
|
metadata.CommandAnnotationPluginVersion: p.Version,
|
||||||
}
|
}
|
||||||
if p.Err != nil {
|
if p.Err != nil {
|
||||||
annotations[CommandAnnotationPluginInvalid] = p.Err.Error()
|
annotations[metadata.CommandAnnotationPluginInvalid] = p.Err.Error()
|
||||||
}
|
}
|
||||||
rootCmd.AddCommand(&cobra.Command{
|
rootCmd.AddCommand(&cobra.Command{
|
||||||
Use: p.Name,
|
Use: p.Name,
|
||||||
@ -89,7 +60,7 @@ func AddPluginCommandStubs(dockerCli command.Cli, rootCmd *cobra.Command) (err e
|
|||||||
cargs = append(cargs, args...)
|
cargs = append(cargs, args...)
|
||||||
cargs = append(cargs, toComplete)
|
cargs = append(cargs, toComplete)
|
||||||
os.Args = cargs
|
os.Args = cargs
|
||||||
runCommand, runErr := PluginRunCommand(dockerCli, p.Name, cmd)
|
runCommand, runErr := PluginRunCommand(dockerCLI, p.Name, cmd)
|
||||||
if runErr != nil {
|
if runErr != nil {
|
||||||
return nil, cobra.ShellCompDirectiveError
|
return nil, cobra.ShellCompDirectiveError
|
||||||
}
|
}
|
||||||
@ -104,44 +75,3 @@ func AddPluginCommandStubs(dockerCli command.Cli, rootCmd *cobra.Command) (err e
|
|||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
dockerCliAttributePrefix = attribute.Key("docker.cli")
|
|
||||||
|
|
||||||
cobraCommandPath = attribute.Key("cobra.command_path")
|
|
||||||
)
|
|
||||||
|
|
||||||
func getPluginResourceAttributes(cmd *cobra.Command, plugin Plugin) attribute.Set {
|
|
||||||
commandPath := cmd.Annotations[CommandAnnotationPluginCommandPath]
|
|
||||||
if commandPath == "" {
|
|
||||||
commandPath = fmt.Sprintf("%s %s", cmd.CommandPath(), plugin.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
attrSet := attribute.NewSet(
|
|
||||||
cobraCommandPath.String(commandPath),
|
|
||||||
)
|
|
||||||
|
|
||||||
kvs := make([]attribute.KeyValue, 0, attrSet.Len())
|
|
||||||
for iter := attrSet.Iter(); iter.Next(); {
|
|
||||||
attr := iter.Attribute()
|
|
||||||
kvs = append(kvs, attribute.KeyValue{
|
|
||||||
Key: dockerCliAttributePrefix + "." + attr.Key,
|
|
||||||
Value: attr.Value,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return attribute.NewSet(kvs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func appendPluginResourceAttributesEnvvar(env []string, cmd *cobra.Command, plugin Plugin) []string {
|
|
||||||
if attrs := getPluginResourceAttributes(cmd, plugin); attrs.Len() > 0 {
|
|
||||||
// values in environment variables need to be in baggage format
|
|
||||||
// otel/baggage package can be used after update to v1.22, currently it encodes incorrectly
|
|
||||||
attrsSlice := make([]string, attrs.Len())
|
|
||||||
for iter := attrs.Iter(); iter.Next(); {
|
|
||||||
i, v := iter.IndexedAttribute()
|
|
||||||
attrsSlice[i] = string(v.Key) + "=" + url.PathEscape(v.Value.AsString())
|
|
||||||
}
|
|
||||||
env = append(env, ResourceAttributesEnvvar+"="+strings.Join(attrsSlice, ","))
|
|
||||||
}
|
|
||||||
return env
|
|
||||||
}
|
|
||||||
|
8
vendor/github.com/docker/cli/cli-plugins/manager/error.go
generated
vendored
8
vendor/github.com/docker/cli/cli-plugins/manager/error.go
generated
vendored
@ -4,7 +4,7 @@
|
|||||||
package manager
|
package manager
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pkg/errors"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// pluginError is set as Plugin.Err by NewPlugin if the plugin
|
// pluginError is set as Plugin.Err by NewPlugin if the plugin
|
||||||
@ -39,16 +39,16 @@ func (e *pluginError) MarshalText() (text []byte, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// wrapAsPluginError wraps an error in a pluginError with an
|
// wrapAsPluginError wraps an error in a pluginError with an
|
||||||
// additional message, analogous to errors.Wrapf.
|
// additional message.
|
||||||
func wrapAsPluginError(err error, msg string) error {
|
func wrapAsPluginError(err error, msg string) error {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &pluginError{cause: errors.Wrap(err, msg)}
|
return &pluginError{cause: fmt.Errorf("%s: %w", msg, err)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPluginError creates a new pluginError, analogous to
|
// NewPluginError creates a new pluginError, analogous to
|
||||||
// errors.Errorf.
|
// errors.Errorf.
|
||||||
func NewPluginError(msg string, args ...any) error {
|
func NewPluginError(msg string, args ...any) error {
|
||||||
return &pluginError{cause: errors.Errorf(msg, args...)}
|
return &pluginError{cause: fmt.Errorf(msg, args...)}
|
||||||
}
|
}
|
||||||
|
28
vendor/github.com/docker/cli/cli-plugins/manager/hooks.go
generated
vendored
28
vendor/github.com/docker/cli/cli-plugins/manager/hooks.go
generated
vendored
@ -6,7 +6,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/docker/cli/cli-plugins/hooks"
|
"github.com/docker/cli/cli-plugins/hooks"
|
||||||
"github.com/docker/cli/cli/command"
|
"github.com/docker/cli/cli/config"
|
||||||
|
"github.com/docker/cli/cli/config/configfile"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
@ -29,29 +30,28 @@ type HookPluginData struct {
|
|||||||
// a main CLI command was executed. It calls the hook subcommand for all
|
// a main CLI command was executed. It calls the hook subcommand for all
|
||||||
// present CLI plugins that declare support for hooks in their metadata and
|
// present CLI plugins that declare support for hooks in their metadata and
|
||||||
// parses/prints their responses.
|
// parses/prints their responses.
|
||||||
func RunCLICommandHooks(ctx context.Context, dockerCli command.Cli, rootCmd, subCommand *cobra.Command, cmdErrorMessage string) {
|
func RunCLICommandHooks(ctx context.Context, dockerCLI config.Provider, rootCmd, subCommand *cobra.Command, cmdErrorMessage string) {
|
||||||
commandName := strings.TrimPrefix(subCommand.CommandPath(), rootCmd.Name()+" ")
|
commandName := strings.TrimPrefix(subCommand.CommandPath(), rootCmd.Name()+" ")
|
||||||
flags := getCommandFlags(subCommand)
|
flags := getCommandFlags(subCommand)
|
||||||
|
|
||||||
runHooks(ctx, dockerCli, rootCmd, subCommand, commandName, flags, cmdErrorMessage)
|
runHooks(ctx, dockerCLI.ConfigFile(), rootCmd, subCommand, commandName, flags, cmdErrorMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunPluginHooks is the entrypoint for the hooks execution flow
|
// RunPluginHooks is the entrypoint for the hooks execution flow
|
||||||
// after a plugin command was just executed by the CLI.
|
// after a plugin command was just executed by the CLI.
|
||||||
func RunPluginHooks(ctx context.Context, dockerCli command.Cli, rootCmd, subCommand *cobra.Command, args []string) {
|
func RunPluginHooks(ctx context.Context, dockerCLI config.Provider, rootCmd, subCommand *cobra.Command, args []string) {
|
||||||
commandName := strings.Join(args, " ")
|
commandName := strings.Join(args, " ")
|
||||||
flags := getNaiveFlags(args)
|
flags := getNaiveFlags(args)
|
||||||
|
|
||||||
runHooks(ctx, dockerCli, rootCmd, subCommand, commandName, flags, "")
|
runHooks(ctx, dockerCLI.ConfigFile(), rootCmd, subCommand, commandName, flags, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func runHooks(ctx context.Context, dockerCli command.Cli, rootCmd, subCommand *cobra.Command, invokedCommand string, flags map[string]string, cmdErrorMessage string) {
|
func runHooks(ctx context.Context, cfg *configfile.ConfigFile, rootCmd, subCommand *cobra.Command, invokedCommand string, flags map[string]string, cmdErrorMessage string) {
|
||||||
nextSteps := invokeAndCollectHooks(ctx, dockerCli, rootCmd, subCommand, invokedCommand, flags, cmdErrorMessage)
|
nextSteps := invokeAndCollectHooks(ctx, cfg, rootCmd, subCommand, invokedCommand, flags, cmdErrorMessage)
|
||||||
|
hooks.PrintNextSteps(subCommand.ErrOrStderr(), nextSteps)
|
||||||
hooks.PrintNextSteps(dockerCli.Err(), nextSteps)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func invokeAndCollectHooks(ctx context.Context, dockerCli command.Cli, rootCmd, subCmd *cobra.Command, subCmdStr string, flags map[string]string, cmdErrorMessage string) []string {
|
func invokeAndCollectHooks(ctx context.Context, cfg *configfile.ConfigFile, rootCmd, subCmd *cobra.Command, subCmdStr string, flags map[string]string, cmdErrorMessage string) []string {
|
||||||
// check if the context was cancelled before invoking hooks
|
// check if the context was cancelled before invoking hooks
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
@ -59,11 +59,15 @@ func invokeAndCollectHooks(ctx context.Context, dockerCli command.Cli, rootCmd,
|
|||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
pluginsCfg := dockerCli.ConfigFile().Plugins
|
pluginsCfg := cfg.Plugins
|
||||||
if pluginsCfg == nil {
|
if pluginsCfg == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pluginDirs, err := getPluginDirs(cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
nextSteps := make([]string, 0, len(pluginsCfg))
|
nextSteps := make([]string, 0, len(pluginsCfg))
|
||||||
for pluginName, cfg := range pluginsCfg {
|
for pluginName, cfg := range pluginsCfg {
|
||||||
match, ok := pluginMatch(cfg, subCmdStr)
|
match, ok := pluginMatch(cfg, subCmdStr)
|
||||||
@ -71,7 +75,7 @@ func invokeAndCollectHooks(ctx context.Context, dockerCli command.Cli, rootCmd,
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
p, err := GetPlugin(pluginName, dockerCli, rootCmd)
|
p, err := getPlugin(pluginName, pluginDirs, rootCmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
27
vendor/github.com/docker/cli/cli-plugins/manager/manager.go
generated
vendored
27
vendor/github.com/docker/cli/cli-plugins/manager/manager.go
generated
vendored
@ -9,7 +9,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/docker/cli/cli/command"
|
"github.com/docker/cli/cli-plugins/metadata"
|
||||||
"github.com/docker/cli/cli/config"
|
"github.com/docker/cli/cli/config"
|
||||||
"github.com/docker/cli/cli/config/configfile"
|
"github.com/docker/cli/cli/config/configfile"
|
||||||
"github.com/fvbommel/sortorder"
|
"github.com/fvbommel/sortorder"
|
||||||
@ -22,10 +22,12 @@ const (
|
|||||||
// used to originally invoke the docker CLI when executing a
|
// used to originally invoke the docker CLI when executing a
|
||||||
// plugin. Assuming $PATH and $CWD remain unchanged this should allow
|
// plugin. Assuming $PATH and $CWD remain unchanged this should allow
|
||||||
// the plugin to re-execute the original CLI.
|
// the plugin to re-execute the original CLI.
|
||||||
ReexecEnvvar = "DOCKER_CLI_PLUGIN_ORIGINAL_CLI_COMMAND"
|
ReexecEnvvar = metadata.ReexecEnvvar
|
||||||
|
|
||||||
// ResourceAttributesEnvvar is the name of the envvar that includes additional
|
// ResourceAttributesEnvvar is the name of the envvar that includes additional
|
||||||
// resource attributes for OTEL.
|
// resource attributes for OTEL.
|
||||||
|
//
|
||||||
|
// Deprecated: The "OTEL_RESOURCE_ATTRIBUTES" env-var is part of the OpenTelemetry specification; users should define their own const for this. This const will be removed in the next release.
|
||||||
ResourceAttributesEnvvar = "OTEL_RESOURCE_ATTRIBUTES"
|
ResourceAttributesEnvvar = "OTEL_RESOURCE_ATTRIBUTES"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -91,10 +93,10 @@ func addPluginCandidatesFromDir(res map[string][]string, d string) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
name := dentry.Name()
|
name := dentry.Name()
|
||||||
if !strings.HasPrefix(name, NamePrefix) {
|
if !strings.HasPrefix(name, metadata.NamePrefix) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
name = strings.TrimPrefix(name, NamePrefix)
|
name = strings.TrimPrefix(name, metadata.NamePrefix)
|
||||||
var err error
|
var err error
|
||||||
if name, err = trimExeSuffix(name); err != nil {
|
if name, err = trimExeSuffix(name); err != nil {
|
||||||
continue
|
continue
|
||||||
@ -113,12 +115,15 @@ func listPluginCandidates(dirs []string) map[string][]string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetPlugin returns a plugin on the system by its name
|
// GetPlugin returns a plugin on the system by its name
|
||||||
func GetPlugin(name string, dockerCli command.Cli, rootcmd *cobra.Command) (*Plugin, error) {
|
func GetPlugin(name string, dockerCLI config.Provider, rootcmd *cobra.Command) (*Plugin, error) {
|
||||||
pluginDirs, err := getPluginDirs(dockerCli.ConfigFile())
|
pluginDirs, err := getPluginDirs(dockerCLI.ConfigFile())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return getPlugin(name, pluginDirs, rootcmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPlugin(name string, pluginDirs []string, rootcmd *cobra.Command) (*Plugin, error) {
|
||||||
candidates := listPluginCandidates(pluginDirs)
|
candidates := listPluginCandidates(pluginDirs)
|
||||||
if paths, ok := candidates[name]; ok {
|
if paths, ok := candidates[name]; ok {
|
||||||
if len(paths) == 0 {
|
if len(paths) == 0 {
|
||||||
@ -139,7 +144,7 @@ func GetPlugin(name string, dockerCli command.Cli, rootcmd *cobra.Command) (*Plu
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListPlugins produces a list of the plugins available on the system
|
// ListPlugins produces a list of the plugins available on the system
|
||||||
func ListPlugins(dockerCli command.Cli, rootcmd *cobra.Command) ([]Plugin, error) {
|
func ListPlugins(dockerCli config.Provider, rootcmd *cobra.Command) ([]Plugin, error) {
|
||||||
pluginDirs, err := getPluginDirs(dockerCli.ConfigFile())
|
pluginDirs, err := getPluginDirs(dockerCli.ConfigFile())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -186,7 +191,7 @@ func ListPlugins(dockerCli command.Cli, rootcmd *cobra.Command) ([]Plugin, error
|
|||||||
// PluginRunCommand returns an "os/exec".Cmd which when .Run() will execute the named plugin.
|
// PluginRunCommand returns an "os/exec".Cmd which when .Run() will execute the named plugin.
|
||||||
// The rootcmd argument is referenced to determine the set of builtin commands in order to detect conficts.
|
// The rootcmd argument is referenced to determine the set of builtin commands in order to detect conficts.
|
||||||
// The error returned satisfies the IsNotFound() predicate if no plugin was found or if the first candidate plugin was invalid somehow.
|
// The error returned satisfies the IsNotFound() predicate if no plugin was found or if the first candidate plugin was invalid somehow.
|
||||||
func PluginRunCommand(dockerCli command.Cli, name string, rootcmd *cobra.Command) (*exec.Cmd, error) {
|
func PluginRunCommand(dockerCli config.Provider, name string, rootcmd *cobra.Command) (*exec.Cmd, error) {
|
||||||
// This uses the full original args, not the args which may
|
// This uses the full original args, not the args which may
|
||||||
// have been provided by cobra to our caller. This is because
|
// have been provided by cobra to our caller. This is because
|
||||||
// they lack e.g. global options which we must propagate here.
|
// they lack e.g. global options which we must propagate here.
|
||||||
@ -196,7 +201,7 @@ func PluginRunCommand(dockerCli command.Cli, name string, rootcmd *cobra.Command
|
|||||||
// fallback to their "invalid" command path.
|
// fallback to their "invalid" command path.
|
||||||
return nil, errPluginNotFound(name)
|
return nil, errPluginNotFound(name)
|
||||||
}
|
}
|
||||||
exename := addExeSuffix(NamePrefix + name)
|
exename := addExeSuffix(metadata.NamePrefix + name)
|
||||||
pluginDirs, err := getPluginDirs(dockerCli.ConfigFile())
|
pluginDirs, err := getPluginDirs(dockerCli.ConfigFile())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -233,7 +238,7 @@ func PluginRunCommand(dockerCli command.Cli, name string, rootcmd *cobra.Command
|
|||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
|
|
||||||
cmd.Env = append(cmd.Environ(), ReexecEnvvar+"="+os.Args[0])
|
cmd.Env = append(cmd.Environ(), metadata.ReexecEnvvar+"="+os.Args[0])
|
||||||
cmd.Env = appendPluginResourceAttributesEnvvar(cmd.Env, rootcmd, plugin)
|
cmd.Env = appendPluginResourceAttributesEnvvar(cmd.Env, rootcmd, plugin)
|
||||||
|
|
||||||
return cmd, nil
|
return cmd, nil
|
||||||
@ -243,5 +248,5 @@ func PluginRunCommand(dockerCli command.Cli, name string, rootcmd *cobra.Command
|
|||||||
|
|
||||||
// IsPluginCommand checks if the given cmd is a plugin-stub.
|
// IsPluginCommand checks if the given cmd is a plugin-stub.
|
||||||
func IsPluginCommand(cmd *cobra.Command) bool {
|
func IsPluginCommand(cmd *cobra.Command) bool {
|
||||||
return cmd.Annotations[CommandAnnotationPlugin] == "true"
|
return cmd.Annotations[metadata.CommandAnnotationPlugin] == "true"
|
||||||
}
|
}
|
||||||
|
23
vendor/github.com/docker/cli/cli-plugins/manager/metadata.go
generated
vendored
23
vendor/github.com/docker/cli/cli-plugins/manager/metadata.go
generated
vendored
@ -1,30 +1,23 @@
|
|||||||
package manager
|
package manager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/docker/cli/cli-plugins/metadata"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// NamePrefix is the prefix required on all plugin binary names
|
// NamePrefix is the prefix required on all plugin binary names
|
||||||
NamePrefix = "docker-"
|
NamePrefix = metadata.NamePrefix
|
||||||
|
|
||||||
// MetadataSubcommandName is the name of the plugin subcommand
|
// MetadataSubcommandName is the name of the plugin subcommand
|
||||||
// which must be supported by every plugin and returns the
|
// which must be supported by every plugin and returns the
|
||||||
// plugin metadata.
|
// plugin metadata.
|
||||||
MetadataSubcommandName = "docker-cli-plugin-metadata"
|
MetadataSubcommandName = metadata.MetadataSubcommandName
|
||||||
|
|
||||||
// HookSubcommandName is the name of the plugin subcommand
|
// HookSubcommandName is the name of the plugin subcommand
|
||||||
// which must be implemented by plugins declaring support
|
// which must be implemented by plugins declaring support
|
||||||
// for hooks in their metadata.
|
// for hooks in their metadata.
|
||||||
HookSubcommandName = "docker-cli-plugin-hooks"
|
HookSubcommandName = metadata.HookSubcommandName
|
||||||
)
|
)
|
||||||
|
|
||||||
// Metadata provided by the plugin.
|
// Metadata provided by the plugin.
|
||||||
type Metadata struct {
|
type Metadata = metadata.Metadata
|
||||||
// SchemaVersion describes the version of this struct. Mandatory, must be "0.1.0"
|
|
||||||
SchemaVersion string `json:",omitempty"`
|
|
||||||
// Vendor is the name of the plugin vendor. Mandatory
|
|
||||||
Vendor string `json:",omitempty"`
|
|
||||||
// Version is the optional version of this plugin.
|
|
||||||
Version string `json:",omitempty"`
|
|
||||||
// ShortDescription should be suitable for a single line help message.
|
|
||||||
ShortDescription string `json:",omitempty"`
|
|
||||||
// URL is a pointer to the plugin's homepage.
|
|
||||||
URL string `json:",omitempty"`
|
|
||||||
}
|
|
||||||
|
20
vendor/github.com/docker/cli/cli-plugins/manager/plugin.go
generated
vendored
20
vendor/github.com/docker/cli/cli-plugins/manager/plugin.go
generated
vendored
@ -3,13 +3,15 @@ package manager
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/docker/cli/cli-plugins/metadata"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,7 +19,7 @@ var pluginNameRe = regexp.MustCompile("^[a-z][a-z0-9]*$")
|
|||||||
|
|
||||||
// Plugin represents a potential plugin with all it's metadata.
|
// Plugin represents a potential plugin with all it's metadata.
|
||||||
type Plugin struct {
|
type Plugin struct {
|
||||||
Metadata
|
metadata.Metadata
|
||||||
|
|
||||||
Name string `json:",omitempty"`
|
Name string `json:",omitempty"`
|
||||||
Path string `json:",omitempty"`
|
Path string `json:",omitempty"`
|
||||||
@ -44,18 +46,18 @@ func newPlugin(c Candidate, cmds []*cobra.Command) (Plugin, error) {
|
|||||||
// which would fail here, so there are all real errors.
|
// which would fail here, so there are all real errors.
|
||||||
fullname := filepath.Base(path)
|
fullname := filepath.Base(path)
|
||||||
if fullname == "." {
|
if fullname == "." {
|
||||||
return Plugin{}, errors.Errorf("unable to determine basename of plugin candidate %q", path)
|
return Plugin{}, fmt.Errorf("unable to determine basename of plugin candidate %q", path)
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
if fullname, err = trimExeSuffix(fullname); err != nil {
|
if fullname, err = trimExeSuffix(fullname); err != nil {
|
||||||
return Plugin{}, errors.Wrapf(err, "plugin candidate %q", path)
|
return Plugin{}, fmt.Errorf("plugin candidate %q: %w", path, err)
|
||||||
}
|
}
|
||||||
if !strings.HasPrefix(fullname, NamePrefix) {
|
if !strings.HasPrefix(fullname, metadata.NamePrefix) {
|
||||||
return Plugin{}, errors.Errorf("plugin candidate %q: does not have %q prefix", path, NamePrefix)
|
return Plugin{}, fmt.Errorf("plugin candidate %q: does not have %q prefix", path, metadata.NamePrefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
p := Plugin{
|
p := Plugin{
|
||||||
Name: strings.TrimPrefix(fullname, NamePrefix),
|
Name: strings.TrimPrefix(fullname, metadata.NamePrefix),
|
||||||
Path: path,
|
Path: path,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,9 +114,9 @@ func (p *Plugin) RunHook(ctx context.Context, hookData HookPluginData) ([]byte,
|
|||||||
return nil, wrapAsPluginError(err, "failed to marshall hook data")
|
return nil, wrapAsPluginError(err, "failed to marshall hook data")
|
||||||
}
|
}
|
||||||
|
|
||||||
pCmd := exec.CommandContext(ctx, p.Path, p.Name, HookSubcommandName, string(hDataBytes)) // #nosec G204 -- ignore "Subprocess launched with a potential tainted input or cmd arguments"
|
pCmd := exec.CommandContext(ctx, p.Path, p.Name, metadata.HookSubcommandName, string(hDataBytes)) // #nosec G204 -- ignore "Subprocess launched with a potential tainted input or cmd arguments"
|
||||||
pCmd.Env = os.Environ()
|
pCmd.Env = os.Environ()
|
||||||
pCmd.Env = append(pCmd.Env, ReexecEnvvar+"="+os.Args[0])
|
pCmd.Env = append(pCmd.Env, metadata.ReexecEnvvar+"="+os.Args[0])
|
||||||
hookCmdOutput, err := pCmd.Output()
|
hookCmdOutput, err := pCmd.Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, wrapAsPluginError(err, "failed to execute plugin hook subcommand")
|
return nil, wrapAsPluginError(err, "failed to execute plugin hook subcommand")
|
||||||
|
14
vendor/github.com/docker/cli/cli-plugins/manager/suffix_windows.go
generated
vendored
14
vendor/github.com/docker/cli/cli-plugins/manager/suffix_windows.go
generated
vendored
@ -1,22 +1,16 @@
|
|||||||
package manager
|
package manager
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is made slightly more complex due to needing to be case insensitive.
|
// This is made slightly more complex due to needing to be case-insensitive.
|
||||||
func trimExeSuffix(s string) (string, error) {
|
func trimExeSuffix(s string) (string, error) {
|
||||||
ext := filepath.Ext(s)
|
ext := filepath.Ext(s)
|
||||||
if ext == "" {
|
if ext == "" || !strings.EqualFold(ext, ".exe") {
|
||||||
return "", errors.Errorf("path %q lacks required file extension", s)
|
return "", fmt.Errorf("path %q lacks required file extension (.exe)", s)
|
||||||
}
|
|
||||||
|
|
||||||
exe := ".exe"
|
|
||||||
if !strings.EqualFold(ext, exe) {
|
|
||||||
return "", errors.Errorf("path %q lacks required %q suffix", s, exe)
|
|
||||||
}
|
}
|
||||||
return strings.TrimSuffix(s, ext), nil
|
return strings.TrimSuffix(s, ext), nil
|
||||||
}
|
}
|
||||||
|
85
vendor/github.com/docker/cli/cli-plugins/manager/telemetry.go
generated
vendored
Normal file
85
vendor/github.com/docker/cli/cli-plugins/manager/telemetry.go
generated
vendored
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
package manager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/docker/cli/cli-plugins/metadata"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"go.opentelemetry.io/otel"
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
"go.opentelemetry.io/otel/baggage"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// resourceAttributesEnvVar is the name of the envvar that includes additional
|
||||||
|
// resource attributes for OTEL as defined in the [OpenTelemetry specification].
|
||||||
|
//
|
||||||
|
// [OpenTelemetry specification]: https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#general-sdk-configuration
|
||||||
|
resourceAttributesEnvVar = "OTEL_RESOURCE_ATTRIBUTES"
|
||||||
|
|
||||||
|
// dockerCLIAttributePrefix is the prefix for any docker cli OTEL attributes.
|
||||||
|
//
|
||||||
|
// It is a copy of the const defined in [command.dockerCLIAttributePrefix].
|
||||||
|
dockerCLIAttributePrefix = "docker.cli."
|
||||||
|
cobraCommandPath = attribute.Key("cobra.command_path")
|
||||||
|
)
|
||||||
|
|
||||||
|
func getPluginResourceAttributes(cmd *cobra.Command, plugin Plugin) attribute.Set {
|
||||||
|
commandPath := cmd.Annotations[metadata.CommandAnnotationPluginCommandPath]
|
||||||
|
if commandPath == "" {
|
||||||
|
commandPath = fmt.Sprintf("%s %s", cmd.CommandPath(), plugin.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
attrSet := attribute.NewSet(
|
||||||
|
cobraCommandPath.String(commandPath),
|
||||||
|
)
|
||||||
|
|
||||||
|
kvs := make([]attribute.KeyValue, 0, attrSet.Len())
|
||||||
|
for iter := attrSet.Iter(); iter.Next(); {
|
||||||
|
attr := iter.Attribute()
|
||||||
|
kvs = append(kvs, attribute.KeyValue{
|
||||||
|
Key: dockerCLIAttributePrefix + attr.Key,
|
||||||
|
Value: attr.Value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return attribute.NewSet(kvs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendPluginResourceAttributesEnvvar(env []string, cmd *cobra.Command, plugin Plugin) []string {
|
||||||
|
if attrs := getPluginResourceAttributes(cmd, plugin); attrs.Len() > 0 {
|
||||||
|
// Construct baggage members for each of the attributes.
|
||||||
|
// Ignore any failures as these aren't significant and
|
||||||
|
// represent an internal issue.
|
||||||
|
members := make([]baggage.Member, 0, attrs.Len())
|
||||||
|
for iter := attrs.Iter(); iter.Next(); {
|
||||||
|
attr := iter.Attribute()
|
||||||
|
m, err := baggage.NewMemberRaw(string(attr.Key), attr.Value.AsString())
|
||||||
|
if err != nil {
|
||||||
|
otel.Handle(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
members = append(members, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combine plugin added resource attributes with ones found in the environment
|
||||||
|
// variable. Our own attributes should be namespaced so there shouldn't be a
|
||||||
|
// conflict. We do not parse the environment variable because we do not want
|
||||||
|
// to handle errors in user configuration.
|
||||||
|
attrsSlice := make([]string, 0, 2)
|
||||||
|
if v := strings.TrimSpace(os.Getenv(resourceAttributesEnvVar)); v != "" {
|
||||||
|
attrsSlice = append(attrsSlice, v)
|
||||||
|
}
|
||||||
|
if b, err := baggage.New(members...); err != nil {
|
||||||
|
otel.Handle(err)
|
||||||
|
} else if b.Len() > 0 {
|
||||||
|
attrsSlice = append(attrsSlice, b.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(attrsSlice) > 0 {
|
||||||
|
env = append(env, resourceAttributesEnvVar+"="+strings.Join(attrsSlice, ","))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return env
|
||||||
|
}
|
28
vendor/github.com/docker/cli/cli-plugins/metadata/annotations.go
generated
vendored
Normal file
28
vendor/github.com/docker/cli/cli-plugins/metadata/annotations.go
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package metadata
|
||||||
|
|
||||||
|
const (
|
||||||
|
// CommandAnnotationPlugin is added to every stub command added by
|
||||||
|
// AddPluginCommandStubs with the value "true" and so can be
|
||||||
|
// used to distinguish plugin stubs from regular commands.
|
||||||
|
CommandAnnotationPlugin = "com.docker.cli.plugin"
|
||||||
|
|
||||||
|
// CommandAnnotationPluginVendor is added to every stub command
|
||||||
|
// added by AddPluginCommandStubs and contains the vendor of
|
||||||
|
// that plugin.
|
||||||
|
CommandAnnotationPluginVendor = "com.docker.cli.plugin.vendor"
|
||||||
|
|
||||||
|
// CommandAnnotationPluginVersion is added to every stub command
|
||||||
|
// added by AddPluginCommandStubs and contains the version of
|
||||||
|
// that plugin.
|
||||||
|
CommandAnnotationPluginVersion = "com.docker.cli.plugin.version"
|
||||||
|
|
||||||
|
// CommandAnnotationPluginInvalid is added to any stub command
|
||||||
|
// added by AddPluginCommandStubs for an invalid command (that
|
||||||
|
// is, one which failed it's candidate test) and contains the
|
||||||
|
// reason for the failure.
|
||||||
|
CommandAnnotationPluginInvalid = "com.docker.cli.plugin-invalid"
|
||||||
|
|
||||||
|
// CommandAnnotationPluginCommandPath is added to overwrite the
|
||||||
|
// command path for a plugin invocation.
|
||||||
|
CommandAnnotationPluginCommandPath = "com.docker.cli.plugin.command_path"
|
||||||
|
)
|
36
vendor/github.com/docker/cli/cli-plugins/metadata/metadata.go
generated
vendored
Normal file
36
vendor/github.com/docker/cli/cli-plugins/metadata/metadata.go
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package metadata
|
||||||
|
|
||||||
|
const (
|
||||||
|
// NamePrefix is the prefix required on all plugin binary names
|
||||||
|
NamePrefix = "docker-"
|
||||||
|
|
||||||
|
// MetadataSubcommandName is the name of the plugin subcommand
|
||||||
|
// which must be supported by every plugin and returns the
|
||||||
|
// plugin metadata.
|
||||||
|
MetadataSubcommandName = "docker-cli-plugin-metadata"
|
||||||
|
|
||||||
|
// HookSubcommandName is the name of the plugin subcommand
|
||||||
|
// which must be implemented by plugins declaring support
|
||||||
|
// for hooks in their metadata.
|
||||||
|
HookSubcommandName = "docker-cli-plugin-hooks"
|
||||||
|
|
||||||
|
// ReexecEnvvar is the name of an ennvar which is set to the command
|
||||||
|
// used to originally invoke the docker CLI when executing a
|
||||||
|
// plugin. Assuming $PATH and $CWD remain unchanged this should allow
|
||||||
|
// the plugin to re-execute the original CLI.
|
||||||
|
ReexecEnvvar = "DOCKER_CLI_PLUGIN_ORIGINAL_CLI_COMMAND"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Metadata provided by the plugin.
|
||||||
|
type Metadata struct {
|
||||||
|
// SchemaVersion describes the version of this struct. Mandatory, must be "0.1.0"
|
||||||
|
SchemaVersion string `json:",omitempty"`
|
||||||
|
// Vendor is the name of the plugin vendor. Mandatory
|
||||||
|
Vendor string `json:",omitempty"`
|
||||||
|
// Version is the optional version of this plugin.
|
||||||
|
Version string `json:",omitempty"`
|
||||||
|
// ShortDescription should be suitable for a single line help message.
|
||||||
|
ShortDescription string `json:",omitempty"`
|
||||||
|
// URL is a pointer to the plugin's homepage.
|
||||||
|
URL string `json:",omitempty"`
|
||||||
|
}
|
20
vendor/github.com/docker/cli/cli-plugins/plugin/plugin.go
generated
vendored
20
vendor/github.com/docker/cli/cli-plugins/plugin/plugin.go
generated
vendored
@ -9,7 +9,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/docker/cli/cli"
|
"github.com/docker/cli/cli"
|
||||||
"github.com/docker/cli/cli-plugins/manager"
|
"github.com/docker/cli/cli-plugins/metadata"
|
||||||
"github.com/docker/cli/cli-plugins/socket"
|
"github.com/docker/cli/cli-plugins/socket"
|
||||||
"github.com/docker/cli/cli/command"
|
"github.com/docker/cli/cli/command"
|
||||||
"github.com/docker/cli/cli/connhelper"
|
"github.com/docker/cli/cli/connhelper"
|
||||||
@ -30,7 +30,7 @@ import (
|
|||||||
var PersistentPreRunE func(*cobra.Command, []string) error
|
var PersistentPreRunE func(*cobra.Command, []string) error
|
||||||
|
|
||||||
// RunPlugin executes the specified plugin command
|
// RunPlugin executes the specified plugin command
|
||||||
func RunPlugin(dockerCli *command.DockerCli, plugin *cobra.Command, meta manager.Metadata) error {
|
func RunPlugin(dockerCli *command.DockerCli, plugin *cobra.Command, meta metadata.Metadata) error {
|
||||||
tcmd := newPluginCommand(dockerCli, plugin, meta)
|
tcmd := newPluginCommand(dockerCli, plugin, meta)
|
||||||
|
|
||||||
var persistentPreRunOnce sync.Once
|
var persistentPreRunOnce sync.Once
|
||||||
@ -81,7 +81,7 @@ func RunPlugin(dockerCli *command.DockerCli, plugin *cobra.Command, meta manager
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run is the top-level entry point to the CLI plugin framework. It should be called from your plugin's `main()` function.
|
// Run is the top-level entry point to the CLI plugin framework. It should be called from your plugin's `main()` function.
|
||||||
func Run(makeCmd func(command.Cli) *cobra.Command, meta manager.Metadata) {
|
func Run(makeCmd func(command.Cli) *cobra.Command, meta metadata.Metadata) {
|
||||||
otel.SetErrorHandler(debug.OTELErrorHandler)
|
otel.SetErrorHandler(debug.OTELErrorHandler)
|
||||||
|
|
||||||
dockerCli, err := command.NewDockerCli()
|
dockerCli, err := command.NewDockerCli()
|
||||||
@ -111,7 +111,7 @@ func Run(makeCmd func(command.Cli) *cobra.Command, meta manager.Metadata) {
|
|||||||
func withPluginClientConn(name string) command.CLIOption {
|
func withPluginClientConn(name string) command.CLIOption {
|
||||||
return command.WithInitializeClient(func(dockerCli *command.DockerCli) (client.APIClient, error) {
|
return command.WithInitializeClient(func(dockerCli *command.DockerCli) (client.APIClient, error) {
|
||||||
cmd := "docker"
|
cmd := "docker"
|
||||||
if x := os.Getenv(manager.ReexecEnvvar); x != "" {
|
if x := os.Getenv(metadata.ReexecEnvvar); x != "" {
|
||||||
cmd = x
|
cmd = x
|
||||||
}
|
}
|
||||||
var flags []string
|
var flags []string
|
||||||
@ -140,9 +140,9 @@ func withPluginClientConn(name string) command.CLIOption {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPluginCommand(dockerCli *command.DockerCli, plugin *cobra.Command, meta manager.Metadata) *cli.TopLevelCommand {
|
func newPluginCommand(dockerCli *command.DockerCli, plugin *cobra.Command, meta metadata.Metadata) *cli.TopLevelCommand {
|
||||||
name := plugin.Name()
|
name := plugin.Name()
|
||||||
fullname := manager.NamePrefix + name
|
fullname := metadata.NamePrefix + name
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: fmt.Sprintf("docker [OPTIONS] %s [ARG...]", name),
|
Use: fmt.Sprintf("docker [OPTIONS] %s [ARG...]", name),
|
||||||
@ -177,12 +177,12 @@ func newPluginCommand(dockerCli *command.DockerCli, plugin *cobra.Command, meta
|
|||||||
return cli.NewTopLevelCommand(cmd, dockerCli, opts, cmd.Flags())
|
return cli.NewTopLevelCommand(cmd, dockerCli, opts, cmd.Flags())
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMetadataSubcommand(plugin *cobra.Command, meta manager.Metadata) *cobra.Command {
|
func newMetadataSubcommand(plugin *cobra.Command, meta metadata.Metadata) *cobra.Command {
|
||||||
if meta.ShortDescription == "" {
|
if meta.ShortDescription == "" {
|
||||||
meta.ShortDescription = plugin.Short
|
meta.ShortDescription = plugin.Short
|
||||||
}
|
}
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: manager.MetadataSubcommandName,
|
Use: metadata.MetadataSubcommandName,
|
||||||
Hidden: true,
|
Hidden: true,
|
||||||
// Suppress the global/parent PersistentPreRunE, which
|
// Suppress the global/parent PersistentPreRunE, which
|
||||||
// needlessly initializes the client and tries to
|
// needlessly initializes the client and tries to
|
||||||
@ -200,8 +200,8 @@ func newMetadataSubcommand(plugin *cobra.Command, meta manager.Metadata) *cobra.
|
|||||||
|
|
||||||
// RunningStandalone tells a CLI plugin it is run standalone by direct execution
|
// RunningStandalone tells a CLI plugin it is run standalone by direct execution
|
||||||
func RunningStandalone() bool {
|
func RunningStandalone() bool {
|
||||||
if os.Getenv(manager.ReexecEnvvar) != "" {
|
if os.Getenv(metadata.ReexecEnvvar) != "" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return len(os.Args) < 2 || os.Args[1] != manager.MetadataSubcommandName
|
return len(os.Args) < 2 || os.Args[1] != metadata.MetadataSubcommandName
|
||||||
}
|
}
|
||||||
|
20
vendor/github.com/docker/cli/cli/cobra.go
generated
vendored
20
vendor/github.com/docker/cli/cli/cobra.go
generated
vendored
@ -3,15 +3,12 @@ package cli
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
pluginmanager "github.com/docker/cli/cli-plugins/manager"
|
"github.com/docker/cli/cli-plugins/metadata"
|
||||||
"github.com/docker/cli/cli/command"
|
"github.com/docker/cli/cli/command"
|
||||||
cliflags "github.com/docker/cli/cli/flags"
|
cliflags "github.com/docker/cli/cli/flags"
|
||||||
"github.com/docker/docker/pkg/homedir"
|
|
||||||
"github.com/docker/docker/registry"
|
|
||||||
"github.com/fvbommel/sortorder"
|
"github.com/fvbommel/sortorder"
|
||||||
"github.com/moby/term"
|
"github.com/moby/term"
|
||||||
"github.com/morikuni/aec"
|
"github.com/morikuni/aec"
|
||||||
@ -62,13 +59,6 @@ func setupCommonRootCommand(rootCmd *cobra.Command) (*cliflags.ClientOptions, *c
|
|||||||
"docs.code-delimiter": `"`, // https://github.com/docker/cli-docs-tool/blob/77abede22166eaea4af7335096bdcedd043f5b19/annotation/annotation.go#L20-L22
|
"docs.code-delimiter": `"`, // https://github.com/docker/cli-docs-tool/blob/77abede22166eaea4af7335096bdcedd043f5b19/annotation/annotation.go#L20-L22
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure registry.CertsDir() when running in rootless-mode
|
|
||||||
if os.Getenv("ROOTLESSKIT_STATE_DIR") != "" {
|
|
||||||
if configHome, err := homedir.GetConfigHome(); err == nil {
|
|
||||||
registry.SetCertsDir(filepath.Join(configHome, "docker/certs.d"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return opts, helpCommand
|
return opts, helpCommand
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,7 +242,7 @@ func hasAdditionalHelp(cmd *cobra.Command) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func isPlugin(cmd *cobra.Command) bool {
|
func isPlugin(cmd *cobra.Command) bool {
|
||||||
return pluginmanager.IsPluginCommand(cmd)
|
return cmd.Annotations[metadata.CommandAnnotationPlugin] == "true"
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasAliases(cmd *cobra.Command) bool {
|
func hasAliases(cmd *cobra.Command) bool {
|
||||||
@ -356,9 +346,9 @@ func decoratedName(cmd *cobra.Command) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func vendorAndVersion(cmd *cobra.Command) string {
|
func vendorAndVersion(cmd *cobra.Command) string {
|
||||||
if vendor, ok := cmd.Annotations[pluginmanager.CommandAnnotationPluginVendor]; ok && isPlugin(cmd) {
|
if vendor, ok := cmd.Annotations[metadata.CommandAnnotationPluginVendor]; ok && isPlugin(cmd) {
|
||||||
version := ""
|
version := ""
|
||||||
if v, ok := cmd.Annotations[pluginmanager.CommandAnnotationPluginVersion]; ok && v != "" {
|
if v, ok := cmd.Annotations[metadata.CommandAnnotationPluginVersion]; ok && v != "" {
|
||||||
version = ", " + v
|
version = ", " + v
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("(%s%s)", vendor, version)
|
return fmt.Sprintf("(%s%s)", vendor, version)
|
||||||
@ -417,7 +407,7 @@ func invalidPlugins(cmd *cobra.Command) []*cobra.Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func invalidPluginReason(cmd *cobra.Command) string {
|
func invalidPluginReason(cmd *cobra.Command) string {
|
||||||
return cmd.Annotations[pluginmanager.CommandAnnotationPluginInvalid]
|
return cmd.Annotations[metadata.CommandAnnotationPluginInvalid]
|
||||||
}
|
}
|
||||||
|
|
||||||
const usageTemplate = `Usage:
|
const usageTemplate = `Usage:
|
||||||
|
59
vendor/github.com/docker/cli/cli/command/cli.go
generated
vendored
59
vendor/github.com/docker/cli/cli/command/cli.go
generated
vendored
@ -8,7 +8,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
@ -21,21 +20,15 @@ import (
|
|||||||
"github.com/docker/cli/cli/context/store"
|
"github.com/docker/cli/cli/context/store"
|
||||||
"github.com/docker/cli/cli/debug"
|
"github.com/docker/cli/cli/debug"
|
||||||
cliflags "github.com/docker/cli/cli/flags"
|
cliflags "github.com/docker/cli/cli/flags"
|
||||||
manifeststore "github.com/docker/cli/cli/manifest/store"
|
|
||||||
registryclient "github.com/docker/cli/cli/registry/client"
|
|
||||||
"github.com/docker/cli/cli/streams"
|
"github.com/docker/cli/cli/streams"
|
||||||
"github.com/docker/cli/cli/trust"
|
|
||||||
"github.com/docker/cli/cli/version"
|
"github.com/docker/cli/cli/version"
|
||||||
dopts "github.com/docker/cli/opts"
|
dopts "github.com/docker/cli/opts"
|
||||||
"github.com/docker/docker/api"
|
"github.com/docker/docker/api"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/registry"
|
|
||||||
"github.com/docker/docker/api/types/swarm"
|
"github.com/docker/docker/api/types/swarm"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
"github.com/docker/go-connections/tlsconfig"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
notaryclient "github.com/theupdateframework/notary/client"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultInitTimeout = 2 * time.Second
|
const defaultInitTimeout = 2 * time.Second
|
||||||
@ -53,19 +46,18 @@ type Cli interface {
|
|||||||
Streams
|
Streams
|
||||||
SetIn(in *streams.In)
|
SetIn(in *streams.In)
|
||||||
Apply(ops ...CLIOption) error
|
Apply(ops ...CLIOption) error
|
||||||
ConfigFile() *configfile.ConfigFile
|
config.Provider
|
||||||
ServerInfo() ServerInfo
|
ServerInfo() ServerInfo
|
||||||
NotaryClient(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (notaryclient.Repository, error)
|
|
||||||
DefaultVersion() string
|
DefaultVersion() string
|
||||||
CurrentVersion() string
|
CurrentVersion() string
|
||||||
ManifestStore() manifeststore.Store
|
|
||||||
RegistryClient(bool) registryclient.RegistryClient
|
|
||||||
ContentTrustEnabled() bool
|
ContentTrustEnabled() bool
|
||||||
BuildKitEnabled() (bool, error)
|
BuildKitEnabled() (bool, error)
|
||||||
ContextStore() store.Store
|
ContextStore() store.Store
|
||||||
CurrentContext() string
|
CurrentContext() string
|
||||||
DockerEndpoint() docker.Endpoint
|
DockerEndpoint() docker.Endpoint
|
||||||
TelemetryClient
|
TelemetryClient
|
||||||
|
DeprecatedNotaryClient
|
||||||
|
DeprecatedManifestClient
|
||||||
}
|
}
|
||||||
|
|
||||||
// DockerCli is an instance the docker command line client.
|
// DockerCli is an instance the docker command line client.
|
||||||
@ -96,7 +88,7 @@ type DockerCli struct {
|
|||||||
enableGlobalMeter, enableGlobalTracer bool
|
enableGlobalMeter, enableGlobalTracer bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultVersion returns api.defaultVersion.
|
// DefaultVersion returns [api.DefaultVersion].
|
||||||
func (*DockerCli) DefaultVersion() string {
|
func (*DockerCli) DefaultVersion() string {
|
||||||
return api.DefaultVersion
|
return api.DefaultVersion
|
||||||
}
|
}
|
||||||
@ -202,16 +194,16 @@ func (cli *DockerCli) BuildKitEnabled() (bool, error) {
|
|||||||
|
|
||||||
// HooksEnabled returns whether plugin hooks are enabled.
|
// HooksEnabled returns whether plugin hooks are enabled.
|
||||||
func (cli *DockerCli) HooksEnabled() bool {
|
func (cli *DockerCli) HooksEnabled() bool {
|
||||||
// legacy support DOCKER_CLI_HINTS env var
|
// use DOCKER_CLI_HOOKS env var value if set and not empty
|
||||||
if v := os.Getenv("DOCKER_CLI_HINTS"); v != "" {
|
if v := os.Getenv("DOCKER_CLI_HOOKS"); v != "" {
|
||||||
enabled, err := strconv.ParseBool(v)
|
enabled, err := strconv.ParseBool(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return enabled
|
return enabled
|
||||||
}
|
}
|
||||||
// use DOCKER_CLI_HOOKS env var value if set and not empty
|
// legacy support DOCKER_CLI_HINTS env var
|
||||||
if v := os.Getenv("DOCKER_CLI_HOOKS"); v != "" {
|
if v := os.Getenv("DOCKER_CLI_HINTS"); v != "" {
|
||||||
enabled, err := strconv.ParseBool(v)
|
enabled, err := strconv.ParseBool(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
@ -230,21 +222,6 @@ func (cli *DockerCli) HooksEnabled() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// ManifestStore returns a store for local manifests
|
|
||||||
func (*DockerCli) ManifestStore() manifeststore.Store {
|
|
||||||
// TODO: support override default location from config file
|
|
||||||
return manifeststore.NewStore(filepath.Join(config.Dir(), "manifests"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// RegistryClient returns a client for communicating with a Docker distribution
|
|
||||||
// registry
|
|
||||||
func (cli *DockerCli) RegistryClient(allowInsecure bool) registryclient.RegistryClient {
|
|
||||||
resolver := func(ctx context.Context, index *registry.IndexInfo) registry.AuthConfig {
|
|
||||||
return ResolveAuthConfig(cli.ConfigFile(), index)
|
|
||||||
}
|
|
||||||
return registryclient.NewRegistryClient(resolver, UserAgent(), allowInsecure)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithInitializeClient is passed to DockerCli.Initialize by callers who wish to set a particular API Client for use by the CLI.
|
// WithInitializeClient is passed to DockerCli.Initialize by callers who wish to set a particular API Client for use by the CLI.
|
||||||
func WithInitializeClient(makeClient func(dockerCli *DockerCli) (client.APIClient, error)) CLIOption {
|
func WithInitializeClient(makeClient func(dockerCli *DockerCli) (client.APIClient, error)) CLIOption {
|
||||||
return func(dockerCli *DockerCli) error {
|
return func(dockerCli *DockerCli) error {
|
||||||
@ -292,6 +269,7 @@ func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions, ops ...CLIOption)
|
|||||||
if cli.enableGlobalTracer {
|
if cli.enableGlobalTracer {
|
||||||
cli.createGlobalTracerProvider(cli.baseCtx)
|
cli.createGlobalTracerProvider(cli.baseCtx)
|
||||||
}
|
}
|
||||||
|
filterResourceAttributesEnvvar()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -345,7 +323,10 @@ func resolveDockerEndpoint(s store.Reader, contextName string) (docker.Endpoint,
|
|||||||
|
|
||||||
// Resolve the Docker endpoint for the default context (based on config, env vars and CLI flags)
|
// Resolve the Docker endpoint for the default context (based on config, env vars and CLI flags)
|
||||||
func resolveDefaultDockerEndpoint(opts *cliflags.ClientOptions) (docker.Endpoint, error) {
|
func resolveDefaultDockerEndpoint(opts *cliflags.ClientOptions) (docker.Endpoint, error) {
|
||||||
host, err := getServerHost(opts.Hosts, opts.TLSOptions)
|
// defaultToTLS determines whether we should use a TLS host as default
|
||||||
|
// if nothing was configured by the user.
|
||||||
|
defaultToTLS := opts.TLSOptions != nil
|
||||||
|
host, err := getServerHost(opts.Hosts, defaultToTLS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return docker.Endpoint{}, err
|
return docker.Endpoint{}, err
|
||||||
}
|
}
|
||||||
@ -403,11 +384,6 @@ func (cli *DockerCli) initializeFromClient() {
|
|||||||
cli.client.NegotiateAPIVersionPing(ping)
|
cli.client.NegotiateAPIVersionPing(ping)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotaryClient provides a Notary Repository to interact with signed metadata for an image
|
|
||||||
func (cli *DockerCli) NotaryClient(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (notaryclient.Repository, error) {
|
|
||||||
return trust.GetNotaryRepository(cli.In(), cli.Out(), UserAgent(), imgRefAndAuth.RepoInfo(), imgRefAndAuth.AuthConfig(), actions...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContextStore returns the ContextStore
|
// ContextStore returns the ContextStore
|
||||||
func (cli *DockerCli) ContextStore() store.Store {
|
func (cli *DockerCli) ContextStore() store.Store {
|
||||||
return cli.contextStore
|
return cli.contextStore
|
||||||
@ -553,18 +529,15 @@ func NewDockerCli(ops ...CLIOption) (*DockerCli, error) {
|
|||||||
return cli, nil
|
return cli, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getServerHost(hosts []string, tlsOptions *tlsconfig.Options) (string, error) {
|
func getServerHost(hosts []string, defaultToTLS bool) (string, error) {
|
||||||
var host string
|
|
||||||
switch len(hosts) {
|
switch len(hosts) {
|
||||||
case 0:
|
case 0:
|
||||||
host = os.Getenv(client.EnvOverrideHost)
|
return dopts.ParseHost(defaultToTLS, os.Getenv(client.EnvOverrideHost))
|
||||||
case 1:
|
case 1:
|
||||||
host = hosts[0]
|
return dopts.ParseHost(defaultToTLS, hosts[0])
|
||||||
default:
|
default:
|
||||||
return "", errors.New("Specify only one -H")
|
return "", errors.New("Specify only one -H")
|
||||||
}
|
}
|
||||||
|
|
||||||
return dopts.ParseHost(tlsOptions != nil, host)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserAgent returns the user agent string used for making API requests
|
// UserAgent returns the user agent string used for making API requests
|
||||||
|
56
vendor/github.com/docker/cli/cli/command/cli_deprecated.go
generated
vendored
Normal file
56
vendor/github.com/docker/cli/cli/command/cli_deprecated.go
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/docker/cli/cli/config"
|
||||||
|
manifeststore "github.com/docker/cli/cli/manifest/store"
|
||||||
|
registryclient "github.com/docker/cli/cli/registry/client"
|
||||||
|
"github.com/docker/cli/cli/trust"
|
||||||
|
"github.com/docker/docker/api/types/registry"
|
||||||
|
notaryclient "github.com/theupdateframework/notary/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DeprecatedNotaryClient interface {
|
||||||
|
// NotaryClient provides a Notary Repository to interact with signed metadata for an image
|
||||||
|
//
|
||||||
|
// Deprecated: use [trust.GetNotaryRepository] instead. This method is no longer used and will be removed in the next release.
|
||||||
|
NotaryClient(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (notaryclient.Repository, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeprecatedManifestClient interface {
|
||||||
|
// ManifestStore returns a store for local manifests
|
||||||
|
//
|
||||||
|
// Deprecated: use [manifeststore.NewStore] instead. This method is no longer used and will be removed in the next release.
|
||||||
|
ManifestStore() manifeststore.Store
|
||||||
|
|
||||||
|
// RegistryClient returns a client for communicating with a Docker distribution
|
||||||
|
// registry.
|
||||||
|
//
|
||||||
|
// Deprecated: use [registryclient.NewRegistryClient]. This method is no longer used and will be removed in the next release.
|
||||||
|
RegistryClient(bool) registryclient.RegistryClient
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotaryClient provides a Notary Repository to interact with signed metadata for an image
|
||||||
|
func (cli *DockerCli) NotaryClient(imgRefAndAuth trust.ImageRefAndAuth, actions []string) (notaryclient.Repository, error) {
|
||||||
|
return trust.GetNotaryRepository(cli.In(), cli.Out(), UserAgent(), imgRefAndAuth.RepoInfo(), imgRefAndAuth.AuthConfig(), actions...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ManifestStore returns a store for local manifests
|
||||||
|
//
|
||||||
|
// Deprecated: use [manifeststore.NewStore] instead. This method is no longer used and will be removed in the next release.
|
||||||
|
func (*DockerCli) ManifestStore() manifeststore.Store {
|
||||||
|
return manifeststore.NewStore(filepath.Join(config.Dir(), "manifests"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegistryClient returns a client for communicating with a Docker distribution
|
||||||
|
// registry
|
||||||
|
//
|
||||||
|
// Deprecated: use [registryclient.NewRegistryClient]. This method is no longer used and will be removed in the next release.
|
||||||
|
func (cli *DockerCli) RegistryClient(allowInsecure bool) registryclient.RegistryClient {
|
||||||
|
resolver := func(ctx context.Context, index *registry.IndexInfo) registry.AuthConfig {
|
||||||
|
return ResolveAuthConfig(cli.ConfigFile(), index)
|
||||||
|
}
|
||||||
|
return registryclient.NewRegistryClient(resolver, UserAgent(), allowInsecure)
|
||||||
|
}
|
29
vendor/github.com/docker/cli/cli/command/formatter/displayutils.go
generated
vendored
29
vendor/github.com/docker/cli/cli/command/formatter/displayutils.go
generated
vendored
@ -1,6 +1,11 @@
|
|||||||
|
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
|
||||||
|
//go:build go1.22
|
||||||
|
|
||||||
package formatter
|
package formatter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"golang.org/x/text/width"
|
"golang.org/x/text/width"
|
||||||
@ -59,3 +64,27 @@ func Ellipsis(s string, maxDisplayWidth int) string {
|
|||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// capitalizeFirst capitalizes the first character of string
|
||||||
|
func capitalizeFirst(s string) string {
|
||||||
|
switch l := len(s); l {
|
||||||
|
case 0:
|
||||||
|
return s
|
||||||
|
case 1:
|
||||||
|
return strings.ToLower(s)
|
||||||
|
default:
|
||||||
|
return strings.ToUpper(string(s[0])) + strings.ToLower(s[1:])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrettyPrint outputs arbitrary data for human formatted output by uppercasing the first letter.
|
||||||
|
func PrettyPrint(i any) string {
|
||||||
|
switch t := i.(type) {
|
||||||
|
case nil:
|
||||||
|
return "None"
|
||||||
|
case string:
|
||||||
|
return capitalizeFirst(t)
|
||||||
|
default:
|
||||||
|
return capitalizeFirst(fmt.Sprintf("%s", t))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
4
vendor/github.com/docker/cli/cli/command/formatter/formatter.go
generated
vendored
4
vendor/github.com/docker/cli/cli/command/formatter/formatter.go
generated
vendored
@ -76,9 +76,9 @@ func (c *Context) preFormat() {
|
|||||||
func (c *Context) parseFormat() (*template.Template, error) {
|
func (c *Context) parseFormat() (*template.Template, error) {
|
||||||
tmpl, err := templates.Parse(c.finalFormat)
|
tmpl, err := templates.Parse(c.finalFormat)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return tmpl, errors.Wrap(err, "template parsing error")
|
return nil, errors.Wrap(err, "template parsing error")
|
||||||
}
|
}
|
||||||
return tmpl, err
|
return tmpl, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) postFormat(tmpl *template.Template, subContext SubContext) {
|
func (c *Context) postFormat(tmpl *template.Template, subContext SubContext) {
|
||||||
|
51
vendor/github.com/docker/cli/cli/command/telemetry.go
generated
vendored
51
vendor/github.com/docker/cli/cli/command/telemetry.go
generated
vendored
@ -4,10 +4,11 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/docker/distribution/uuid"
|
"github.com/google/uuid"
|
||||||
"go.opentelemetry.io/otel"
|
"go.opentelemetry.io/otel"
|
||||||
"go.opentelemetry.io/otel/metric"
|
"go.opentelemetry.io/otel/metric"
|
||||||
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
|
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
|
||||||
@ -142,7 +143,7 @@ func defaultResourceOptions() []resource.Option {
|
|||||||
// of the CLI is its own instance. Without this, downstream
|
// of the CLI is its own instance. Without this, downstream
|
||||||
// OTEL processors may think the same process is restarting
|
// OTEL processors may think the same process is restarting
|
||||||
// continuously.
|
// continuously.
|
||||||
semconv.ServiceInstanceID(uuid.Generate().String()),
|
semconv.ServiceInstanceID(uuid.NewString()),
|
||||||
),
|
),
|
||||||
resource.WithFromEnv(),
|
resource.WithFromEnv(),
|
||||||
resource.WithTelemetrySDK(),
|
resource.WithTelemetrySDK(),
|
||||||
@ -216,3 +217,49 @@ func (r *cliReader) ForceFlush(ctx context.Context) error {
|
|||||||
func deltaTemporality(_ sdkmetric.InstrumentKind) metricdata.Temporality {
|
func deltaTemporality(_ sdkmetric.InstrumentKind) metricdata.Temporality {
|
||||||
return metricdata.DeltaTemporality
|
return metricdata.DeltaTemporality
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// resourceAttributesEnvVar is the name of the envvar that includes additional
|
||||||
|
// resource attributes for OTEL as defined in the [OpenTelemetry specification].
|
||||||
|
//
|
||||||
|
// [OpenTelemetry specification]: https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#general-sdk-configuration
|
||||||
|
const resourceAttributesEnvVar = "OTEL_RESOURCE_ATTRIBUTES"
|
||||||
|
|
||||||
|
func filterResourceAttributesEnvvar() {
|
||||||
|
if v := os.Getenv(resourceAttributesEnvVar); v != "" {
|
||||||
|
if filtered := filterResourceAttributes(v); filtered != "" {
|
||||||
|
_ = os.Setenv(resourceAttributesEnvVar, filtered)
|
||||||
|
} else {
|
||||||
|
_ = os.Unsetenv(resourceAttributesEnvVar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// dockerCLIAttributePrefix is the prefix for any docker cli OTEL attributes.
|
||||||
|
// When updating, make sure to also update the copy in cli-plugins/manager.
|
||||||
|
//
|
||||||
|
// TODO(thaJeztah): move telemetry-related code to an (internal) package to reduce dependency on cli/command in cli-plugins, which has too many imports.
|
||||||
|
const dockerCLIAttributePrefix = "docker.cli."
|
||||||
|
|
||||||
|
func filterResourceAttributes(s string) string {
|
||||||
|
if trimmed := strings.TrimSpace(s); trimmed == "" {
|
||||||
|
return trimmed
|
||||||
|
}
|
||||||
|
|
||||||
|
pairs := strings.Split(s, ",")
|
||||||
|
elems := make([]string, 0, len(pairs))
|
||||||
|
for _, p := range pairs {
|
||||||
|
k, _, found := strings.Cut(p, "=")
|
||||||
|
if !found {
|
||||||
|
// Do not interact with invalid otel resources.
|
||||||
|
elems = append(elems, p)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip attributes that have our docker.cli prefix.
|
||||||
|
if strings.HasPrefix(k, dockerCLIAttributePrefix) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
elems = append(elems, p)
|
||||||
|
}
|
||||||
|
return strings.Join(elems, ",")
|
||||||
|
}
|
||||||
|
79
vendor/github.com/docker/cli/cli/command/utils.go
generated
vendored
79
vendor/github.com/docker/cli/cli/command/utils.go
generated
vendored
@ -13,10 +13,9 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/docker/cli/cli/config"
|
||||||
"github.com/docker/cli/cli/streams"
|
"github.com/docker/cli/cli/streams"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
mounttypes "github.com/docker/docker/api/types/mount"
|
|
||||||
"github.com/docker/docker/api/types/versions"
|
|
||||||
"github.com/docker/docker/errdefs"
|
"github.com/docker/docker/errdefs"
|
||||||
"github.com/moby/sys/sequential"
|
"github.com/moby/sys/sequential"
|
||||||
"github.com/moby/term"
|
"github.com/moby/term"
|
||||||
@ -51,30 +50,6 @@ func CopyToFile(outfile string, r io.Reader) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// capitalizeFirst capitalizes the first character of string
|
|
||||||
func capitalizeFirst(s string) string {
|
|
||||||
switch l := len(s); l {
|
|
||||||
case 0:
|
|
||||||
return s
|
|
||||||
case 1:
|
|
||||||
return strings.ToLower(s)
|
|
||||||
default:
|
|
||||||
return strings.ToUpper(string(s[0])) + strings.ToLower(s[1:])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrettyPrint outputs arbitrary data for human formatted output by uppercasing the first letter.
|
|
||||||
func PrettyPrint(i any) string {
|
|
||||||
switch t := i.(type) {
|
|
||||||
case nil:
|
|
||||||
return "None"
|
|
||||||
case string:
|
|
||||||
return capitalizeFirst(t)
|
|
||||||
default:
|
|
||||||
return capitalizeFirst(fmt.Sprintf("%s", t))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var ErrPromptTerminated = errdefs.Cancelled(errors.New("prompt terminated"))
|
var ErrPromptTerminated = errdefs.Cancelled(errors.New("prompt terminated"))
|
||||||
|
|
||||||
// DisableInputEcho disables input echo on the provided streams.In.
|
// DisableInputEcho disables input echo on the provided streams.In.
|
||||||
@ -166,11 +141,12 @@ func PromptForConfirmation(ctx context.Context, ins io.Reader, outs io.Writer, m
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PruneFilters returns consolidated prune filters obtained from config.json and cli
|
// PruneFilters returns consolidated prune filters obtained from config.json and cli
|
||||||
func PruneFilters(dockerCli Cli, pruneFilters filters.Args) filters.Args {
|
func PruneFilters(dockerCLI config.Provider, pruneFilters filters.Args) filters.Args {
|
||||||
if dockerCli.ConfigFile() == nil {
|
cfg := dockerCLI.ConfigFile()
|
||||||
|
if cfg == nil {
|
||||||
return pruneFilters
|
return pruneFilters
|
||||||
}
|
}
|
||||||
for _, f := range dockerCli.ConfigFile().PruneFilters {
|
for _, f := range cfg.PruneFilters {
|
||||||
k, v, ok := strings.Cut(f, "=")
|
k, v, ok := strings.Cut(f, "=")
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
@ -239,48 +215,3 @@ func ValidateOutputPathFileMode(fileMode os.FileMode) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func stringSliceIndex(s, subs []string) int {
|
|
||||||
j := 0
|
|
||||||
if len(subs) > 0 {
|
|
||||||
for i, x := range s {
|
|
||||||
if j < len(subs) && subs[j] == x {
|
|
||||||
j++
|
|
||||||
} else {
|
|
||||||
j = 0
|
|
||||||
}
|
|
||||||
if len(subs) == j {
|
|
||||||
return i + 1 - j
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringSliceReplaceAt replaces the sub-slice find, with the sub-slice replace, in the string
|
|
||||||
// slice s, returning a new slice and a boolean indicating if the replacement happened.
|
|
||||||
// requireIdx is the index at which old needs to be found at (or -1 to disregard that).
|
|
||||||
func StringSliceReplaceAt(s, find, replace []string, requireIndex int) ([]string, bool) {
|
|
||||||
idx := stringSliceIndex(s, find)
|
|
||||||
if (requireIndex != -1 && requireIndex != idx) || idx == -1 {
|
|
||||||
return s, false
|
|
||||||
}
|
|
||||||
out := append([]string{}, s[:idx]...)
|
|
||||||
out = append(out, replace...)
|
|
||||||
out = append(out, s[idx+len(find):]...)
|
|
||||||
return out, true
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateMountWithAPIVersion validates a mount with the server API version.
|
|
||||||
func ValidateMountWithAPIVersion(m mounttypes.Mount, serverAPIVersion string) error {
|
|
||||||
if m.BindOptions != nil {
|
|
||||||
if m.BindOptions.NonRecursive && versions.LessThan(serverAPIVersion, "1.40") {
|
|
||||||
return errors.Errorf("bind-recursive=disabled requires API v1.40 or later")
|
|
||||||
}
|
|
||||||
// ReadOnlyNonRecursive can be safely ignored when API < 1.44
|
|
||||||
if m.BindOptions.ReadOnlyForceRecursive && versions.LessThan(serverAPIVersion, "1.44") {
|
|
||||||
return errors.Errorf("bind-recursive=readonly requires API v1.44 or later")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
5
vendor/github.com/docker/cli/cli/config/config.go
generated
vendored
5
vendor/github.com/docker/cli/cli/config/config.go
generated
vendored
@ -69,6 +69,11 @@ func getHomeDir() string {
|
|||||||
return home
|
return home
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Provider defines an interface for providing the CLI config.
|
||||||
|
type Provider interface {
|
||||||
|
ConfigFile() *configfile.ConfigFile
|
||||||
|
}
|
||||||
|
|
||||||
// Dir returns the directory the configuration file is stored in
|
// Dir returns the directory the configuration file is stored in
|
||||||
func Dir() string {
|
func Dir() string {
|
||||||
initConfigDir.Do(func() {
|
initConfigDir.Do(func() {
|
||||||
|
68
vendor/github.com/docker/cli/cli/internal/jsonstream/display.go
generated
vendored
Normal file
68
vendor/github.com/docker/cli/cli/internal/jsonstream/display.go
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
package jsonstream
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/docker/docker/pkg/jsonmessage"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
Stream = jsonmessage.Stream
|
||||||
|
JSONMessage = jsonmessage.JSONMessage
|
||||||
|
JSONError = jsonmessage.JSONError
|
||||||
|
JSONProgress = jsonmessage.JSONProgress
|
||||||
|
)
|
||||||
|
|
||||||
|
type ctxReader struct {
|
||||||
|
err chan error
|
||||||
|
r io.Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ctxReader) Read(p []byte) (n int, err error) {
|
||||||
|
select {
|
||||||
|
case err = <-r.err:
|
||||||
|
return 0, err
|
||||||
|
default:
|
||||||
|
return r.r.Read(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Options func(*options)
|
||||||
|
|
||||||
|
type options struct {
|
||||||
|
AuxCallback func(JSONMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithAuxCallback(cb func(JSONMessage)) Options {
|
||||||
|
return func(o *options) {
|
||||||
|
o.AuxCallback = cb
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display prints the JSON messages from the given reader to the given stream.
|
||||||
|
//
|
||||||
|
// It wraps the [jsonmessage.DisplayJSONMessagesStream] function to make it
|
||||||
|
// "context aware" and appropriately returns why the function was canceled.
|
||||||
|
//
|
||||||
|
// It returns an error if the context is canceled, but not if the input reader / stream is closed.
|
||||||
|
func Display(ctx context.Context, in io.Reader, stream Stream, opts ...Options) error {
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
reader := &ctxReader{err: make(chan error, 1), r: in}
|
||||||
|
stopFunc := context.AfterFunc(ctx, func() { reader.err <- ctx.Err() })
|
||||||
|
defer stopFunc()
|
||||||
|
|
||||||
|
o := options{}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(&o)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := jsonmessage.DisplayJSONMessagesStream(reader, stream, stream.FD(), stream.IsTerminal(), o.AuxCallback); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
33
vendor/github.com/docker/cli/cli/registry/client/client.go
generated
vendored
33
vendor/github.com/docker/cli/cli/registry/client/client.go
generated
vendored
@ -8,7 +8,6 @@ import (
|
|||||||
|
|
||||||
"github.com/distribution/reference"
|
"github.com/distribution/reference"
|
||||||
manifesttypes "github.com/docker/cli/cli/manifest/types"
|
manifesttypes "github.com/docker/cli/cli/manifest/types"
|
||||||
"github.com/docker/cli/cli/trust"
|
|
||||||
"github.com/docker/distribution"
|
"github.com/docker/distribution"
|
||||||
distributionclient "github.com/docker/distribution/registry/client"
|
distributionclient "github.com/docker/distribution/registry/client"
|
||||||
registrytypes "github.com/docker/docker/api/types/registry"
|
registrytypes "github.com/docker/docker/api/types/registry"
|
||||||
@ -38,12 +37,6 @@ func NewRegistryClient(resolver AuthConfigResolver, userAgent string, insecure b
|
|||||||
// AuthConfigResolver returns Auth Configuration for an index
|
// AuthConfigResolver returns Auth Configuration for an index
|
||||||
type AuthConfigResolver func(ctx context.Context, index *registrytypes.IndexInfo) registrytypes.AuthConfig
|
type AuthConfigResolver func(ctx context.Context, index *registrytypes.IndexInfo) registrytypes.AuthConfig
|
||||||
|
|
||||||
// PutManifestOptions is the data sent to push a manifest
|
|
||||||
type PutManifestOptions struct {
|
|
||||||
MediaType string
|
|
||||||
Payload []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type client struct {
|
type client struct {
|
||||||
authConfigResolver AuthConfigResolver
|
authConfigResolver AuthConfigResolver
|
||||||
insecureRegistry bool
|
insecureRegistry bool
|
||||||
@ -61,13 +54,13 @@ func (err ErrBlobCreated) Error() string {
|
|||||||
err.From, err.Target)
|
err.From, err.Target)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrHTTPProto returned if attempting to use TLS with a non-TLS registry
|
// httpProtoError returned if attempting to use TLS with a non-TLS registry
|
||||||
type ErrHTTPProto struct {
|
type httpProtoError struct {
|
||||||
OrigErr string
|
cause error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (err ErrHTTPProto) Error() string {
|
func (e httpProtoError) Error() string {
|
||||||
return err.OrigErr
|
return e.cause.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ RegistryClient = &client{}
|
var _ RegistryClient = &client{}
|
||||||
@ -78,7 +71,7 @@ func (c *client) MountBlob(ctx context.Context, sourceRef reference.Canonical, t
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
repoEndpoint.actions = trust.ActionsPushAndPull
|
repoEndpoint.actions = []string{"pull", "push"}
|
||||||
repo, err := c.getRepositoryForReference(ctx, targetRef, repoEndpoint)
|
repo, err := c.getRepositoryForReference(ctx, targetRef, repoEndpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -104,7 +97,7 @@ func (c *client) PutManifest(ctx context.Context, ref reference.Named, manifest
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
repoEndpoint.actions = trust.ActionsPushAndPull
|
repoEndpoint.actions = []string{"pull", "push"}
|
||||||
repo, err := c.getRepositoryForReference(ctx, ref, repoEndpoint)
|
repo, err := c.getRepositoryForReference(ctx, ref, repoEndpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@ -121,7 +114,10 @@ func (c *client) PutManifest(ctx context.Context, ref reference.Named, manifest
|
|||||||
}
|
}
|
||||||
|
|
||||||
dgst, err := manifestService.Put(ctx, manifest, opts...)
|
dgst, err := manifestService.Put(ctx, manifest, opts...)
|
||||||
return dgst, errors.Wrapf(err, "failed to put manifest %s", ref)
|
if err != nil {
|
||||||
|
return dgst, errors.Wrapf(err, "failed to put manifest %s", ref)
|
||||||
|
}
|
||||||
|
return dgst, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *client) getRepositoryForReference(ctx context.Context, ref reference.Named, repoEndpoint repositoryEndpoint) (distribution.Repository, error) {
|
func (c *client) getRepositoryForReference(ctx context.Context, ref reference.Named, repoEndpoint repositoryEndpoint) (distribution.Repository, error) {
|
||||||
@ -135,7 +131,7 @@ func (c *client) getRepositoryForReference(ctx context.Context, ref reference.Na
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if !repoEndpoint.endpoint.TLSConfig.InsecureSkipVerify {
|
if !repoEndpoint.endpoint.TLSConfig.InsecureSkipVerify {
|
||||||
return nil, ErrHTTPProto{OrigErr: err.Error()}
|
return nil, httpProtoError{cause: err}
|
||||||
}
|
}
|
||||||
// --insecure was set; fall back to plain HTTP
|
// --insecure was set; fall back to plain HTTP
|
||||||
if url := repoEndpoint.endpoint.URL; url != nil && url.Scheme == "https" {
|
if url := repoEndpoint.endpoint.URL; url != nil && url.Scheme == "https" {
|
||||||
@ -157,7 +153,10 @@ func (c *client) getHTTPTransportForRepoEndpoint(ctx context.Context, repoEndpoi
|
|||||||
c.userAgent,
|
c.userAgent,
|
||||||
repoEndpoint.actions,
|
repoEndpoint.actions,
|
||||||
)
|
)
|
||||||
return httpTransport, errors.Wrap(err, "failed to configure transport")
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to configure transport")
|
||||||
|
}
|
||||||
|
return httpTransport, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetManifest returns an ImageManifest for the reference
|
// GetManifest returns an ImageManifest for the reference
|
||||||
|
19
vendor/github.com/docker/cli/cli/registry/client/endpoint.go
generated
vendored
19
vendor/github.com/docker/cli/cli/registry/client/endpoint.go
generated
vendored
@ -6,7 +6,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/distribution/reference"
|
"github.com/distribution/reference"
|
||||||
"github.com/docker/cli/cli/trust"
|
|
||||||
"github.com/docker/distribution/registry/client/auth"
|
"github.com/docker/distribution/registry/client/auth"
|
||||||
"github.com/docker/distribution/registry/client/transport"
|
"github.com/docker/distribution/registry/client/transport"
|
||||||
registrytypes "github.com/docker/docker/api/types/registry"
|
registrytypes "github.com/docker/docker/api/types/registry"
|
||||||
@ -31,10 +30,7 @@ func (r repositoryEndpoint) BaseURL() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newDefaultRepositoryEndpoint(ref reference.Named, insecure bool) (repositoryEndpoint, error) {
|
func newDefaultRepositoryEndpoint(ref reference.Named, insecure bool) (repositoryEndpoint, error) {
|
||||||
repoInfo, err := registry.ParseRepositoryInfo(ref)
|
repoInfo, _ := registry.ParseRepositoryInfo(ref)
|
||||||
if err != nil {
|
|
||||||
return repositoryEndpoint{}, err
|
|
||||||
}
|
|
||||||
endpoint, err := getDefaultEndpointFromRepoInfo(repoInfo)
|
endpoint, err := getDefaultEndpointFromRepoInfo(repoInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return repositoryEndpoint{}, err
|
return repositoryEndpoint{}, err
|
||||||
@ -94,7 +90,7 @@ func getHTTPTransport(authConfig registrytypes.AuthConfig, endpoint registry.API
|
|||||||
modifiers = append(modifiers, auth.NewAuthorizer(challengeManager, passThruTokenHandler))
|
modifiers = append(modifiers, auth.NewAuthorizer(challengeManager, passThruTokenHandler))
|
||||||
} else {
|
} else {
|
||||||
if len(actions) == 0 {
|
if len(actions) == 0 {
|
||||||
actions = trust.ActionsPullOnly
|
actions = []string{"pull"}
|
||||||
}
|
}
|
||||||
creds := registry.NewStaticCredentialStore(&authConfig)
|
creds := registry.NewStaticCredentialStore(&authConfig)
|
||||||
tokenHandler := auth.NewTokenHandler(authTransport, creds, repoName, actions...)
|
tokenHandler := auth.NewTokenHandler(authTransport, creds, repoName, actions...)
|
||||||
@ -104,14 +100,11 @@ func getHTTPTransport(authConfig registrytypes.AuthConfig, endpoint registry.API
|
|||||||
return transport.NewTransport(base, modifiers...), nil
|
return transport.NewTransport(base, modifiers...), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RepoNameForReference returns the repository name from a reference
|
// RepoNameForReference returns the repository name from a reference.
|
||||||
|
//
|
||||||
|
// Deprecated: this function is no longer used and will be removed in the next release.
|
||||||
func RepoNameForReference(ref reference.Named) (string, error) {
|
func RepoNameForReference(ref reference.Named) (string, error) {
|
||||||
// insecure is fine since this only returns the name
|
return reference.Path(reference.TrimNamed(ref)), nil
|
||||||
repo, err := newDefaultRepositoryEndpoint(ref, false)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return repo.Name(), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type existingTokenHandler struct {
|
type existingTokenHandler struct {
|
||||||
|
14
vendor/github.com/docker/cli/cli/registry/client/fetcher.go
generated
vendored
14
vendor/github.com/docker/cli/cli/registry/client/fetcher.go
generated
vendored
@ -220,10 +220,7 @@ func (c *client) iterateEndpoints(ctx context.Context, namedRef reference.Named,
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
repoInfo, err := registry.ParseRepositoryInfo(namedRef)
|
repoInfo, _ := registry.ParseRepositoryInfo(namedRef)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
confirmedTLSRegistries := make(map[string]bool)
|
confirmedTLSRegistries := make(map[string]bool)
|
||||||
for _, endpoint := range endpoints {
|
for _, endpoint := range endpoints {
|
||||||
@ -241,7 +238,8 @@ func (c *client) iterateEndpoints(ctx context.Context, namedRef reference.Named,
|
|||||||
repo, err := c.getRepositoryForReference(ctx, namedRef, repoEndpoint)
|
repo, err := c.getRepositoryForReference(ctx, namedRef, repoEndpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Debugf("error %s with repo endpoint %+v", err, repoEndpoint)
|
logrus.Debugf("error %s with repo endpoint %+v", err, repoEndpoint)
|
||||||
if _, ok := err.(ErrHTTPProto); ok {
|
var protoErr httpProtoError
|
||||||
|
if errors.As(err, &protoErr) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
@ -272,11 +270,6 @@ func (c *client) iterateEndpoints(ctx context.Context, namedRef reference.Named,
|
|||||||
|
|
||||||
// allEndpoints returns a list of endpoints ordered by priority (v2, http).
|
// allEndpoints returns a list of endpoints ordered by priority (v2, http).
|
||||||
func allEndpoints(namedRef reference.Named, insecure bool) ([]registry.APIEndpoint, error) {
|
func allEndpoints(namedRef reference.Named, insecure bool) ([]registry.APIEndpoint, error) {
|
||||||
repoInfo, err := registry.ParseRepositoryInfo(namedRef)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var serviceOpts registry.ServiceOptions
|
var serviceOpts registry.ServiceOptions
|
||||||
if insecure {
|
if insecure {
|
||||||
logrus.Debugf("allowing insecure registry for: %s", reference.Domain(namedRef))
|
logrus.Debugf("allowing insecure registry for: %s", reference.Domain(namedRef))
|
||||||
@ -286,6 +279,7 @@ func allEndpoints(namedRef reference.Named, insecure bool) ([]registry.APIEndpoi
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return []registry.APIEndpoint{}, err
|
return []registry.APIEndpoint{}, err
|
||||||
}
|
}
|
||||||
|
repoInfo, _ := registry.ParseRepositoryInfo(namedRef)
|
||||||
endpoints, err := registryService.LookupPullEndpoints(reference.Domain(repoInfo.Name))
|
endpoints, err := registryService.LookupPullEndpoints(reference.Domain(repoInfo.Name))
|
||||||
logrus.Debugf("endpoints for %s: %v", namedRef, endpoints)
|
logrus.Debugf("endpoints for %s: %v", namedRef, endpoints)
|
||||||
return endpoints, err
|
return endpoints, err
|
||||||
|
25
vendor/github.com/docker/cli/cli/trust/trust.go
generated
vendored
25
vendor/github.com/docker/cli/cli/trust/trust.go
generated
vendored
@ -40,10 +40,11 @@ var (
|
|||||||
ActionsPullOnly = []string{"pull"}
|
ActionsPullOnly = []string{"pull"}
|
||||||
// ActionsPushAndPull defines the actions for read-write interactions with a Notary Repository
|
// ActionsPushAndPull defines the actions for read-write interactions with a Notary Repository
|
||||||
ActionsPushAndPull = []string{"pull", "push"}
|
ActionsPushAndPull = []string{"pull", "push"}
|
||||||
// NotaryServer is the endpoint serving the Notary trust server
|
|
||||||
NotaryServer = "https://notary.docker.io"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NotaryServer is the endpoint serving the Notary trust server
|
||||||
|
const NotaryServer = "https://notary.docker.io"
|
||||||
|
|
||||||
// GetTrustDirectory returns the base trust directory name
|
// GetTrustDirectory returns the base trust directory name
|
||||||
func GetTrustDirectory() string {
|
func GetTrustDirectory() string {
|
||||||
return filepath.Join(config.Dir(), "trust")
|
return filepath.Join(config.Dir(), "trust")
|
||||||
@ -238,6 +239,20 @@ func NotaryError(repoName string, err error) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddToAllSignableRoles attempts to add the image target to all the top level
|
||||||
|
// delegation roles we can (based on whether we have the signing key and whether
|
||||||
|
// the role's path allows us to).
|
||||||
|
//
|
||||||
|
// If there are no delegation roles, we add to the targets role.
|
||||||
|
func AddToAllSignableRoles(repo client.Repository, target *client.Target) error {
|
||||||
|
signableRoles, err := GetSignableRoles(repo, target)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return repo.AddTarget(target, signableRoles...)
|
||||||
|
}
|
||||||
|
|
||||||
// GetSignableRoles returns a list of roles for which we have valid signing
|
// GetSignableRoles returns a list of roles for which we have valid signing
|
||||||
// keys, given a notary repository and a target
|
// keys, given a notary repository and a target
|
||||||
func GetSignableRoles(repo client.Repository, target *client.Target) ([]data.RoleName, error) {
|
func GetSignableRoles(repo client.Repository, target *client.Target) ([]data.RoleName, error) {
|
||||||
@ -307,11 +322,7 @@ func GetImageReferencesAndAuth(ctx context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Resolve the Repository name from fqn to RepositoryInfo
|
// Resolve the Repository name from fqn to RepositoryInfo
|
||||||
repoInfo, err := registry.ParseRepositoryInfo(ref)
|
repoInfo, _ := registry.ParseRepositoryInfo(ref)
|
||||||
if err != nil {
|
|
||||||
return ImageRefAndAuth{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
authConfig := authResolver(ctx, repoInfo.Index)
|
authConfig := authResolver(ctx, repoInfo.Index)
|
||||||
return ImageRefAndAuth{
|
return ImageRefAndAuth{
|
||||||
original: imgName,
|
original: imgName,
|
||||||
|
143
vendor/github.com/docker/cli/cli/trust/trust_push.go
generated
vendored
Normal file
143
vendor/github.com/docker/cli/cli/trust/trust_push.go
generated
vendored
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
package trust
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/distribution/reference"
|
||||||
|
"github.com/docker/cli/cli/internal/jsonstream"
|
||||||
|
"github.com/docker/cli/cli/streams"
|
||||||
|
"github.com/docker/docker/api/types"
|
||||||
|
registrytypes "github.com/docker/docker/api/types/registry"
|
||||||
|
"github.com/docker/docker/registry"
|
||||||
|
"github.com/opencontainers/go-digest"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/theupdateframework/notary/client"
|
||||||
|
"github.com/theupdateframework/notary/tuf/data"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Streams is an interface which exposes the standard input and output streams.
|
||||||
|
//
|
||||||
|
// Same interface as [github.com/docker/cli/cli/command.Streams] but defined here to prevent a circular import.
|
||||||
|
type Streams interface {
|
||||||
|
In() *streams.In
|
||||||
|
Out() *streams.Out
|
||||||
|
Err() *streams.Out
|
||||||
|
}
|
||||||
|
|
||||||
|
// PushTrustedReference pushes a canonical reference to the trust server.
|
||||||
|
//
|
||||||
|
//nolint:gocyclo
|
||||||
|
func PushTrustedReference(ctx context.Context, ioStreams Streams, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig registrytypes.AuthConfig, in io.Reader, userAgent string) error {
|
||||||
|
// If it is a trusted push we would like to find the target entry which match the
|
||||||
|
// tag provided in the function and then do an AddTarget later.
|
||||||
|
notaryTarget := &client.Target{}
|
||||||
|
// Count the times of calling for handleTarget,
|
||||||
|
// if it is called more that once, that should be considered an error in a trusted push.
|
||||||
|
cnt := 0
|
||||||
|
handleTarget := func(msg jsonstream.JSONMessage) {
|
||||||
|
cnt++
|
||||||
|
if cnt > 1 {
|
||||||
|
// handleTarget should only be called once. This will be treated as an error.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var pushResult types.PushResult
|
||||||
|
err := json.Unmarshal(*msg.Aux, &pushResult)
|
||||||
|
if err == nil && pushResult.Tag != "" {
|
||||||
|
if dgst, err := digest.Parse(pushResult.Digest); err == nil {
|
||||||
|
h, err := hex.DecodeString(dgst.Hex())
|
||||||
|
if err != nil {
|
||||||
|
notaryTarget = nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
notaryTarget.Name = pushResult.Tag
|
||||||
|
notaryTarget.Hashes = data.Hashes{string(dgst.Algorithm()): h}
|
||||||
|
notaryTarget.Length = int64(pushResult.Size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var tag string
|
||||||
|
switch x := ref.(type) {
|
||||||
|
case reference.Canonical:
|
||||||
|
return errors.New("cannot push a digest reference")
|
||||||
|
case reference.NamedTagged:
|
||||||
|
tag = x.Tag()
|
||||||
|
default:
|
||||||
|
// We want trust signatures to always take an explicit tag,
|
||||||
|
// otherwise it will act as an untrusted push.
|
||||||
|
if err := jsonstream.Display(ctx, in, ioStreams.Out()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, _ = fmt.Fprintln(ioStreams.Err(), "No tag specified, skipping trust metadata push")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := jsonstream.Display(ctx, in, ioStreams.Out(), jsonstream.WithAuxCallback(handleTarget)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if cnt > 1 {
|
||||||
|
return errors.Errorf("internal error: only one call to handleTarget expected")
|
||||||
|
}
|
||||||
|
|
||||||
|
if notaryTarget == nil {
|
||||||
|
return errors.Errorf("no targets found, provide a specific tag in order to sign it")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _ = fmt.Fprintln(ioStreams.Out(), "Signing and pushing trust metadata")
|
||||||
|
|
||||||
|
repo, err := GetNotaryRepository(ioStreams.In(), ioStreams.Out(), userAgent, repoInfo, &authConfig, "push", "pull")
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "error establishing connection to trust repository")
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the latest repository metadata so we can figure out which roles to sign
|
||||||
|
_, err = repo.ListTargets()
|
||||||
|
|
||||||
|
switch err.(type) {
|
||||||
|
case client.ErrRepoNotInitialized, client.ErrRepositoryNotExist:
|
||||||
|
keys := repo.GetCryptoService().ListKeys(data.CanonicalRootRole)
|
||||||
|
var rootKeyID string
|
||||||
|
// always select the first root key
|
||||||
|
if len(keys) > 0 {
|
||||||
|
sort.Strings(keys)
|
||||||
|
rootKeyID = keys[0]
|
||||||
|
} else {
|
||||||
|
rootPublicKey, err := repo.GetCryptoService().Create(data.CanonicalRootRole, "", data.ECDSAKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rootKeyID = rootPublicKey.ID()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the notary repository with a remotely managed snapshot key
|
||||||
|
if err := repo.Initialize([]string{rootKeyID}, data.CanonicalSnapshotRole); err != nil {
|
||||||
|
return NotaryError(repoInfo.Name.Name(), err)
|
||||||
|
}
|
||||||
|
_, _ = fmt.Fprintf(ioStreams.Out(), "Finished initializing %q\n", repoInfo.Name.Name())
|
||||||
|
err = repo.AddTarget(notaryTarget, data.CanonicalTargetsRole)
|
||||||
|
case nil:
|
||||||
|
// already initialized and we have successfully downloaded the latest metadata
|
||||||
|
err = AddToAllSignableRoles(repo, notaryTarget)
|
||||||
|
default:
|
||||||
|
return NotaryError(repoInfo.Name.Name(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
err = repo.Publish()
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
err = errors.Wrapf(err, "failed to sign %s:%s", repoInfo.Name.Name(), tag)
|
||||||
|
return NotaryError(repoInfo.Name.Name(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _ = fmt.Fprintf(ioStreams.Out(), "Successfully signed %s:%s\n", repoInfo.Name.Name(), tag)
|
||||||
|
return nil
|
||||||
|
}
|
22
vendor/github.com/docker/cli/cli/trust/trust_tag.go
generated
vendored
Normal file
22
vendor/github.com/docker/cli/cli/trust/trust_tag.go
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package trust
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/distribution/reference"
|
||||||
|
"github.com/docker/docker/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TagTrusted tags a trusted ref. It is a shallow wrapper around [client.Client.ImageTag]
|
||||||
|
// that updates the given image references to their familiar format for tagging
|
||||||
|
// and printing.
|
||||||
|
func TagTrusted(ctx context.Context, apiClient client.ImageAPIClient, out io.Writer, trustedRef reference.Canonical, ref reference.NamedTagged) error {
|
||||||
|
// Use familiar references when interacting with client and output
|
||||||
|
familiarRef := reference.FamiliarString(ref)
|
||||||
|
trustedFamiliarRef := reference.FamiliarString(trustedRef)
|
||||||
|
|
||||||
|
_, _ = fmt.Fprintf(out, "Tagging %s as %s\n", trustedFamiliarRef, familiarRef)
|
||||||
|
return apiClient.ImageTag(ctx, trustedFamiliarRef, familiarRef)
|
||||||
|
}
|
5
vendor/github.com/docker/cli/opts/duration.go
generated
vendored
5
vendor/github.com/docker/cli/opts/duration.go
generated
vendored
@ -1,9 +1,8 @@
|
|||||||
package opts
|
package opts
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// PositiveDurationOpt is an option type for time.Duration that uses a pointer.
|
// PositiveDurationOpt is an option type for time.Duration that uses a pointer.
|
||||||
@ -20,7 +19,7 @@ func (d *PositiveDurationOpt) Set(s string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if *d.DurationOpt.value < 0 {
|
if *d.DurationOpt.value < 0 {
|
||||||
return errors.Errorf("duration cannot be negative")
|
return errors.New("duration cannot be negative")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
3
vendor/github.com/docker/cli/opts/env.go
generated
vendored
3
vendor/github.com/docker/cli/opts/env.go
generated
vendored
@ -1,10 +1,9 @@
|
|||||||
package opts
|
package opts
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ValidateEnv validates an environment variable and returns it.
|
// ValidateEnv validates an environment variable and returns it.
|
||||||
|
13
vendor/github.com/docker/cli/opts/gpus.go
generated
vendored
13
vendor/github.com/docker/cli/opts/gpus.go
generated
vendored
@ -2,12 +2,12 @@ package opts
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/csv"
|
"encoding/csv"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GpuOpts is a Value type for parsing mounts
|
// GpuOpts is a Value type for parsing mounts
|
||||||
@ -20,7 +20,14 @@ func parseCount(s string) (int, error) {
|
|||||||
return -1, nil
|
return -1, nil
|
||||||
}
|
}
|
||||||
i, err := strconv.Atoi(s)
|
i, err := strconv.Atoi(s)
|
||||||
return i, errors.Wrap(err, "count must be an integer")
|
if err != nil {
|
||||||
|
var numErr *strconv.NumError
|
||||||
|
if errors.As(err, &numErr) {
|
||||||
|
err = numErr.Err
|
||||||
|
}
|
||||||
|
return 0, fmt.Errorf(`invalid count (%s): value must be either "all" or an integer: %w`, s, err)
|
||||||
|
}
|
||||||
|
return i, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set a new mount value
|
// Set a new mount value
|
||||||
@ -69,7 +76,7 @@ func (o *GpuOpts) Set(value string) error {
|
|||||||
r := csv.NewReader(strings.NewReader(val))
|
r := csv.NewReader(strings.NewReader(val))
|
||||||
optFields, err := r.Read()
|
optFields, err := r.Read()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to read gpu options")
|
return fmt.Errorf("failed to read gpu options: %w", err)
|
||||||
}
|
}
|
||||||
req.Options = ConvertKVStringsToMap(optFields)
|
req.Options = ConvertKVStringsToMap(optFields)
|
||||||
default:
|
default:
|
||||||
|
3
vendor/github.com/docker/cli/opts/mount.go
generated
vendored
3
vendor/github.com/docker/cli/opts/mount.go
generated
vendored
@ -135,8 +135,7 @@ func (m *MountOpt) Set(value string) error {
|
|||||||
// TODO: implicitly set propagation and error if the user specifies a propagation in a future refactor/UX polish pass
|
// TODO: implicitly set propagation and error if the user specifies a propagation in a future refactor/UX polish pass
|
||||||
// https://github.com/docker/cli/pull/4316#discussion_r1341974730
|
// https://github.com/docker/cli/pull/4316#discussion_r1341974730
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("invalid value for %s: %s (must be \"enabled\", \"disabled\", \"writable\", or \"readonly\")",
|
return fmt.Errorf(`invalid value for %s: %s (must be "enabled", "disabled", "writable", or "readonly")`, key, val)
|
||||||
key, val)
|
|
||||||
}
|
}
|
||||||
case "volume-subpath":
|
case "volume-subpath":
|
||||||
volumeOptions().Subpath = val
|
volumeOptions().Subpath = val
|
||||||
|
6
vendor/github.com/docker/cli/opts/network.go
generated
vendored
6
vendor/github.com/docker/cli/opts/network.go
generated
vendored
@ -89,7 +89,11 @@ func (n *NetworkOpt) Set(value string) error { //nolint:gocyclo
|
|||||||
case gwPriorityOpt:
|
case gwPriorityOpt:
|
||||||
netOpt.GwPriority, err = strconv.Atoi(val)
|
netOpt.GwPriority, err = strconv.Atoi(val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("invalid gw-priority: %w", err)
|
var numErr *strconv.NumError
|
||||||
|
if errors.As(err, &numErr) {
|
||||||
|
err = numErr.Err
|
||||||
|
}
|
||||||
|
return fmt.Errorf("invalid gw-priority (%s): %w", val, err)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return errors.New("invalid field key " + key)
|
return errors.New("invalid field key " + key)
|
||||||
|
4
vendor/github.com/docker/cli/opts/opts.go
generated
vendored
4
vendor/github.com/docker/cli/opts/opts.go
generated
vendored
@ -1,6 +1,7 @@
|
|||||||
package opts
|
package opts
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"net"
|
"net"
|
||||||
@ -9,8 +10,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
units "github.com/docker/go-units"
|
"github.com/docker/go-units"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
18
vendor/github.com/docker/cli/opts/opts_deprecated.go
generated
vendored
Normal file
18
vendor/github.com/docker/cli/opts/opts_deprecated.go
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package opts
|
||||||
|
|
||||||
|
import "github.com/docker/cli/opts/swarmopts"
|
||||||
|
|
||||||
|
// PortOpt represents a port config in swarm mode.
|
||||||
|
//
|
||||||
|
// Deprecated: use [swarmopts.PortOpt]
|
||||||
|
type PortOpt = swarmopts.PortOpt
|
||||||
|
|
||||||
|
// ConfigOpt is a Value type for parsing configs.
|
||||||
|
//
|
||||||
|
// Deprecated: use [swarmopts.ConfigOpt]
|
||||||
|
type ConfigOpt = swarmopts.ConfigOpt
|
||||||
|
|
||||||
|
// SecretOpt is a Value type for parsing secrets
|
||||||
|
//
|
||||||
|
// Deprecated: use [swarmopts.SecretOpt]
|
||||||
|
type SecretOpt = swarmopts.SecretOpt
|
@ -1,4 +1,4 @@
|
|||||||
package opts
|
package swarmopts
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/csv"
|
"encoding/csv"
|
||||||
@ -8,12 +8,12 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
swarmtypes "github.com/docker/docker/api/types/swarm"
|
"github.com/docker/docker/api/types/swarm"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ConfigOpt is a Value type for parsing configs
|
// ConfigOpt is a Value type for parsing configs
|
||||||
type ConfigOpt struct {
|
type ConfigOpt struct {
|
||||||
values []*swarmtypes.ConfigReference
|
values []*swarm.ConfigReference
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set a new config value
|
// Set a new config value
|
||||||
@ -24,8 +24,8 @@ func (o *ConfigOpt) Set(value string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
options := &swarmtypes.ConfigReference{
|
options := &swarm.ConfigReference{
|
||||||
File: &swarmtypes.ConfigReferenceFileTarget{
|
File: &swarm.ConfigReferenceFileTarget{
|
||||||
UID: "0",
|
UID: "0",
|
||||||
GID: "0",
|
GID: "0",
|
||||||
Mode: 0o444,
|
Mode: 0o444,
|
||||||
@ -95,6 +95,6 @@ func (o *ConfigOpt) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Value returns the config requests
|
// Value returns the config requests
|
||||||
func (o *ConfigOpt) Value() []*swarmtypes.ConfigReference {
|
func (o *ConfigOpt) Value() []*swarm.ConfigReference {
|
||||||
return o.values
|
return o.values
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package opts
|
package swarmopts
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/csv"
|
"encoding/csv"
|
||||||
@ -46,42 +46,50 @@ func (p *PortOpt) Set(value string) error {
|
|||||||
// TODO(thaJeztah): these options should not be case-insensitive.
|
// TODO(thaJeztah): these options should not be case-insensitive.
|
||||||
key, val, ok := strings.Cut(strings.ToLower(field), "=")
|
key, val, ok := strings.Cut(strings.ToLower(field), "=")
|
||||||
if !ok || key == "" {
|
if !ok || key == "" {
|
||||||
return fmt.Errorf("invalid field %s", field)
|
return fmt.Errorf("invalid field: %s", field)
|
||||||
}
|
}
|
||||||
switch key {
|
switch key {
|
||||||
case portOptProtocol:
|
case portOptProtocol:
|
||||||
if val != string(swarm.PortConfigProtocolTCP) && val != string(swarm.PortConfigProtocolUDP) && val != string(swarm.PortConfigProtocolSCTP) {
|
if val != string(swarm.PortConfigProtocolTCP) && val != string(swarm.PortConfigProtocolUDP) && val != string(swarm.PortConfigProtocolSCTP) {
|
||||||
return fmt.Errorf("invalid protocol value %s", val)
|
return fmt.Errorf("invalid protocol value '%s'", val)
|
||||||
}
|
}
|
||||||
|
|
||||||
pConfig.Protocol = swarm.PortConfigProtocol(val)
|
pConfig.Protocol = swarm.PortConfigProtocol(val)
|
||||||
case portOptMode:
|
case portOptMode:
|
||||||
if val != string(swarm.PortConfigPublishModeIngress) && val != string(swarm.PortConfigPublishModeHost) {
|
if val != string(swarm.PortConfigPublishModeIngress) && val != string(swarm.PortConfigPublishModeHost) {
|
||||||
return fmt.Errorf("invalid publish mode value %s", val)
|
return fmt.Errorf("invalid publish mode value (%s): must be either '%s' or '%s'", val, swarm.PortConfigPublishModeIngress, swarm.PortConfigPublishModeHost)
|
||||||
}
|
}
|
||||||
|
|
||||||
pConfig.PublishMode = swarm.PortConfigPublishMode(val)
|
pConfig.PublishMode = swarm.PortConfigPublishMode(val)
|
||||||
case portOptTargetPort:
|
case portOptTargetPort:
|
||||||
tPort, err := strconv.ParseUint(val, 10, 16)
|
tPort, err := strconv.ParseUint(val, 10, 16)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
var numErr *strconv.NumError
|
||||||
|
if errors.As(err, &numErr) {
|
||||||
|
err = numErr.Err
|
||||||
|
}
|
||||||
|
return fmt.Errorf("invalid target port (%s): value must be an integer: %w", val, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pConfig.TargetPort = uint32(tPort)
|
pConfig.TargetPort = uint32(tPort)
|
||||||
case portOptPublishedPort:
|
case portOptPublishedPort:
|
||||||
pPort, err := strconv.ParseUint(val, 10, 16)
|
pPort, err := strconv.ParseUint(val, 10, 16)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
var numErr *strconv.NumError
|
||||||
|
if errors.As(err, &numErr) {
|
||||||
|
err = numErr.Err
|
||||||
|
}
|
||||||
|
return fmt.Errorf("invalid published port (%s): value must be an integer: %w", val, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pConfig.PublishedPort = uint32(pPort)
|
pConfig.PublishedPort = uint32(pPort)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("invalid field key %s", key)
|
return fmt.Errorf("invalid field key: %s", key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if pConfig.TargetPort == 0 {
|
if pConfig.TargetPort == 0 {
|
||||||
return fmt.Errorf("missing mandatory field %q", portOptTargetPort)
|
return fmt.Errorf("missing mandatory field '%s'", portOptTargetPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
if pConfig.PublishMode == "" {
|
if pConfig.PublishMode == "" {
|
@ -1,4 +1,4 @@
|
|||||||
package opts
|
package swarmopts
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/csv"
|
"encoding/csv"
|
||||||
@ -8,12 +8,12 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
swarmtypes "github.com/docker/docker/api/types/swarm"
|
"github.com/docker/docker/api/types/swarm"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SecretOpt is a Value type for parsing secrets
|
// SecretOpt is a Value type for parsing secrets
|
||||||
type SecretOpt struct {
|
type SecretOpt struct {
|
||||||
values []*swarmtypes.SecretReference
|
values []*swarm.SecretReference
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set a new secret value
|
// Set a new secret value
|
||||||
@ -24,8 +24,8 @@ func (o *SecretOpt) Set(value string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
options := &swarmtypes.SecretReference{
|
options := &swarm.SecretReference{
|
||||||
File: &swarmtypes.SecretReferenceFileTarget{
|
File: &swarm.SecretReferenceFileTarget{
|
||||||
UID: "0",
|
UID: "0",
|
||||||
GID: "0",
|
GID: "0",
|
||||||
Mode: 0o444,
|
Mode: 0o444,
|
||||||
@ -94,6 +94,6 @@ func (o *SecretOpt) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Value returns the secret requests
|
// Value returns the secret requests
|
||||||
func (o *SecretOpt) Value() []*swarmtypes.SecretReference {
|
func (o *SecretOpt) Value() []*swarm.SecretReference {
|
||||||
return o.values
|
return o.values
|
||||||
}
|
}
|
5
vendor/modules.txt
vendored
5
vendor/modules.txt
vendored
@ -229,11 +229,12 @@ github.com/davecgh/go-spew/spew
|
|||||||
# github.com/distribution/reference v0.6.0
|
# github.com/distribution/reference v0.6.0
|
||||||
## explicit; go 1.20
|
## explicit; go 1.20
|
||||||
github.com/distribution/reference
|
github.com/distribution/reference
|
||||||
# github.com/docker/cli v28.0.1+incompatible
|
# github.com/docker/cli v28.0.2+incompatible
|
||||||
## explicit
|
## explicit
|
||||||
github.com/docker/cli/cli
|
github.com/docker/cli/cli
|
||||||
github.com/docker/cli/cli-plugins/hooks
|
github.com/docker/cli/cli-plugins/hooks
|
||||||
github.com/docker/cli/cli-plugins/manager
|
github.com/docker/cli/cli-plugins/manager
|
||||||
|
github.com/docker/cli/cli-plugins/metadata
|
||||||
github.com/docker/cli/cli-plugins/plugin
|
github.com/docker/cli/cli-plugins/plugin
|
||||||
github.com/docker/cli/cli-plugins/socket
|
github.com/docker/cli/cli-plugins/socket
|
||||||
github.com/docker/cli/cli/command
|
github.com/docker/cli/cli/command
|
||||||
@ -252,6 +253,7 @@ github.com/docker/cli/cli/context/store
|
|||||||
github.com/docker/cli/cli/debug
|
github.com/docker/cli/cli/debug
|
||||||
github.com/docker/cli/cli/flags
|
github.com/docker/cli/cli/flags
|
||||||
github.com/docker/cli/cli/hints
|
github.com/docker/cli/cli/hints
|
||||||
|
github.com/docker/cli/cli/internal/jsonstream
|
||||||
github.com/docker/cli/cli/manifest/store
|
github.com/docker/cli/cli/manifest/store
|
||||||
github.com/docker/cli/cli/manifest/types
|
github.com/docker/cli/cli/manifest/types
|
||||||
github.com/docker/cli/cli/registry/client
|
github.com/docker/cli/cli/registry/client
|
||||||
@ -260,6 +262,7 @@ github.com/docker/cli/cli/trust
|
|||||||
github.com/docker/cli/cli/version
|
github.com/docker/cli/cli/version
|
||||||
github.com/docker/cli/internal/tui
|
github.com/docker/cli/internal/tui
|
||||||
github.com/docker/cli/opts
|
github.com/docker/cli/opts
|
||||||
|
github.com/docker/cli/opts/swarmopts
|
||||||
github.com/docker/cli/pkg/kvfile
|
github.com/docker/cli/pkg/kvfile
|
||||||
github.com/docker/cli/templates
|
github.com/docker/cli/templates
|
||||||
# github.com/docker/cli-docs-tool v0.9.0
|
# github.com/docker/cli-docs-tool v0.9.0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user