vendor: github.com/docker/docker, github.com/docker/cli v25.0.0-beta.1

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2023-11-14 14:44:33 +01:00
parent c857eaa380
commit 898a8eeddf
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C
216 changed files with 2858 additions and 2203 deletions

View File

@ -22,6 +22,7 @@ import (
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/mount"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/api/types/system"
dockerclient "github.com/docker/docker/client"
"github.com/docker/docker/errdefs"
dockerarchive "github.com/docker/docker/pkg/archive"
@ -161,7 +162,7 @@ func (d *Driver) create(ctx context.Context, l progress.SubLogger) error {
}
}
secOpts, err := dockertypes.DecodeSecurityOptions(info.SecurityOptions)
secOpts, err := system.DecodeSecurityOptions(info.SecurityOptions)
if err != nil {
return err
}
@ -220,7 +221,7 @@ func (d *Driver) wait(ctx context.Context, l progress.SubLogger) error {
}
func (d *Driver) copyLogs(ctx context.Context, l progress.SubLogger) error {
rc, err := d.DockerAPI.ContainerLogs(ctx, d.Name, dockertypes.ContainerLogsOptions{
rc, err := d.DockerAPI.ContainerLogs(ctx, d.Name, container.LogsOptions{
ShowStdout: true, ShowStderr: true,
})
if err != nil {
@ -298,7 +299,7 @@ func (d *Driver) run(ctx context.Context, cmd []string, stdout, stderr io.Writer
}
func (d *Driver) start(ctx context.Context, l progress.SubLogger) error {
return d.DockerAPI.ContainerStart(ctx, d.Name, dockertypes.ContainerStartOptions{})
return d.DockerAPI.ContainerStart(ctx, d.Name, container.StartOptions{})
}
func (d *Driver) Info(ctx context.Context) (*driver.Info, error) {
@ -356,18 +357,18 @@ func (d *Driver) Rm(ctx context.Context, force, rmVolume, rmDaemon bool) error {
return err
}
if info.Status != driver.Inactive {
container, err := d.DockerAPI.ContainerInspect(ctx, d.Name)
ctr, err := d.DockerAPI.ContainerInspect(ctx, d.Name)
if err != nil {
return err
}
if rmDaemon {
if err := d.DockerAPI.ContainerRemove(ctx, d.Name, dockertypes.ContainerRemoveOptions{
if err := d.DockerAPI.ContainerRemove(ctx, d.Name, container.RemoveOptions{
RemoveVolumes: true,
Force: force,
}); err != nil {
return err
}
for _, v := range container.Mounts {
for _, v := range ctr.Mounts {
if v.Name != d.Name+volumeStateSuffix {
continue
}

6
go.mod
View File

@ -13,9 +13,9 @@ require (
github.com/containerd/typeurl/v2 v2.1.1
github.com/creack/pty v1.1.18
github.com/distribution/reference v0.5.0
github.com/docker/cli v24.0.5+incompatible
github.com/docker/cli v25.0.0-beta.1+incompatible
github.com/docker/cli-docs-tool v0.6.0
github.com/docker/docker v24.0.5+incompatible
github.com/docker/docker v25.0.0-beta.1+incompatible
github.com/docker/go-units v0.5.0
github.com/gofrs/flock v0.8.1
github.com/gogo/protobuf v1.3.2
@ -113,11 +113,11 @@ require (
github.com/moby/patternmatcher v0.6.0 // indirect
github.com/moby/spdystream v0.2.0 // indirect
github.com/moby/sys/sequential v0.5.0 // indirect
github.com/moby/sys/user v0.1.0 // indirect
github.com/moby/term v0.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/opencontainers/runc v1.1.9 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.14.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect

11
go.sum
View File

@ -154,15 +154,15 @@ 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/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/cli v24.0.5+incompatible h1:WeBimjvS0eKdH4Ygx+ihVq1Q++xg36M/rMi4aXAvodc=
github.com/docker/cli v24.0.5+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli v25.0.0-beta.1+incompatible h1:bJzIgR4mKNpceAwwi19SqZK0AbztMc3nQTgnvxxyY/A=
github.com/docker/cli v25.0.0-beta.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli-docs-tool v0.6.0 h1:Z9x10SaZgFaB6jHgz3OWooynhSa40CsWkpe5hEnG/qA=
github.com/docker/cli-docs-tool v0.6.0/go.mod h1:zMjqTFCU361PRh8apiXzeAZ1Q/xupbIwTusYpzCXS/o=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY=
github.com/docker/docker v24.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v25.0.0-beta.1+incompatible h1:NiDFwGzVt+mR9Jb5oC4+cd8lE9Zs86TXhCQg0zGk/sk=
github.com/docker/docker v25.0.0-beta.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.8.0 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8=
github.com/docker/docker-credential-helpers v0.8.0/go.mod h1:UGFXcuoQ5TxPiB54nHOZ32AWRqQdECoh/Mg0AlEYb40=
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=
@ -402,6 +402,8 @@ github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI=
github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg=
github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg=
github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU=
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@ -431,7 +433,6 @@ github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zM
github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI=
github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8=
github.com/opencontainers/runc v1.1.9 h1:XR0VIHTGce5eWPkaPesqTBrhW2yAcaraWfsEalNwQLM=
github.com/opencontainers/runc v1.1.9/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50=
github.com/opencontainers/runtime-spec v1.1.0-rc.2 h1:ucBtEms2tamYYW/SvGpvq9yUN0NEVL6oyLEwDcTSrk8=
github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU=
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=

View File

@ -1,8 +1,6 @@
package manager
import (
exec "golang.org/x/sys/execabs"
)
import "os/exec"
// Candidate represents a possible plugin candidate, for mocking purposes
type Candidate interface {

View File

@ -3,6 +3,7 @@ package manager
import (
"context"
"os"
"os/exec"
"path/filepath"
"sort"
"strings"
@ -13,7 +14,6 @@ import (
"github.com/fvbommel/sortorder"
"github.com/spf13/cobra"
"golang.org/x/sync/errgroup"
exec "golang.org/x/sys/execabs"
)
// ReexecEnvvar is the name of an ennvar which is set to the command

View File

@ -1,5 +1,4 @@
//go:build !windows
// +build !windows
package manager

View File

@ -22,8 +22,4 @@ type Metadata struct {
ShortDescription string `json:",omitempty"`
// URL is a pointer to the plugin's homepage.
URL string `json:",omitempty"`
// Experimental specifies whether the plugin is experimental.
//
// Deprecated: experimental features are now always enabled in the CLI
Experimental bool `json:",omitempty"`
}

View File

@ -1,5 +1,4 @@
//go:build !windows
// +build !windows
package manager

View File

@ -131,7 +131,7 @@ func newPluginCommand(dockerCli *command.DockerCli, plugin *cobra.Command, meta
DisableDescriptions: true,
},
}
opts, flags := cli.SetupPluginRootCommand(cmd)
opts, _ := cli.SetupPluginRootCommand(cmd)
cmd.SetIn(dockerCli.In())
cmd.SetOut(dockerCli.Out())
@ -144,7 +144,7 @@ func newPluginCommand(dockerCli *command.DockerCli, plugin *cobra.Command, meta
cli.DisableFlagsInUseLine(cmd)
return cli.NewTopLevelCommand(cmd, dockerCli, opts, flags)
return cli.NewTopLevelCommand(cmd, dockerCli, opts, cmd.Flags())
}
func newMetadataSubcommand(plugin *cobra.Command, meta manager.Metadata) *cobra.Command {

View File

@ -9,7 +9,6 @@ import (
pluginmanager "github.com/docker/cli/cli-plugins/manager"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/config"
cliflags "github.com/docker/cli/cli/flags"
"github.com/docker/docker/pkg/homedir"
"github.com/docker/docker/registry"
@ -23,12 +22,9 @@ import (
// setupCommonRootCommand contains the setup common to
// SetupRootCommand and SetupPluginRootCommand.
func setupCommonRootCommand(rootCmd *cobra.Command) (*cliflags.ClientOptions, *pflag.FlagSet, *cobra.Command) {
func setupCommonRootCommand(rootCmd *cobra.Command) (*cliflags.ClientOptions, *cobra.Command) {
opts := cliflags.NewClientOptions()
flags := rootCmd.Flags()
flags.StringVar(&opts.ConfigDir, "config", config.Dir(), "Location of client config files")
opts.InstallFlags(flags)
opts.InstallFlags(rootCmd.Flags())
cobra.AddTemplateFunc("add", func(a, b int) int { return a + b })
cobra.AddTemplateFunc("hasAliases", hasAliases)
@ -73,20 +69,20 @@ func setupCommonRootCommand(rootCmd *cobra.Command) (*cliflags.ClientOptions, *p
}
}
return opts, flags, helpCommand
return opts, helpCommand
}
// SetupRootCommand sets default usage, help, and error handling for the
// root command.
func SetupRootCommand(rootCmd *cobra.Command) (*cliflags.ClientOptions, *pflag.FlagSet, *cobra.Command) {
func SetupRootCommand(rootCmd *cobra.Command) (opts *cliflags.ClientOptions, helpCmd *cobra.Command) {
rootCmd.SetVersionTemplate("Docker version {{.Version}}\n")
return setupCommonRootCommand(rootCmd)
}
// SetupPluginRootCommand sets default usage, help and error handling for a plugin root command.
func SetupPluginRootCommand(rootCmd *cobra.Command) (*cliflags.ClientOptions, *pflag.FlagSet) {
opts, flags, _ := setupCommonRootCommand(rootCmd)
return opts, flags
opts, _ := setupCommonRootCommand(rootCmd)
return opts, rootCmd.Flags()
}
// FlagErrorFunc prints an error message which matches the format of the

View File

@ -189,7 +189,7 @@ func (cli *DockerCli) ManifestStore() manifeststore.Store {
// registry
func (cli *DockerCli) RegistryClient(allowInsecure bool) registryclient.RegistryClient {
resolver := func(ctx context.Context, index *registry.IndexInfo) registry.AuthConfig {
return ResolveAuthConfig(ctx, cli, index)
return ResolveAuthConfig(cli.ConfigFile(), index)
}
return registryclient.NewRegistryClient(resolver, UserAgent(), allowInsecure)
}
@ -260,17 +260,15 @@ func NewAPIClientFromFlags(opts *cliflags.ClientOptions, configFile *configfile.
}
func newAPIClientFromEndpoint(ep docker.Endpoint, configFile *configfile.ConfigFile) (client.APIClient, error) {
clientOpts, err := ep.ClientOpts()
opts, err := ep.ClientOpts()
if err != nil {
return nil, err
}
customHeaders := make(map[string]string, len(configFile.HTTPHeaders))
for k, v := range configFile.HTTPHeaders {
customHeaders[k] = v
if len(configFile.HTTPHeaders) > 0 {
opts = append(opts, client.WithHTTPHeaders(configFile.HTTPHeaders))
}
customHeaders["User-Agent"] = UserAgent()
clientOpts = append(clientOpts, client.WithHTTPHeaders(customHeaders))
return client.NewClientWithOpts(clientOpts...)
opts = append(opts, client.WithUserAgent(UserAgent()))
return client.NewClientWithOpts(opts...)
}
func resolveDockerEndpoint(s store.Reader, contextName string) (docker.Endpoint, error) {
@ -364,7 +362,7 @@ func (cli *DockerCli) ContextStore() store.Store {
// order of preference:
//
// 1. The "--context" command-line option.
// 2. The "DOCKER_CONTEXT" environment variable.
// 2. The "DOCKER_CONTEXT" environment variable ([EnvOverrideContext]).
// 3. The current context as configured through the in "currentContext"
// field in the CLI configuration file ("~/.docker/config.json").
// 4. If no context is configured, use the "default" context.
@ -406,7 +404,7 @@ func resolveContextName(opts *cliflags.ClientOptions, config *configfile.ConfigF
if os.Getenv(client.EnvOverrideHost) != "" {
return DefaultContextName
}
if ctxName := os.Getenv("DOCKER_CONTEXT"); ctxName != "" {
if ctxName := os.Getenv(EnvOverrideContext); ctxName != "" {
return ctxName
}
if config != nil && config.CurrentContext != "" {

View File

@ -11,6 +11,12 @@ import (
const (
// DefaultContextName is the name reserved for the default context (config & env based)
DefaultContextName = "default"
// EnvOverrideContext is the name of the environment variable that can be
// used to override the context to use. If set, it overrides the context
// that's set in the CLI's configuration file, but takes no effect if the
// "DOCKER_HOST" env-var is set (which takes precedence.
EnvOverrideContext = "DOCKER_CONTEXT"
)
// DefaultContext contains the default context data for all endpoints

View File

@ -3,28 +3,28 @@ package command
import (
"sync"
eventtypes "github.com/docker/docker/api/types/events"
"github.com/docker/docker/api/types/events"
"github.com/sirupsen/logrus"
)
// EventHandler is abstract interface for user to customize
// own handle functions of each type of events
type EventHandler interface {
Handle(action string, h func(eventtypes.Message))
Watch(c <-chan eventtypes.Message)
Handle(action events.Action, h func(events.Message))
Watch(c <-chan events.Message)
}
// InitEventHandler initializes and returns an EventHandler
func InitEventHandler() EventHandler {
return &eventHandler{handlers: make(map[string]func(eventtypes.Message))}
return &eventHandler{handlers: make(map[events.Action]func(events.Message))}
}
type eventHandler struct {
handlers map[string]func(eventtypes.Message)
handlers map[events.Action]func(events.Message)
mu sync.Mutex
}
func (w *eventHandler) Handle(action string, h func(eventtypes.Message)) {
func (w *eventHandler) Handle(action events.Action, h func(events.Message)) {
w.mu.Lock()
w.handlers[action] = h
w.mu.Unlock()
@ -33,7 +33,7 @@ func (w *eventHandler) Handle(action string, h func(eventtypes.Message)) {
// Watch ranges over the passed in event chan and processes the events based on the
// handlers created for a given action.
// To stop watching, close the event chan.
func (w *eventHandler) Watch(c <-chan eventtypes.Message) {
func (w *eventHandler) Watch(c <-chan events.Message) {
for e := range c {
w.mu.Lock()
h, exists := w.handlers[e.Action]

View File

@ -2,16 +2,17 @@ package command
import (
"bufio"
"context"
"fmt"
"io"
"os"
"runtime"
"strings"
"github.com/distribution/reference"
"github.com/docker/cli/cli/config/configfile"
configtypes "github.com/docker/cli/cli/config/types"
"github.com/docker/cli/cli/hints"
"github.com/docker/cli/cli/streams"
"github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/registry"
@ -19,12 +20,9 @@ import (
"github.com/pkg/errors"
)
// EncodeAuthToBase64 serializes the auth configuration as JSON base64 payload.
//
// Deprecated: use [registrytypes.EncodeAuthConfig] instead.
func EncodeAuthToBase64(authConfig registrytypes.AuthConfig) (string, error) {
return registrytypes.EncodeAuthConfig(authConfig)
}
const patSuggest = "You can log in with your password or a Personal Access " +
"Token (PAT). Using a limited-scope PAT grants better security and is required " +
"for organizations using SSO. Learn more at https://docs.docker.com/go/access-tokens/"
// RegistryAuthenticationPrivilegedFunc returns a RequestPrivilegeFunc from the specified registry index info
// for the given command.
@ -33,7 +31,7 @@ func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInf
fmt.Fprintf(cli.Out(), "\nPlease login prior to %s:\n", cmdName)
indexServer := registry.GetAuthConfigKey(index)
isDefaultRegistry := indexServer == registry.IndexServer
authConfig, err := GetDefaultAuthConfig(cli, true, indexServer, isDefaultRegistry)
authConfig, err := GetDefaultAuthConfig(cli.ConfigFile(), true, indexServer, isDefaultRegistry)
if err != nil {
fmt.Fprintf(cli.Err(), "Unable to retrieve stored credentials for %s, error: %s.\n", indexServer, err)
}
@ -51,26 +49,26 @@ func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInf
//
// It is similar to [registry.ResolveAuthConfig], but uses the credentials-
// store, instead of looking up credentials from a map.
func ResolveAuthConfig(_ context.Context, cli Cli, index *registrytypes.IndexInfo) registrytypes.AuthConfig {
func ResolveAuthConfig(cfg *configfile.ConfigFile, index *registrytypes.IndexInfo) registrytypes.AuthConfig {
configKey := index.Name
if index.Official {
configKey = registry.IndexServer
}
a, _ := cli.ConfigFile().GetAuthConfig(configKey)
a, _ := cfg.GetAuthConfig(configKey)
return registrytypes.AuthConfig(a)
}
// GetDefaultAuthConfig gets the default auth config given a serverAddress
// If credentials for given serverAddress exists in the credential store, the configuration will be populated with values in it
func GetDefaultAuthConfig(cli Cli, checkCredStore bool, serverAddress string, isDefaultRegistry bool) (registrytypes.AuthConfig, error) {
func GetDefaultAuthConfig(cfg *configfile.ConfigFile, checkCredStore bool, serverAddress string, isDefaultRegistry bool) (registrytypes.AuthConfig, error) {
if !isDefaultRegistry {
serverAddress = registry.ConvertToHostname(serverAddress)
}
authconfig := configtypes.AuthConfig{}
var err error
if checkCredStore {
authconfig, err = cli.ConfigFile().GetAuthConfig(serverAddress)
authconfig, err = cfg.GetAuthConfig(serverAddress)
if err != nil {
return registrytypes.AuthConfig{
ServerAddress: serverAddress,
@ -79,8 +77,7 @@ func GetDefaultAuthConfig(cli Cli, checkCredStore bool, serverAddress string, is
}
authconfig.ServerAddress = serverAddress
authconfig.IdentityToken = ""
res := registrytypes.AuthConfig(authconfig)
return res, nil
return registrytypes.AuthConfig(authconfig), nil
}
// ConfigureAuth handles prompting of user's username and password if needed
@ -113,7 +110,11 @@ func ConfigureAuth(cli Cli, flUser, flPassword string, authconfig *registrytypes
if flUser = strings.TrimSpace(flUser); flUser == "" {
if isDefaultRegistry {
// if this is a default registry (docker hub), then display the following message.
fmt.Fprintln(cli.Out(), "Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.")
fmt.Fprintln(cli.Out(), "Log in with your Docker ID or email address to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com/ to create one.")
if hints.Enabled() {
fmt.Fprintln(cli.Out(), patSuggest)
fmt.Fprintln(cli.Out())
}
}
promptWithDefault(cli.Out(), "Username", authconfig.Username)
var err error
@ -179,9 +180,9 @@ func promptWithDefault(out io.Writer, prompt string, configDefault string) {
//
// For details on base64url encoding, see:
// - RFC4648, section 5: https://tools.ietf.org/html/rfc4648#section-5
func RetrieveAuthTokenFromImage(ctx context.Context, cli Cli, image string) (string, error) {
func RetrieveAuthTokenFromImage(cfg *configfile.ConfigFile, image string) (string, error) {
// Retrieve encoded auth token from the image reference
authConfig, err := resolveAuthConfigFromImage(ctx, cli, image)
authConfig, err := resolveAuthConfigFromImage(cfg, image)
if err != nil {
return "", err
}
@ -193,7 +194,7 @@ func RetrieveAuthTokenFromImage(ctx context.Context, cli Cli, image string) (str
}
// resolveAuthConfigFromImage retrieves that AuthConfig using the image string
func resolveAuthConfigFromImage(ctx context.Context, cli Cli, image string) (registrytypes.AuthConfig, error) {
func resolveAuthConfigFromImage(cfg *configfile.ConfigFile, image string) (registrytypes.AuthConfig, error) {
registryRef, err := reference.ParseNormalizedNamed(image)
if err != nil {
return registrytypes.AuthConfig{}, err
@ -202,5 +203,5 @@ func resolveAuthConfigFromImage(ctx context.Context, cli Cli, image string) (reg
if err != nil {
return registrytypes.AuthConfig{}, err
}
return ResolveAuthConfig(ctx, cli, repoInfo.Index), nil
return ResolveAuthConfig(cfg, repoInfo.Index), nil
}

View File

@ -11,6 +11,8 @@ import (
"github.com/docker/cli/cli/streams"
"github.com/docker/docker/api/types/filters"
mounttypes "github.com/docker/docker/api/types/mount"
"github.com/docker/docker/api/types/versions"
"github.com/moby/sys/sequential"
"github.com/pkg/errors"
"github.com/spf13/pflag"
@ -195,3 +197,17 @@ func StringSliceReplaceAt(s, old, new []string, requireIndex int) ([]string, boo
out = append(out, s[idx+len(old):]...)
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
}

View File

@ -16,32 +16,25 @@ import (
)
const (
// ConfigFileName is the name of config file
// EnvOverrideConfigDir is the name of the environment variable that can be
// used to override the location of the client configuration files (~/.docker).
//
// It takes priority over the default, but can be overridden by the "--config"
// command line option.
EnvOverrideConfigDir = "DOCKER_CONFIG"
// ConfigFileName is the name of the client configuration file inside the
// config-directory.
ConfigFileName = "config.json"
configFileDir = ".docker"
oldConfigfile = ".dockercfg" // Deprecated: remove once we stop printing deprecation warning
contextsDir = "contexts"
)
var (
initConfigDir = new(sync.Once)
configDir string
homeDir string
)
// resetHomeDir is used in testing to reset the "homeDir" package variable to
// force re-lookup of the home directory between tests.
func resetHomeDir() {
homeDir = ""
}
func getHomeDir() string {
if homeDir == "" {
homeDir = homedir.Get()
}
return homeDir
}
// resetConfigDir is used in testing to reset the "configDir" package variable
// and its sync.Once to force re-lookup between tests.
func resetConfigDir() {
@ -49,19 +42,14 @@ func resetConfigDir() {
initConfigDir = new(sync.Once)
}
func setConfigDir() {
if configDir != "" {
return
}
configDir = os.Getenv("DOCKER_CONFIG")
if configDir == "" {
configDir = filepath.Join(getHomeDir(), configFileDir)
}
}
// Dir returns the directory the configuration file is stored in
func Dir() string {
initConfigDir.Do(setConfigDir)
initConfigDir.Do(func() {
configDir = os.Getenv(EnvOverrideConfigDir)
if configDir == "" {
configDir = filepath.Join(homedir.Get(), configFileDir)
}
})
return configDir
}
@ -72,6 +60,8 @@ func ContextStoreDir() string {
// SetDir sets the directory the configuration file is stored in
func SetDir(dir string) {
// trigger the sync.Once to synchronise with Dir()
initConfigDir.Do(func() {})
configDir = filepath.Clean(dir)
}
@ -96,55 +86,43 @@ func LoadFromReader(configData io.Reader) (*configfile.ConfigFile, error) {
// Load reads the configuration files in the given directory, and sets up
// the auth config information and returns values.
// FIXME: use the internal golang config parser
func Load(configDir string) (*configfile.ConfigFile, error) {
cfg, _, err := load(configDir)
return cfg, err
}
// TODO remove this temporary hack, which is used to warn about the deprecated ~/.dockercfg file
// so we can remove the bool return value and collapse this back into `Load`
func load(configDir string) (*configfile.ConfigFile, bool, error) {
printLegacyFileWarning := false
if configDir == "" {
configDir = Dir()
}
return load(configDir)
}
func load(configDir string) (*configfile.ConfigFile, error) {
filename := filepath.Join(configDir, ConfigFileName)
configFile := configfile.New(filename)
// Try happy path first - latest config file
if file, err := os.Open(filename); err == nil {
defer file.Close()
err = configFile.LoadFromReader(file)
if err != nil {
err = errors.Wrap(err, filename)
file, err := os.Open(filename)
if err != nil {
if os.IsNotExist(err) {
//
// if file is there but we can't stat it for any reason other
// than it doesn't exist then stop
return configFile, nil
}
return configFile, printLegacyFileWarning, err
} else if !os.IsNotExist(err) {
// if file is there but we can't stat it for any reason other
// than it doesn't exist then stop
return configFile, printLegacyFileWarning, errors.Wrap(err, filename)
return configFile, nil
}
// Can't find latest config file so check for the old one
filename = filepath.Join(getHomeDir(), oldConfigfile)
if _, err := os.Stat(filename); err == nil {
printLegacyFileWarning = true
defer file.Close()
err = configFile.LoadFromReader(file)
if err != nil {
err = errors.Wrap(err, filename)
}
return configFile, printLegacyFileWarning, nil
return configFile, err
}
// LoadDefaultConfigFile attempts to load the default config file and returns
// an initialized ConfigFile struct if none is found.
func LoadDefaultConfigFile(stderr io.Writer) *configfile.ConfigFile {
configFile, printLegacyFileWarning, err := load(Dir())
configFile, err := load(Dir())
if err != nil {
fmt.Fprintf(stderr, "WARNING: Error loading config file: %v\n", err)
}
if printLegacyFileWarning {
_, _ = fmt.Fprintln(stderr, "WARNING: Support for the legacy ~/.dockercfg configuration file and file-format has been removed and the configuration file will be ignored")
_, _ = fmt.Fprintf(stderr, "WARNING: Error loading config file: %v\n", err)
}
if !configFile.ContainsAuth() {
configFile.CredentialsStore = credentials.DetectDefaultStore(configFile.CredentialsStore)

View File

@ -1,5 +1,4 @@
//go:build !windows
// +build !windows
package configfile

View File

@ -1,21 +1,22 @@
package credentials
import (
exec "golang.org/x/sys/execabs"
)
import "os/exec"
// DetectDefaultStore return the default credentials store for the platform if
// the store executable is available.
// no user-defined store is passed, and the store executable is available.
func DetectDefaultStore(store string) string {
platformDefault := defaultCredentialsStore()
// user defined or no default for platform
if store != "" || platformDefault == "" {
if store != "" {
// use user-defined
return store
}
if _, err := exec.LookPath(remoteCredentialsPrefix + platformDefault); err == nil {
return platformDefault
platformDefault := defaultCredentialsStore()
if platformDefault == "" {
return ""
}
return ""
if _, err := exec.LookPath(remoteCredentialsPrefix + platformDefault); err != nil {
return ""
}
return platformDefault
}

View File

@ -1,5 +1,4 @@
//go:build !windows && !darwin && !linux
// +build !windows,!darwin,!linux
package credentials

View File

@ -51,6 +51,7 @@ func (c *nativeStore) Get(serverAddress string) (types.AuthConfig, error) {
auth.Username = creds.Username
auth.IdentityToken = creds.IdentityToken
auth.Password = creds.Password
auth.ServerAddress = creds.ServerAddress
return auth, nil
}
@ -76,6 +77,9 @@ func (c *nativeStore) GetAll() (map[string]types.AuthConfig, error) {
ac.Username = creds.Username
ac.Password = creds.Password
ac.IdentityToken = creds.IdentityToken
if ac.ServerAddress == "" {
ac.ServerAddress = creds.ServerAddress
}
authConfigs[registry] = ac
}

View File

@ -20,6 +20,7 @@ import (
"io"
"net"
"os"
"os/exec"
"runtime"
"strings"
"sync"
@ -29,7 +30,6 @@ import (
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
exec "golang.org/x/sys/execabs"
)
// New returns net.Conn

View File

@ -1,5 +1,4 @@
//go:build !linux
// +build !linux
package commandconn

View File

@ -1,5 +1,4 @@
//go:build !windows
// +build !windows
package commandconn

View File

@ -40,23 +40,23 @@ func WithTLSData(s store.Reader, contextName string, m EndpointMeta) (Endpoint,
}
// tlsConfig extracts a context docker endpoint TLS config
func (c *Endpoint) tlsConfig() (*tls.Config, error) {
if c.TLSData == nil && !c.SkipTLSVerify {
func (ep *Endpoint) tlsConfig() (*tls.Config, error) {
if ep.TLSData == nil && !ep.SkipTLSVerify {
// there is no specific tls config
return nil, nil
}
var tlsOpts []func(*tls.Config)
if c.TLSData != nil && c.TLSData.CA != nil {
if ep.TLSData != nil && ep.TLSData.CA != nil {
certPool := x509.NewCertPool()
if !certPool.AppendCertsFromPEM(c.TLSData.CA) {
if !certPool.AppendCertsFromPEM(ep.TLSData.CA) {
return nil, errors.New("failed to retrieve context tls info: ca.pem seems invalid")
}
tlsOpts = append(tlsOpts, func(cfg *tls.Config) {
cfg.RootCAs = certPool
})
}
if c.TLSData != nil && c.TLSData.Key != nil && c.TLSData.Cert != nil {
keyBytes := c.TLSData.Key
if ep.TLSData != nil && ep.TLSData.Key != nil && ep.TLSData.Cert != nil {
keyBytes := ep.TLSData.Key
pemBlock, _ := pem.Decode(keyBytes)
if pemBlock == nil {
return nil, errors.New("no valid private key found")
@ -65,7 +65,7 @@ func (c *Endpoint) tlsConfig() (*tls.Config, error) {
return nil, errors.New("private key is encrypted - support for encrypted private keys has been removed, see https://docs.docker.com/go/deprecated/")
}
x509cert, err := tls.X509KeyPair(c.TLSData.Cert, keyBytes)
x509cert, err := tls.X509KeyPair(ep.TLSData.Cert, keyBytes)
if err != nil {
return nil, errors.Wrap(err, "failed to retrieve context tls info")
}
@ -73,7 +73,7 @@ func (c *Endpoint) tlsConfig() (*tls.Config, error) {
cfg.Certificates = []tls.Certificate{x509cert}
})
}
if c.SkipTLSVerify {
if ep.SkipTLSVerify {
tlsOpts = append(tlsOpts, func(cfg *tls.Config) {
cfg.InsecureSkipVerify = true
})
@ -82,33 +82,31 @@ func (c *Endpoint) tlsConfig() (*tls.Config, error) {
}
// ClientOpts returns a slice of Client options to configure an API client with this endpoint
func (c *Endpoint) ClientOpts() ([]client.Opt, error) {
func (ep *Endpoint) ClientOpts() ([]client.Opt, error) {
var result []client.Opt
if c.Host != "" {
helper, err := connhelper.GetConnectionHelper(c.Host)
if ep.Host != "" {
helper, err := connhelper.GetConnectionHelper(ep.Host)
if err != nil {
return nil, err
}
if helper == nil {
tlsConfig, err := c.tlsConfig()
tlsConfig, err := ep.tlsConfig()
if err != nil {
return nil, err
}
result = append(result,
withHTTPClient(tlsConfig),
client.WithHost(c.Host),
client.WithHost(ep.Host),
)
} else {
httpClient := &http.Client{
// No tls
// No proxy
Transport: &http.Transport{
DialContext: helper.Dialer,
},
}
result = append(result,
client.WithHTTPClient(httpClient),
client.WithHTTPClient(&http.Client{
// No TLS, and no proxy.
Transport: &http.Transport{
DialContext: helper.Dialer,
},
}),
client.WithHost(helper.Host),
client.WithDialContext(helper.Dialer),
)
@ -125,8 +123,7 @@ func withHTTPClient(tlsConfig *tls.Config) func(*client.Client) error {
// Use the default HTTPClient
return nil
}
httpClient := &http.Client{
return client.WithHTTPClient(&http.Client{
Transport: &http.Transport{
TLSClientConfig: tlsConfig,
DialContext: (&net.Dialer{
@ -135,8 +132,7 @@ func withHTTPClient(tlsConfig *tls.Config) func(*client.Client) error {
}).DialContext,
},
CheckRedirect: client.CheckRedirect,
}
return client.WithHTTPClient(httpClient)(c)
})(c)
}
}

View File

@ -14,6 +14,18 @@ import (
)
const (
// EnvEnableTLS is the name of the environment variable that can be used
// to enable TLS for client connections. When set to a non-empty value, TLS
// is enabled for API connections using TCP. For backward-compatibility, this
// environment-variable can only be used to enable TLS, not to disable.
//
// Note that TLS is always enabled implicitly if the "--tls-verify" option
// or "DOCKER_TLS_VERIFY" ([github.com/docker/docker/client.EnvTLSVerify])
// env var is set to, which could be to either enable or disable TLS certification
// validation. In both cases, TLS is enabled but, depending on the setting,
// with verification disabled.
EnvEnableTLS = "DOCKER_TLS"
// DefaultCaFile is the default filename for the CA pem file
DefaultCaFile = "ca.pem"
// DefaultKeyFile is the default filename for the key pem file
@ -39,8 +51,7 @@ Refer to https://docs.docker.com/go/formatting/ for more information about forma
var (
dockerCertPath = os.Getenv(client.EnvOverrideCertPath)
dockerTLSVerify = os.Getenv(client.EnvTLSVerify) != ""
// TODO(thaJeztah) the 'DOCKER_TLS' environment variable is not documented, and does not have a const.
dockerTLS = os.Getenv("DOCKER_TLS") != ""
dockerTLS = os.Getenv(EnvEnableTLS) != ""
)
// ClientOptions are the options used to configure the client cli.
@ -62,10 +73,12 @@ func NewClientOptions() *ClientOptions {
// InstallFlags adds flags for the common options on the FlagSet
func (o *ClientOptions) InstallFlags(flags *pflag.FlagSet) {
configDir := config.Dir()
if dockerCertPath == "" {
dockerCertPath = config.Dir()
dockerCertPath = configDir
}
flags.StringVar(&o.ConfigDir, "config", configDir, "Location of client config files")
flags.BoolVarP(&o.Debug, "debug", "D", false, "Enable debug mode")
flags.StringVarP(&o.LogLevel, "log-level", "l", "info", `Set the logging level ("debug", "info", "warn", "error", "fatal")`)
flags.BoolVar(&o.TLS, "tls", dockerTLS, "Use TLS; implied by --tlsverify")

18
vendor/github.com/docker/cli/cli/hints/hints.go generated vendored Normal file
View File

@ -0,0 +1,18 @@
package hints
import (
"os"
"strconv"
)
// Enabled returns whether cli hints are enabled or not
func Enabled() bool {
if v := os.Getenv("DOCKER_CLI_HINTS"); v != "" {
enabled, err := strconv.ParseBool(v)
if err != nil {
return true
}
return enabled
}
return true
}

View File

@ -7,9 +7,9 @@ import (
"path/filepath"
"strings"
"github.com/distribution/reference"
"github.com/docker/cli/cli/manifest/types"
"github.com/docker/distribution/manifest/manifestlist"
"github.com/docker/distribution/reference"
"github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"

View File

@ -3,11 +3,11 @@ package types
import (
"encoding/json"
"github.com/distribution/reference"
"github.com/docker/distribution"
"github.com/docker/distribution/manifest/manifestlist"
"github.com/docker/distribution/manifest/ocischema"
"github.com/docker/distribution/manifest/schema2"
"github.com/docker/distribution/reference"
"github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"

View File

@ -6,9 +6,10 @@ import (
"net/http"
"strings"
"github.com/distribution/reference"
manifesttypes "github.com/docker/cli/cli/manifest/types"
"github.com/docker/cli/cli/trust"
"github.com/docker/distribution"
"github.com/docker/distribution/reference"
distributionclient "github.com/docker/distribution/registry/client"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/opencontainers/go-digest"
@ -77,6 +78,7 @@ func (c *client) MountBlob(ctx context.Context, sourceRef reference.Canonical, t
if err != nil {
return err
}
repoEndpoint.actions = trust.ActionsPushAndPull
repo, err := c.getRepositoryForReference(ctx, targetRef, repoEndpoint)
if err != nil {
return err
@ -102,6 +104,7 @@ func (c *client) PutManifest(ctx context.Context, ref reference.Named, manifest
return digest.Digest(""), err
}
repoEndpoint.actions = trust.ActionsPushAndPull
repo, err := c.getRepositoryForReference(ctx, ref, repoEndpoint)
if err != nil {
return digest.Digest(""), err
@ -151,7 +154,9 @@ func (c *client) getHTTPTransportForRepoEndpoint(ctx context.Context, repoEndpoi
c.authConfigResolver(ctx, repoEndpoint.info.Index),
repoEndpoint.endpoint,
repoEndpoint.Name(),
c.userAgent)
c.userAgent,
repoEndpoint.actions,
)
return httpTransport, errors.Wrap(err, "failed to configure transport")
}

View File

@ -6,7 +6,8 @@ import (
"net/http"
"time"
"github.com/docker/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/transport"
registrytypes "github.com/docker/docker/api/types/registry"
@ -17,6 +18,7 @@ import (
type repositoryEndpoint struct {
info *registry.RepositoryInfo
endpoint registry.APIEndpoint
actions []string
}
// Name returns the repository name
@ -74,7 +76,7 @@ func getDefaultEndpointFromRepoInfo(repoInfo *registry.RepositoryInfo) (registry
}
// getHTTPTransport builds a transport for use in communicating with a registry
func getHTTPTransport(authConfig registrytypes.AuthConfig, endpoint registry.APIEndpoint, repoName string, userAgent string) (http.RoundTripper, error) {
func getHTTPTransport(authConfig registrytypes.AuthConfig, endpoint registry.APIEndpoint, repoName, userAgent string, actions []string) (http.RoundTripper, error) {
// get the http transport, this will be used in a client to upload manifest
base := &http.Transport{
Proxy: http.ProxyFromEnvironment,
@ -98,8 +100,11 @@ func getHTTPTransport(authConfig registrytypes.AuthConfig, endpoint registry.API
passThruTokenHandler := &existingTokenHandler{token: authConfig.RegistryToken}
modifiers = append(modifiers, auth.NewAuthorizer(challengeManager, passThruTokenHandler))
} else {
if len(actions) == 0 {
actions = trust.ActionsPullOnly
}
creds := registry.NewStaticCredentialStore(&authConfig)
tokenHandler := auth.NewTokenHandler(authTransport, creds, repoName, "push", "pull")
tokenHandler := auth.NewTokenHandler(authTransport, creds, repoName, actions...)
basicHandler := auth.NewBasicHandler(creds)
modifiers = append(modifiers, auth.NewAuthorizer(challengeManager, tokenHandler, basicHandler))
}

View File

@ -4,12 +4,12 @@ import (
"context"
"encoding/json"
"github.com/distribution/reference"
"github.com/docker/cli/cli/manifest/types"
"github.com/docker/distribution"
"github.com/docker/distribution/manifest/manifestlist"
"github.com/docker/distribution/manifest/ocischema"
"github.com/docker/distribution/manifest/schema2"
"github.com/docker/distribution/reference"
"github.com/docker/distribution/registry/api/errcode"
v2 "github.com/docker/distribution/registry/api/v2"
distclient "github.com/docker/distribution/registry/client"
@ -31,17 +31,9 @@ func fetchManifest(ctx context.Context, repo distribution.Repository, ref refere
switch v := manifest.(type) {
// Removed Schema 1 support
case *schema2.DeserializedManifest:
imageManifest, err := pullManifestSchemaV2(ctx, ref, repo, *v)
if err != nil {
return types.ImageManifest{}, err
}
return imageManifest, nil
return pullManifestSchemaV2(ctx, ref, repo, *v)
case *ocischema.DeserializedManifest:
imageManifest, err := pullManifestOCISchema(ctx, ref, repo, *v)
if err != nil {
return types.ImageManifest{}, err
}
return imageManifest, nil
return pullManifestOCISchema(ctx, ref, repo, *v)
case *manifestlist.DeserializedManifestList:
return types.ImageManifest{}, errors.Errorf("%s is a manifest list", ref)
}
@ -56,11 +48,7 @@ func fetchList(ctx context.Context, repo distribution.Repository, ref reference.
switch v := manifest.(type) {
case *manifestlist.DeserializedManifestList:
imageManifests, err := pullManifestList(ctx, ref, repo, *v)
if err != nil {
return nil, err
}
return imageManifests, nil
return pullManifestList(ctx, ref, repo, *v)
default:
return nil, errors.Errorf("unsupported manifest format: %v", v)
}
@ -154,11 +142,8 @@ func validateManifestDigest(ref reference.Named, mfst distribution.Manifest) (oc
}
// If pull by digest, then verify the manifest digest.
if digested, isDigested := ref.(reference.Canonical); isDigested {
if digested.Digest() != desc.Digest {
err := errors.Errorf("manifest verification failed for digest %s", digested.Digest())
return ocispec.Descriptor{}, err
}
if digested, isDigested := ref.(reference.Canonical); isDigested && digested.Digest() != desc.Digest {
return ocispec.Descriptor{}, errors.Errorf("manifest verification failed for digest %s", digested.Digest())
}
return desc, nil
@ -167,12 +152,11 @@ func validateManifestDigest(ref reference.Named, mfst distribution.Manifest) (oc
// pullManifestList handles "manifest lists" which point to various
// platform-specific manifests.
func pullManifestList(ctx context.Context, ref reference.Named, repo distribution.Repository, mfstList manifestlist.DeserializedManifestList) ([]types.ImageManifest, error) {
infos := []types.ImageManifest{}
if _, err := validateManifestDigest(ref, mfstList); err != nil {
return nil, err
}
infos := make([]types.ImageManifest, 0, len(mfstList.Manifests))
for _, manifestDescriptor := range mfstList.Manifests {
manSvc, err := repo.Manifests(ctx)
if err != nil {
@ -202,7 +186,8 @@ func pullManifestList(ctx context.Context, ref reference.Named, repo distributio
}
// Replace platform from config
imageManifest.Descriptor.Platform = types.OCIPlatform(&manifestDescriptor.Platform)
p := manifestDescriptor.Platform
imageManifest.Descriptor.Platform = types.OCIPlatform(&p)
infos = append(infos, imageManifest)
}
@ -217,12 +202,12 @@ func continueOnError(err error) bool {
}
return continueOnError(v[0])
case errcode.Error:
e := err.(errcode.Error)
switch e.Code {
switch e := err.(errcode.Error); e.Code {
case errcode.ErrorCodeUnauthorized, v2.ErrorCodeManifestUnknown, v2.ErrorCodeNameUnknown:
return true
default:
return false
}
return false
case *distclient.UnexpectedHTTPResponseError:
return true
}
@ -242,11 +227,6 @@ func (c *client) iterateEndpoints(ctx context.Context, namedRef reference.Named,
confirmedTLSRegistries := make(map[string]bool)
for _, endpoint := range endpoints {
if endpoint.Version == registry.APIVersion1 {
logrus.Debugf("skipping v1 endpoint %s", endpoint.URL)
continue
}
if endpoint.URL.Scheme != "https" {
if _, confirmedTLS := confirmedTLSRegistries[endpoint.URL.Host]; confirmedTLS {
logrus.Debugf("skipping non-TLS endpoint %s for host/port that appears to use TLS", endpoint.URL)

View File

@ -12,8 +12,8 @@ import (
"path/filepath"
"time"
"github.com/distribution/reference"
"github.com/docker/cli/cli/config"
"github.com/docker/distribution/reference"
"github.com/docker/distribution/registry/client/auth"
"github.com/docker/distribution/registry/client/auth/challenge"
"github.com/docker/distribution/registry/client/transport"

View File

@ -1,5 +1,4 @@
//go:build !windows
// +build !windows
package opts

View File

@ -1,47 +0,0 @@
package opts
import (
"fmt"
"net"
)
// IPOpt holds an IP. It is used to store values from CLI flags.
type IPOpt struct {
*net.IP
}
// NewIPOpt creates a new IPOpt from a reference net.IP and a
// string representation of an IP. If the string is not a valid
// IP it will fallback to the specified reference.
func NewIPOpt(ref *net.IP, defaultVal string) *IPOpt {
o := &IPOpt{
IP: ref,
}
o.Set(defaultVal)
return o
}
// Set sets an IPv4 or IPv6 address from a given string. If the given
// string is not parseable as an IP address it returns an error.
func (o *IPOpt) Set(val string) error {
ip := net.ParseIP(val)
if ip == nil {
return fmt.Errorf("%s is not an ip address", val)
}
*o.IP = ip
return nil
}
// String returns the IP address stored in the IPOpt. If stored IP is a
// nil pointer, it returns an empty string.
func (o *IPOpt) String() string {
if *o.IP == nil {
return ""
}
return o.IP.String()
}
// Type returns the type of the option
func (o *IPOpt) Type() string {
return "ip"
}

View File

@ -2,6 +2,7 @@ package opts
import (
"encoding/csv"
"errors"
"fmt"
"os"
"path/filepath"
@ -10,6 +11,7 @@ import (
mounttypes "github.com/docker/docker/api/types/mount"
"github.com/docker/go-units"
"github.com/sirupsen/logrus"
)
// MountOpt is a Value type for parsing mounts
@ -112,6 +114,32 @@ func (m *MountOpt) Set(value string) error {
if err != nil {
return fmt.Errorf("invalid value for %s: %s", key, val)
}
logrus.Warn("bind-nonrecursive is deprecated, use bind-recursive=disabled instead")
case "bind-recursive":
valS := val
// Allow boolean as an alias to "enabled" or "disabled"
if b, err := strconv.ParseBool(valS); err == nil {
if b {
valS = "enabled"
} else {
valS = "disabled"
}
}
switch valS {
case "enabled": // read-only mounts are recursively read-only if Engine >= v25 && kernel >= v5.12, otherwise writable
// NOP
case "disabled": // alias of bind-nonrecursive=true
bindOptions().NonRecursive = true
case "writable": // conforms to the default read-only bind-mount of Docker v24; read-only mounts are recursively mounted but not recursively read-only
bindOptions().ReadOnlyNonRecursive = true
case "readonly": // force recursively read-only, or raise an error
bindOptions().ReadOnlyForceRecursive = true
// 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
default:
return fmt.Errorf("invalid value for %s: %s (must be \"enabled\", \"disabled\", \"writable\", or \"readonly\")",
key, val)
}
case "volume-nocopy":
volumeOptions().NoCopy, err = strconv.ParseBool(val)
if err != nil {
@ -161,6 +189,22 @@ func (m *MountOpt) Set(value string) error {
return fmt.Errorf("cannot mix 'tmpfs-*' options with mount type '%s'", mount.Type)
}
if mount.BindOptions != nil {
if mount.BindOptions.ReadOnlyNonRecursive {
if !mount.ReadOnly {
return errors.New("option 'bind-recursive=writable' requires 'readonly' to be specified in conjunction")
}
}
if mount.BindOptions.ReadOnlyForceRecursive {
if !mount.ReadOnly {
return errors.New("option 'bind-recursive=readonly' requires 'readonly' to be specified in conjunction")
}
if mount.BindOptions.Propagation != mounttypes.PropagationRPrivate {
return errors.New("option 'bind-recursive=readonly' requires 'bind-propagation=rprivate' to be specified in conjunction")
}
}
}
m.values = append(m.values, mount)
return nil
}

View File

@ -12,6 +12,8 @@ const (
networkOptAlias = "alias"
networkOptIPv4Address = "ip"
networkOptIPv6Address = "ip6"
networkOptMacAddress = "mac-address"
networkOptLinkLocalIP = "link-local-ip"
driverOpt = "driver-opt"
)
@ -23,7 +25,8 @@ type NetworkAttachmentOpts struct {
Links []string // TODO add support for links in the csv notation of `--network`
IPv4Address string
IPv6Address string
LinkLocalIPs []string // TODO add support for LinkLocalIPs in the csv notation of `--network` ?
LinkLocalIPs []string
MacAddress string
}
// NetworkOpt represents a network config in swarm mode.
@ -32,7 +35,7 @@ type NetworkOpt struct {
}
// Set networkopts value
func (n *NetworkOpt) Set(value string) error {
func (n *NetworkOpt) Set(value string) error { //nolint:gocyclo
longSyntax, err := regexp.MatchString(`\w+=\w+(,\w+=\w+)*`, value)
if err != nil {
return err
@ -66,6 +69,10 @@ func (n *NetworkOpt) Set(value string) error {
netOpt.IPv4Address = val
case networkOptIPv6Address:
netOpt.IPv6Address = val
case networkOptMacAddress:
netOpt.MacAddress = val
case networkOptLinkLocalIP:
netOpt.LinkLocalIPs = append(netOpt.LinkLocalIPs, val)
case driverOpt:
key, val, err = parseDriverOpt(val)
if err != nil {

View File

@ -224,13 +224,17 @@ type ValidatorFctType func(val string) (string, error)
// ValidatorFctListType defines a validator function that returns a validated list of string and/or an error
type ValidatorFctListType func(val string) ([]string, error)
// ValidateIPAddress validates an Ip address.
// ValidateIPAddress validates if the given value is a correctly formatted
// IP address, and returns the value in normalized form. Leading and trailing
// whitespace is allowed, but it does not allow IPv6 addresses surrounded by
// square brackets ("[::1]").
//
// Refer to [net.ParseIP] for accepted formats.
func ValidateIPAddress(val string) (string, error) {
ip := net.ParseIP(strings.TrimSpace(val))
if ip != nil {
if ip := net.ParseIP(strings.TrimSpace(val)); ip != nil {
return ip.String(), nil
}
return "", fmt.Errorf("%s is not an ip address", val)
return "", fmt.Errorf("IP address is not correctly formatted: %s", val)
}
// ValidateMACAddress validates a MAC address.

View File

@ -71,21 +71,26 @@ func ConvertKVStringsToMapWithNil(values []string) map[string]*string {
// ParseRestartPolicy returns the parsed policy or an error indicating what is incorrect
func ParseRestartPolicy(policy string) (container.RestartPolicy, error) {
p := container.RestartPolicy{}
if policy == "" {
return p, nil
// for backward-compatibility, we don't set the default ("no")
// policy here, because older versions of the engine may not
// support it.
return container.RestartPolicy{}, nil
}
k, v, _ := strings.Cut(policy, ":")
p := container.RestartPolicy{}
k, v, ok := strings.Cut(policy, ":")
if ok && k == "" {
return container.RestartPolicy{}, fmt.Errorf("invalid restart policy format: no policy provided before colon")
}
if v != "" {
count, err := strconv.Atoi(v)
if err != nil {
return p, fmt.Errorf("invalid restart policy format: maximum retry count must be an integer")
return container.RestartPolicy{}, fmt.Errorf("invalid restart policy format: maximum retry count must be an integer")
}
p.MaximumRetryCount = count
}
p.Name = k
p.Name = container.RestartPolicyMode(k)
return p, nil
}

View File

@ -27,6 +27,7 @@ Adam Miller <admiller@redhat.com>
Adam Mills <adam@armills.info>
Adam Pointer <adam.pointer@skybettingandgaming.com>
Adam Singer <financeCoding@gmail.com>
Adam Thornton <adam.thornton@maryville.com>
Adam Walz <adam@adamwalz.net>
Adam Williams <awilliams@mirantis.com>
AdamKorcz <adam@adalogics.com>
@ -173,6 +174,7 @@ Andy Rothfusz <github@developersupport.net>
Andy Smith <github@anarkystic.com>
Andy Wilson <wilson.andrew.j+github@gmail.com>
Andy Zhang <andy.zhangtao@hotmail.com>
Aneesh Kulkarni <askthefactorcamera@gmail.com>
Anes Hasicic <anes.hasicic@gmail.com>
Angel Velazquez <angelcar@amazon.com>
Anil Belur <askb23@gmail.com>
@ -262,7 +264,7 @@ Billy Ridgway <wrridgwa@us.ibm.com>
Bily Zhang <xcoder@tenxcloud.com>
Bin Liu <liubin0329@gmail.com>
Bingshen Wang <bingshen.wbs@alibaba-inc.com>
Bjorn Neergaard <bneergaard@mirantis.com>
Bjorn Neergaard <bjorn@neersighted.com>
Blake Geno <blakegeno@gmail.com>
Boaz Shuster <ripcurld.github@gmail.com>
bobby abbott <ttobbaybbob@gmail.com>
@ -433,8 +435,8 @@ Cristian Staretu <cristian.staretu@gmail.com>
cristiano balducci <cristiano.balducci@gmail.com>
Cristina Yenyxe Gonzalez Garcia <cristina.yenyxe@gmail.com>
Cruceru Calin-Cristian <crucerucalincristian@gmail.com>
cui fliter <imcusg@gmail.com>
CUI Wei <ghostplant@qq.com>
cuishuang <imcusg@gmail.com>
Cuong Manh Le <cuong.manhle.vn@gmail.com>
Cyprian Gracz <cyprian.gracz@micro-jumbo.eu>
Cyril F <cyrilf7x@gmail.com>
@ -602,6 +604,7 @@ Donald Huang <don.hcd@gmail.com>
Dong Chen <dongluo.chen@docker.com>
Donghwa Kim <shanytt@gmail.com>
Donovan Jones <git@gamma.net.nz>
Dorin Geman <dorin.geman@docker.com>
Doron Podoleanu <doronp@il.ibm.com>
Doug Davis <dug@us.ibm.com>
Doug MacEachern <dougm@vmware.com>
@ -676,6 +679,7 @@ Evan Allrich <evan@unguku.com>
Evan Carmi <carmi@users.noreply.github.com>
Evan Hazlett <ejhazlett@gmail.com>
Evan Krall <krall@yelp.com>
Evan Lezar <elezar@nvidia.com>
Evan Phoenix <evan@fallingsnow.net>
Evan Wies <evan@neomantra.net>
Evelyn Xu <evelynhsu21@gmail.com>
@ -983,6 +987,7 @@ Jean Rouge <rougej+github@gmail.com>
Jean-Baptiste Barth <jeanbaptiste.barth@gmail.com>
Jean-Baptiste Dalido <jeanbaptiste@appgratis.com>
Jean-Christophe Berthon <huygens@berthon.eu>
Jean-Michel Rouet <jm.rouet@gmail.com>
Jean-Paul Calderone <exarkun@twistedmatrix.com>
Jean-Pierre Huynh <jean-pierre.huynh@ounet.fr>
Jean-Tiare Le Bigot <jt@yadutaf.fr>
@ -1013,6 +1018,7 @@ Jeroen Jacobs <github@jeroenj.be>
Jesse Dearing <jesse.dearing@gmail.com>
Jesse Dubay <jesse@thefortytwo.net>
Jessica Frazelle <jess@oxide.computer>
Jeyanthinath Muthuram <jeyanthinath10@gmail.com>
Jezeniel Zapanta <jpzapanta22@gmail.com>
Jhon Honce <jhonce@redhat.com>
Ji.Zhilong <zhilongji@gmail.com>
@ -1141,6 +1147,7 @@ junxu <xujun@cmss.chinamobile.com>
Jussi Nummelin <jussi.nummelin@gmail.com>
Justas Brazauskas <brazauskasjustas@gmail.com>
Justen Martin <jmart@the-coder.com>
Justin Chadwell <me@jedevc.com>
Justin Cormack <justin.cormack@docker.com>
Justin Force <justin.force@gmail.com>
Justin Keller <85903732+jk-vb@users.noreply.github.com>
@ -1192,7 +1199,7 @@ Kenjiro Nakayama <nakayamakenjiro@gmail.com>
Kent Johnson <kentoj@gmail.com>
Kenta Tada <Kenta.Tada@sony.com>
Kevin "qwazerty" Houdebert <kevin.houdebert@gmail.com>
Kevin Alvarez <crazy-max@users.noreply.github.com>
Kevin Alvarez <github@crazymax.dev>
Kevin Burke <kev@inburke.com>
Kevin Clark <kevin.clark@gmail.com>
Kevin Feyrer <kevin.feyrer@btinternet.com>
@ -1225,6 +1232,7 @@ Konstantin Gribov <grossws@gmail.com>
Konstantin L <sw.double@gmail.com>
Konstantin Pelykh <kpelykh@zettaset.com>
Kostadin Plachkov <k.n.plachkov@gmail.com>
kpcyrd <git@rxv.cc>
Krasi Georgiev <krasi@vip-consult.solutions>
Krasimir Georgiev <support@vip-consult.co.uk>
Kris-Mikael Krister <krismikael@protonmail.com>
@ -1512,7 +1520,7 @@ Mike Snitzer <snitzer@redhat.com>
mikelinjie <294893458@qq.com>
Mikhail Sobolev <mss@mawhrin.net>
Miklos Szegedi <miklos.szegedi@cloudera.com>
Milas Bowman <milasb@gmail.com>
Milas Bowman <devnull@milas.dev>
Milind Chawre <milindchawre@gmail.com>
Miloslav Trmač <mitr@redhat.com>
mingqing <limingqing@cyou-inc.com>
@ -1606,6 +1614,7 @@ Noah Treuhaft <noah.treuhaft@docker.com>
NobodyOnSE <ich@sektor.selfip.com>
noducks <onemannoducks@gmail.com>
Nolan Darilek <nolan@thewordnerd.info>
Nolan Miles <nolanpmiles@gmail.com>
Noriki Nakamura <noriki.nakamura@miraclelinux.com>
nponeccop <andy.melnikov@gmail.com>
Nurahmadie <nurahmadie@gmail.com>
@ -1661,6 +1670,7 @@ Paul Lietar <paul@lietar.net>
Paul Liljenberg <liljenberg.paul@gmail.com>
Paul Morie <pmorie@gmail.com>
Paul Nasrat <pnasrat@gmail.com>
Paul Seiffert <paul.seiffert@jimdo.com>
Paul Weaver <pauweave@cisco.com>
Paulo Gomes <pjbgf@linux.com>
Paulo Ribeiro <paigr.io@gmail.com>
@ -1703,6 +1713,7 @@ Phil Estes <estesp@gmail.com>
Phil Sphicas <phil.sphicas@att.com>
Phil Spitler <pspitler@gmail.com>
Philip Alexander Etling <paetling@gmail.com>
Philip K. Warren <pkwarren@gmail.com>
Philip Monroe <phil@philmonroe.com>
Philipp Gillé <philipp.gille@gmail.com>
Philipp Wahala <philipp.wahala@gmail.com>
@ -1923,6 +1934,7 @@ Sebastiaan van Steenis <mail@superseb.nl>
Sebastiaan van Stijn <github@gone.nl>
Sebastian Höffner <sebastian.hoeffner@mevis.fraunhofer.de>
Sebastian Radloff <sradloff23@gmail.com>
Sebastian Thomschke <sebthom@users.noreply.github.com>
Sebastien Goasguen <runseb@gmail.com>
Senthil Kumar Selvaraj <senthil.thecoder@gmail.com>
Senthil Kumaran <senthil@uthcode.com>
@ -2204,6 +2216,7 @@ Vinod Kulkarni <vinod.kulkarni@gmail.com>
Vishal Doshi <vishal.doshi@gmail.com>
Vishnu Kannan <vishnuk@google.com>
Vitaly Ostrosablin <vostrosablin@virtuozzo.com>
Vitor Anjos <bartier@users.noreply.github.com>
Vitor Monteiro <vmrmonteiro@gmail.com>
Vivek Agarwal <me@vivek.im>
Vivek Dasgupta <vdasgupt@redhat.com>
@ -2250,6 +2263,7 @@ Wenxuan Zhao <viz@linux.com>
Wenyu You <21551128@zju.edu.cn>
Wenzhi Liang <wenzhi.liang@gmail.com>
Wes Morgan <cap10morgan@gmail.com>
Wesley Pettit <wppttt@amazon.com>
Wewang Xiaorenfine <wang.xiaoren@zte.com.cn>
Wiktor Kwapisiewicz <wiktor@metacode.biz>
Will Dietz <w@wdtz.org>
@ -2355,6 +2369,7 @@ Zen Lin(Zhinan Lin) <linzhinan@huawei.com>
Zhang Kun <zkazure@gmail.com>
Zhang Wei <zhangwei555@huawei.com>
Zhang Wentao <zhangwentao234@huawei.com>
zhangguanzhang <zhangguanzhang@qq.com>
ZhangHang <stevezhang2014@gmail.com>
zhangxianwei <xianwei.zw@alibaba-inc.com>
Zhenan Ye <21551168@zju.edu.cn>
@ -2381,6 +2396,7 @@ Zuhayr Elahi <zuhayr.elahi@docker.com>
Zunayed Ali <zunayed@gmail.com>
Álvaro Lázaro <alvaro.lazaro.g@gmail.com>
Átila Camurça Alves <camurca.home@gmail.com>
吴小白 <296015668@qq.com>
尹吉峰 <jifeng.yin@gmail.com>
屈骏 <qujun@tiduyun.com>
徐俊杰 <paco.xu@daocloud.io>

View File

@ -37,6 +37,6 @@ There is hopefully enough example material in the file for you to copy a similar
When you make edits to `swagger.yaml`, you may want to check the generated API documentation to ensure it renders correctly.
Run `make swagger-docs` and a preview will be running at `http://localhost`. Some of the styling may be incorrect, but you'll be able to ensure that it is generating the correct documentation.
Run `make swagger-docs` and a preview will be running at `http://localhost:9000`. Some of the styling may be incorrect, but you'll be able to ensure that it is generating the correct documentation.
The production documentation is generated by vendoring `swagger.yaml` into [docker/docker.github.io](https://github.com/docker/docker.github.io).

View File

@ -3,7 +3,7 @@ package api // import "github.com/docker/docker/api"
// Common constants for daemon and client.
const (
// DefaultVersion of Current REST API
DefaultVersion = "1.43"
DefaultVersion = "1.44"
// NoBaseImageSpecifier is the symbol used by the FROM
// command to specify that no base image is to be used.

View File

@ -1,5 +1,4 @@
//go:build !windows
// +build !windows
package api // import "github.com/docker/docker/api"

View File

@ -19,10 +19,10 @@ produces:
consumes:
- "application/json"
- "text/plain"
basePath: "/v1.43"
basePath: "/v1.44"
info:
title: "Docker Engine API"
version: "1.43"
version: "1.44"
x-logo:
url: "https://docs.docker.com/assets/images/logo-docker-main.png"
description: |
@ -55,8 +55,8 @@ info:
the URL is not supported by the daemon, a HTTP `400 Bad Request` error message
is returned.
If you omit the version-prefix, the current version of the API (v1.43) is used.
For example, calling `/info` is the same as calling `/v1.43/info`. Using the
If you omit the version-prefix, the current version of the API (v1.44) is used.
For example, calling `/info` is the same as calling `/v1.44/info`. Using the
API without a version-prefix is deprecated and will be removed in a future release.
Engine releases in the near future should support this version of the API,
@ -388,6 +388,16 @@ definitions:
description: "Create mount point on host if missing"
type: "boolean"
default: false
ReadOnlyNonRecursive:
description: |
Make the mount non-recursively read-only, but still leave the mount recursive
(unless NonRecursive is set to true in conjunction).
type: "boolean"
default: false
ReadOnlyForceRecursive:
description: "Raise an error if the mount cannot be made recursively read-only."
type: "boolean"
default: false
VolumeOptions:
description: "Optional configuration for the `volume` type."
type: "object"
@ -794,6 +804,12 @@ definitions:
1000000 (1 ms). 0 means inherit.
type: "integer"
format: "int64"
StartInterval:
description: |
The time to wait between checks in nanoseconds during the start period.
It should be 0 or at least 1000000 (1 ms). 0 means inherit.
type: "integer"
format: "int64"
Health:
description: |
@ -1297,7 +1313,10 @@ definitions:
type: "boolean"
x-nullable: true
MacAddress:
description: "MAC address of the container."
description: |
MAC address of the container.
Deprecated: this field is deprecated in API v1.44 and up. Use EndpointSettings.MacAddress instead.
type: "string"
x-nullable: true
OnBuild:
@ -1347,16 +1366,16 @@ definitions:
EndpointsConfig:
description: |
A mapping of network name to endpoint configuration for that network.
The endpoint configuration can be left empty to connect to that
network with no particular endpoint configuration.
type: "object"
additionalProperties:
$ref: "#/definitions/EndpointSettings"
example:
# putting an example here, instead of using the example values from
# /definitions/EndpointSettings, because containers/create currently
# does not support attaching to multiple networks, so the example request
# would be confusing if it showed that multiple networks can be contained
# in the EndpointsConfig.
# TODO remove once we support multiple networks on container create (see https://github.com/moby/moby/blob/07e6b843594e061f82baa5fa23c2ff7d536c2a05/daemon/create.go#L323)
# /definitions/EndpointSettings, because EndpointSettings contains
# operational data returned when inspecting a container that we don't
# accept here.
EndpointsConfig:
isolated_nw:
IPAMConfig:
@ -1365,12 +1384,14 @@ definitions:
LinkLocalIPs:
- "169.254.34.68"
- "fe80::3468"
MacAddress: "02:42:ac:12:05:02"
Links:
- "container_1"
- "container_2"
Aliases:
- "server_x"
- "server_y"
database_nw: {}
NetworkSettings:
description: "NetworkSettings exposes the network settings in the API"
@ -1781,13 +1802,7 @@ definitions:
description: |
Total size of the image including all layers it is composed of.
In versions of Docker before v1.10, this field was calculated from
the image itself and all of its parent images. Images are now stored
self-contained, and no longer use a parent-chain, making this field
an equivalent of the Size field.
> **Deprecated**: this field is kept for backward compatibility, but
> will be removed in API v1.44.
Deprecated: this field is omitted in API v1.44, but kept for backward compatibility. Use Size instead.
type: "integer"
format: "int64"
example: 1239828
@ -1829,6 +1844,7 @@ definitions:
x-nullable: true
ImageSummary:
type: "object"
x-go-name: "Summary"
required:
- Id
- ParentId
@ -1925,12 +1941,7 @@ definitions:
description: |-
Total size of the image including all layers it is composed of.
In versions of Docker before v1.10, this field was calculated from
the image itself and all of its parent images. Images are now stored
self-contained, and no longer use a parent-chain, making this field
an equivalent of the Size field.
Deprecated: this field is kept for backward compatibility, and will be removed in API v1.44.
Deprecated: this field is omitted in API v1.44, but kept for backward compatibility. Use Size instead.
type: "integer"
format: "int64"
example: 172064416
@ -2448,6 +2459,11 @@ definitions:
example:
- "container_1"
- "container_2"
MacAddress:
description: |
MAC address for the endpoint on this network. The network driver might ignore this parameter.
type: "string"
example: "02:42:ac:11:00:04"
Aliases:
type: "array"
items:
@ -2498,11 +2514,6 @@ definitions:
type: "integer"
format: "int64"
example: 64
MacAddress:
description: |
MAC address for the endpoint on this network.
type: "string"
example: "02:42:ac:11:00:04"
DriverOpts:
description: |
DriverOpts is a mapping of driver options and values. These options
@ -3547,6 +3558,32 @@ definitions:
Level:
type: "string"
description: "SELinux level label"
Seccomp:
type: "object"
description: "Options for configuring seccomp on the container"
properties:
Mode:
type: "string"
enum:
- "default"
- "unconfined"
- "custom"
Profile:
description: "The custom seccomp profile as a json object"
type: "string"
AppArmor:
type: "object"
description: "Options for configuring AppArmor on the container"
properties:
Mode:
type: "string"
enum:
- "default"
- "disabled"
NoNewPrivileges:
type: "boolean"
description: "Configuration of the no_new_privs bit in the container"
TTY:
description: "Whether a pseudo-TTY should be allocated."
type: "boolean"
@ -4445,6 +4482,7 @@ definitions:
ImageDeleteResponseItem:
type: "object"
x-go-name: "DeleteResponse"
properties:
Untagged:
description: "The image ID of an image that was untagged"
@ -4453,6 +4491,29 @@ definitions:
description: "The image ID of an image that was deleted"
type: "string"
ServiceCreateResponse:
type: "object"
description: |
contains the information returned to a client on the
creation of a new service.
properties:
ID:
description: "The ID of the created service."
type: "string"
x-nullable: false
example: "ak7w3gjqoa3kuz8xcpnyy0pvl"
Warnings:
description: |
Optional warning message.
FIXME(thaJeztah): this should have "omitempty" in the generated type.
type: "array"
x-nullable: true
items:
type: "string"
example:
- "unable to pin image doesnotexist:latest to digest: image library/doesnotexist:latest not found"
ServiceUpdateResponse:
type: "object"
properties:
@ -4462,7 +4523,8 @@ definitions:
items:
type: "string"
example:
Warning: "unable to pin image doesnotexist:latest to digest: image library/doesnotexist:latest not found"
Warnings:
- "unable to pin image doesnotexist:latest to digest: image library/doesnotexist:latest not found"
ContainerSummary:
type: "object"
@ -5068,7 +5130,7 @@ definitions:
Go runtime (`GOOS`).
Currently returned values are "linux" and "windows". A full list of
possible values can be found in the [Go documentation](https://golang.org/doc/install/source#environment).
possible values can be found in the [Go documentation](https://go.dev/doc/install/source#environment).
type: "string"
example: "linux"
Architecture:
@ -5076,7 +5138,7 @@ definitions:
Hardware architecture of the host, as returned by the Go runtime
(`GOARCH`).
A full list of possible values can be found in the [Go documentation](https://golang.org/doc/install/source#environment).
A full list of possible values can be found in the [Go documentation](https://go.dev/doc/install/source#environment).
type: "string"
example: "x86_64"
NCPU:
@ -5296,7 +5358,25 @@ definitions:
- "WARNING: No memory limit support"
- "WARNING: bridge-nf-call-iptables is disabled"
- "WARNING: bridge-nf-call-ip6tables is disabled"
CDISpecDirs:
description: |
List of directories where (Container Device Interface) CDI
specifications are located.
These specifications define vendor-specific modifications to an OCI
runtime specification for a container being created.
An empty list indicates that CDI device injection is disabled.
Note that since using CDI device injection requires the daemon to have
experimental enabled. For non-experimental daemons an empty list will
always be returned.
type: "array"
items:
type: "string"
example:
- "/etc/cdi"
- "/var/run/cdi"
# PluginsInfo is a temp struct holding Plugins name
# registered with docker daemon. It is used by Info struct
@ -6416,6 +6496,7 @@ paths:
Aliases:
- "server_x"
- "server_y"
database_nw: {}
required: true
responses:
@ -6563,7 +6644,7 @@ paths:
StopSignal: "SIGTERM"
StopTimeout: 10
Created: "2015-01-06T15:47:31.485331387Z"
Driver: "devicemapper"
Driver: "overlay2"
ExecIDs:
- "b35395de42bc8abd327f9dd65d913b9ba28c74d2f0734eeeae84fa1c616a0fca"
- "3fc1232e5cd20c8de182ed81178503dc6437f4e7ef12b52cc5e8de020652f1c4"
@ -7994,6 +8075,7 @@ paths:
- `label=key` or `label="key=value"` of an image label
- `reference`=(`<image-name>[:<tag>]`)
- `since`=(`<image-name>[:<tag>]`, `<image id>` or `<image@digest>`)
- `until=<timestamp>`
type: "string"
- name: "shared-size"
in: "query"
@ -8245,7 +8327,7 @@ paths:
/images/create:
post:
summary: "Create an image"
description: "Create an image by either pulling it from a registry or importing it."
description: "Pull or import an image."
operationId: "ImageCreate"
consumes:
- "text/plain"
@ -8596,28 +8678,36 @@ paths:
is_official:
type: "boolean"
is_automated:
description: |
Whether this repository has automated builds enabled.
<p><br /></p>
> **Deprecated**: This field is deprecated and will always
> be "false" in future.
type: "boolean"
example: false
name:
type: "string"
star_count:
type: "integer"
examples:
application/json:
- description: ""
is_official: false
- description: "A minimal Docker image based on Alpine Linux with a complete package index and only 5 MB in size!"
is_official: true
is_automated: false
name: "wma55/u1210sshd"
star_count: 0
- description: ""
is_official: false
name: "alpine"
star_count: 10093
- description: "Busybox base image."
is_official: true
is_automated: false
name: "jdswinbank/sshd"
star_count: 0
- description: ""
is_official: false
name: "Busybox base image."
star_count: 3037
- description: "The PostgreSQL object-relational database system provides reliability and data integrity."
is_official: true
is_automated: false
name: "vgauthier/sshd"
star_count: 0
name: "postgres"
star_count: 12408
500:
description: "Server error"
schema:
@ -8637,9 +8727,13 @@ paths:
description: |
A JSON encoded value of the filters (a `map[string][]string`) to process on the images list. Available filters:
- `is-automated=(true|false)`
- `is-automated=(true|false)` (deprecated, see below)
- `is-official=(true|false)`
- `stars=<number>` Matches images that has at least 'number' stars.
The `is-automated` filter is deprecated. The `is_automated` field has
been deprecated by Docker Hub's search API. Consequently, searching
for `is-automated=true` will yield no results.
type: "string"
tags: ["Image"]
/images/prune:
@ -9032,7 +9126,6 @@ paths:
Created: 1466724217
Size: 1092588
SharedSize: 0
VirtualSize: 1092588
Labels: {}
Containers: 1
Containers:
@ -9895,6 +9988,10 @@ paths:
example:
Id: "22be93d5babb089c5aab8dbc369042fad48ff791584ca2da2100db837a1c7c30"
Warning: ""
400:
description: "bad parameter"
schema:
$ref: "#/definitions/ErrorResponse"
403:
description: |
Forbidden operation. This happens when trying to create a network named after a pre-defined network,
@ -9924,13 +10021,7 @@ paths:
type: "string"
CheckDuplicate:
description: |
Check for networks with duplicate names. Since Network is
primarily keyed based on a random ID and not on the name, and
network name is strictly a user-friendly alias to the network
which is uniquely identified using ID, there is no guaranteed
way to check for duplicates. CheckDuplicate is there to provide
a best effort checking of any networks which has the same name
but it is not guaranteed to catch all name collisions.
Deprecated: CheckDuplicate is now always enabled.
type: "boolean"
Driver:
description: "Name of the network driver plugin to use."
@ -9998,14 +10089,19 @@ paths:
/networks/{id}/connect:
post:
summary: "Connect a container to a network"
description: "The network must be either a local-scoped network or a swarm-scoped network with the `attachable` option set. A network cannot be re-attached to a running container"
operationId: "NetworkConnect"
consumes:
- "application/json"
responses:
200:
description: "No error"
400:
description: "bad parameter"
schema:
$ref: "#/definitions/ErrorResponse"
403:
description: "Operation not supported for swarm scoped networks"
description: "Operation forbidden"
schema:
$ref: "#/definitions/ErrorResponse"
404:
@ -10040,6 +10136,7 @@ paths:
IPAMConfig:
IPv4Address: "172.24.56.89"
IPv6Address: "2001:db8::5689"
MacAddress: "02:42:ac:12:05:02"
tags: ["Network"]
/networks/{id}/disconnect:
@ -11033,18 +11130,7 @@ paths:
201:
description: "no error"
schema:
type: "object"
title: "ServiceCreateResponse"
properties:
ID:
description: "The ID of the created service."
type: "string"
Warning:
description: "Optional warning message"
type: "string"
example:
ID: "ak7w3gjqoa3kuz8xcpnyy0pvl"
Warning: "unable to pin image doesnotexist:latest to digest: image library/doesnotexist:latest not found"
$ref: "#/definitions/ServiceCreateResponse"
400:
description: "bad parameter"
schema:

View File

@ -1,7 +0,0 @@
package types // import "github.com/docker/docker/api/types"
import "github.com/docker/docker/api/types/registry"
// AuthConfig contains authorization information for connecting to a Registry.
//
// Deprecated: use github.com/docker/docker/api/types/registry.AuthConfig
type AuthConfig = registry.AuthConfig

View File

@ -0,0 +1,7 @@
package checkpoint
// Summary represents the details of a checkpoint when listing endpoints.
type Summary struct {
// Name is the name of the checkpoint.
Name string
}

View File

@ -0,0 +1,19 @@
package checkpoint
// CreateOptions holds parameters to create a checkpoint from a container.
type CreateOptions struct {
CheckpointID string
CheckpointDir string
Exit bool
}
// ListOptions holds parameters to list checkpoints for a container.
type ListOptions struct {
CheckpointDir string
}
// DeleteOptions holds parameters to delete a checkpoint from a container.
type DeleteOptions struct {
CheckpointID string
CheckpointDir string
}

View File

@ -11,44 +11,6 @@ import (
units "github.com/docker/go-units"
)
// CheckpointCreateOptions holds parameters to create a checkpoint from a container
type CheckpointCreateOptions struct {
CheckpointID string
CheckpointDir string
Exit bool
}
// CheckpointListOptions holds parameters to list checkpoints for a container
type CheckpointListOptions struct {
CheckpointDir string
}
// CheckpointDeleteOptions holds parameters to delete a checkpoint from a container
type CheckpointDeleteOptions struct {
CheckpointID string
CheckpointDir string
}
// ContainerAttachOptions holds parameters to attach to a container.
type ContainerAttachOptions struct {
Stream bool
Stdin bool
Stdout bool
Stderr bool
DetachKeys string
Logs bool
}
// ContainerCommitOptions holds parameters to commit changes into a container.
type ContainerCommitOptions struct {
Reference string
Comment string
Author string
Changes []string
Pause bool
Config *container.Config
}
// ContainerExecInspect holds information returned by exec inspect.
type ContainerExecInspect struct {
ExecID string `json:"ID"`
@ -58,42 +20,6 @@ type ContainerExecInspect struct {
Pid int
}
// ContainerListOptions holds parameters to list containers with.
type ContainerListOptions struct {
Size bool
All bool
Latest bool
Since string
Before string
Limit int
Filters filters.Args
}
// ContainerLogsOptions holds parameters to filter logs with.
type ContainerLogsOptions struct {
ShowStdout bool
ShowStderr bool
Since string
Until string
Timestamps bool
Follow bool
Tail string
Details bool
}
// ContainerRemoveOptions holds parameters to remove containers.
type ContainerRemoveOptions struct {
RemoveVolumes bool
RemoveLinks bool
Force bool
}
// ContainerStartOptions holds parameters to start containers.
type ContainerStartOptions struct {
CheckpointID string
CheckpointDir string
}
// CopyToContainerOptions holds information
// about files to copy into a container
type CopyToContainerOptions struct {
@ -307,14 +233,6 @@ type ImageSearchOptions struct {
Limit int
}
// ResizeOptions holds parameters to resize a tty.
// It can be used to resize container ttys and
// exec process ttys too.
type ResizeOptions struct {
Height uint
Width uint
}
// NodeListOptions holds parameters to list nodes with.
type NodeListOptions struct {
Filters filters.Args
@ -340,15 +258,6 @@ type ServiceCreateOptions struct {
QueryRegistry bool
}
// ServiceCreateResponse contains the information returned to a client
// on the creation of a new service.
type ServiceCreateResponse struct {
// ID is the ID of the created service.
ID string
// Warnings is a set of non-fatal warning messages to pass on to the user.
Warnings []string `json:",omitempty"`
}
// Values for RegistryAuthFrom in ServiceUpdateOptions
const (
RegistryAuthFromSpec = "spec"

View File

@ -1,6 +0,0 @@
package container
// ContainerChangeResponseItem change item in response to ContainerChanges operation
//
// Deprecated: use [FilesystemChange].
type ContainerChangeResponseItem = FilesystemChange

View File

@ -5,6 +5,7 @@ import (
"time"
"github.com/docker/docker/api/types/strslice"
dockerspec "github.com/docker/docker/image/spec/specs-go/v1"
"github.com/docker/go-connections/nat"
)
@ -33,25 +34,7 @@ type StopOptions struct {
}
// HealthConfig holds configuration settings for the HEALTHCHECK feature.
type HealthConfig struct {
// Test is the test to perform to check that the container is healthy.
// An empty slice means to inherit the default.
// The options are:
// {} : inherit healthcheck
// {"NONE"} : disable healthcheck
// {"CMD", args...} : exec arguments directly
// {"CMD-SHELL", command} : run command with system's default shell
Test []string `json:",omitempty"`
// Zero means to inherit. Durations are expressed as integer nanoseconds.
Interval time.Duration `json:",omitempty"` // Interval is the time to wait between checks.
Timeout time.Duration `json:",omitempty"` // Timeout is the time to wait before considering the check to have hung.
StartPeriod time.Duration `json:",omitempty"` // The start period for the container to initialize before the retries starts to count down.
// Retries is the number of consecutive failures needed to consider a container as unhealthy.
// Zero means inherit.
Retries int `json:",omitempty"`
}
type HealthConfig = dockerspec.HealthcheckConfig
// ExecStartOptions holds the options to start container's exec.
type ExecStartOptions struct {
@ -87,10 +70,13 @@ type Config struct {
WorkingDir string // Current directory (PWD) in the command will be launched
Entrypoint strslice.StrSlice // Entrypoint to run when starting the container
NetworkDisabled bool `json:",omitempty"` // Is network disabled
MacAddress string `json:",omitempty"` // Mac Address of the container
OnBuild []string // ONBUILD metadata that were defined on the image Dockerfile
Labels map[string]string // List of labels set to this container
StopSignal string `json:",omitempty"` // Signal to stop a container
StopTimeout *int `json:",omitempty"` // Timeout (in seconds) to stop a container
Shell strslice.StrSlice `json:",omitempty"` // Shell for shell-form of RUN, CMD, ENTRYPOINT
// Mac Address of the container.
//
// Deprecated: this field is deprecated since API v1.44. Use EndpointSettings.MacAddress instead.
MacAddress string `json:",omitempty"`
OnBuild []string // ONBUILD metadata that were defined on the image Dockerfile
Labels map[string]string // List of labels set to this container
StopSignal string `json:",omitempty"` // Signal to stop a container
StopTimeout *int `json:",omitempty"` // Timeout (in seconds) to stop a container
Shell strslice.StrSlice `json:",omitempty"` // Shell for shell-form of RUN, CMD, ENTRYPOINT
}

View File

@ -0,0 +1,9 @@
package container
type errInvalidParameter struct{ error }
func (e *errInvalidParameter) InvalidParameter() {}
func (e *errInvalidParameter) Unwrap() error {
return e.error
}

View File

@ -1,6 +1,7 @@
package container // import "github.com/docker/docker/api/types/container"
import (
"fmt"
"strings"
"github.com/docker/docker/api/types/blkiodev"
@ -271,33 +272,42 @@ type DeviceMapping struct {
// RestartPolicy represents the restart policies of the container.
type RestartPolicy struct {
Name string
Name RestartPolicyMode
MaximumRetryCount int
}
type RestartPolicyMode string
const (
RestartPolicyDisabled RestartPolicyMode = "no"
RestartPolicyAlways RestartPolicyMode = "always"
RestartPolicyOnFailure RestartPolicyMode = "on-failure"
RestartPolicyUnlessStopped RestartPolicyMode = "unless-stopped"
)
// IsNone indicates whether the container has the "no" restart policy.
// This means the container will not automatically restart when exiting.
func (rp *RestartPolicy) IsNone() bool {
return rp.Name == "no" || rp.Name == ""
return rp.Name == RestartPolicyDisabled || rp.Name == ""
}
// IsAlways indicates whether the container has the "always" restart policy.
// This means the container will automatically restart regardless of the exit status.
func (rp *RestartPolicy) IsAlways() bool {
return rp.Name == "always"
return rp.Name == RestartPolicyAlways
}
// IsOnFailure indicates whether the container has the "on-failure" restart policy.
// This means the container will automatically restart of exiting with a non-zero exit status.
func (rp *RestartPolicy) IsOnFailure() bool {
return rp.Name == "on-failure"
return rp.Name == RestartPolicyOnFailure
}
// IsUnlessStopped indicates whether the container has the
// "unless-stopped" restart policy. This means the container will
// automatically restart unless user has put it to stopped state.
func (rp *RestartPolicy) IsUnlessStopped() bool {
return rp.Name == "unless-stopped"
return rp.Name == RestartPolicyUnlessStopped
}
// IsSame compares two RestartPolicy to see if they are the same
@ -305,6 +315,33 @@ func (rp *RestartPolicy) IsSame(tp *RestartPolicy) bool {
return rp.Name == tp.Name && rp.MaximumRetryCount == tp.MaximumRetryCount
}
// ValidateRestartPolicy validates the given RestartPolicy.
func ValidateRestartPolicy(policy RestartPolicy) error {
switch policy.Name {
case RestartPolicyAlways, RestartPolicyUnlessStopped, RestartPolicyDisabled:
if policy.MaximumRetryCount != 0 {
msg := "invalid restart policy: maximum retry count can only be used with 'on-failure'"
if policy.MaximumRetryCount < 0 {
msg += " and cannot be negative"
}
return &errInvalidParameter{fmt.Errorf(msg)}
}
return nil
case RestartPolicyOnFailure:
if policy.MaximumRetryCount < 0 {
return &errInvalidParameter{fmt.Errorf("invalid restart policy: maximum retry count cannot be negative")}
}
return nil
case "":
// Versions before v25.0.0 created an empty restart-policy "name" as
// default. Allow an empty name with "any" MaximumRetryCount for
// backward-compatibility.
return nil
default:
return &errInvalidParameter{fmt.Errorf("invalid restart policy: unknown policy '%s'; use one of '%s', '%s', '%s', or '%s'", policy.Name, RestartPolicyDisabled, RestartPolicyAlways, RestartPolicyOnFailure, RestartPolicyUnlessStopped)}
}
}
// LogMode is a type to define the available modes for logging
// These modes affect how logs are handled when log messages start piling up.
type LogMode string

View File

@ -1,5 +1,4 @@
//go:build !windows
// +build !windows
package container // import "github.com/docker/docker/api/types/container"

View File

@ -0,0 +1,67 @@
package container
import "github.com/docker/docker/api/types/filters"
// ResizeOptions holds parameters to resize a TTY.
// It can be used to resize container TTYs and
// exec process TTYs too.
type ResizeOptions struct {
Height uint
Width uint
}
// AttachOptions holds parameters to attach to a container.
type AttachOptions struct {
Stream bool
Stdin bool
Stdout bool
Stderr bool
DetachKeys string
Logs bool
}
// CommitOptions holds parameters to commit changes into a container.
type CommitOptions struct {
Reference string
Comment string
Author string
Changes []string
Pause bool
Config *Config
}
// RemoveOptions holds parameters to remove containers.
type RemoveOptions struct {
RemoveVolumes bool
RemoveLinks bool
Force bool
}
// StartOptions holds parameters to start containers.
type StartOptions struct {
CheckpointID string
CheckpointDir string
}
// ListOptions holds parameters to list containers with.
type ListOptions struct {
Size bool
All bool
Latest bool
Since string
Before string
Limit int
Filters filters.Args
}
// LogsOptions holds parameters to filter logs with.
type LogsOptions struct {
ShowStdout bool
ShowStderr bool
Since string
Until string
Timestamps bool
Follow bool
Tail string
Details bool
}

View File

@ -1,7 +1,7 @@
package events // import "github.com/docker/docker/api/types/events"
// Type is used for event-types.
type Type = string
type Type string
// List of known event types.
const (
@ -18,6 +18,86 @@ const (
VolumeEventType Type = "volume" // VolumeEventType is the event type that volumes generate.
)
// Action is used for event-actions.
type Action string
const (
ActionCreate Action = "create"
ActionStart Action = "start"
ActionRestart Action = "restart"
ActionStop Action = "stop"
ActionCheckpoint Action = "checkpoint"
ActionPause Action = "pause"
ActionUnPause Action = "unpause"
ActionAttach Action = "attach"
ActionDetach Action = "detach"
ActionResize Action = "resize"
ActionUpdate Action = "update"
ActionRename Action = "rename"
ActionKill Action = "kill"
ActionDie Action = "die"
ActionOOM Action = "oom"
ActionDestroy Action = "destroy"
ActionRemove Action = "remove"
ActionCommit Action = "commit"
ActionTop Action = "top"
ActionCopy Action = "copy"
ActionArchivePath Action = "archive-path"
ActionExtractToDir Action = "extract-to-dir"
ActionExport Action = "export"
ActionImport Action = "import"
ActionSave Action = "save"
ActionLoad Action = "load"
ActionTag Action = "tag"
ActionUnTag Action = "untag"
ActionPush Action = "push"
ActionPull Action = "pull"
ActionPrune Action = "prune"
ActionDelete Action = "delete"
ActionEnable Action = "enable"
ActionDisable Action = "disable"
ActionConnect Action = "connect"
ActionDisconnect Action = "disconnect"
ActionReload Action = "reload"
ActionMount Action = "mount"
ActionUnmount Action = "unmount"
// ActionExecCreate is the prefix used for exec_create events. These
// event-actions are commonly followed by a colon and space (": "),
// and the command that's defined for the exec, for example:
//
// exec_create: /bin/sh -c 'echo hello'
//
// This is far from ideal; it's a compromise to allow filtering and
// to preserve backward-compatibility.
ActionExecCreate Action = "exec_create"
// ActionExecStart is the prefix used for exec_create events. These
// event-actions are commonly followed by a colon and space (": "),
// and the command that's defined for the exec, for example:
//
// exec_start: /bin/sh -c 'echo hello'
//
// This is far from ideal; it's a compromise to allow filtering and
// to preserve backward-compatibility.
ActionExecStart Action = "exec_start"
ActionExecDie Action = "exec_die"
ActionExecDetach Action = "exec_detach"
// ActionHealthStatus is the prefix to use for health_status events.
//
// Health-status events can either have a pre-defined status, in which
// case the "health_status" action is followed by a colon, or can be
// "free-form", in which case they're followed by the output of the
// health-check output.
//
// This is far form ideal, and a compromise to allow filtering, and
// to preserve backward-compatibility.
ActionHealthStatus Action = "health_status"
ActionHealthStatusRunning Action = "health_status: running"
ActionHealthStatusHealthy Action = "health_status: healthy"
ActionHealthStatusUnhealthy Action = "health_status: unhealthy"
)
// Actor describes something that generates events,
// like a container, or a network, or a volume.
// It has a defined name and a set of attributes.
@ -37,7 +117,7 @@ type Message struct {
From string `json:"from,omitempty"` // Deprecated: use Actor.Attributes["image"] instead.
Type Type
Action string
Action Action
Actor Actor
// Engine events are local scope. Cluster events are swarm scope.
Scope string `json:"scope,omitempty"`

View File

@ -98,7 +98,7 @@ func FromJSON(p string) (Args, error) {
// Fallback to parsing arguments in the legacy slice format
deprecated := map[string][]string{}
if legacyErr := json.Unmarshal(raw, &deprecated); legacyErr != nil {
return args, invalidFilter{}
return args, &invalidFilter{}
}
args.fields = deprecatedArgs(deprecated)
@ -206,7 +206,7 @@ func (args Args) GetBoolOrDefault(key string, defaultValue bool) (bool, error) {
}
if len(fieldValues) == 0 {
return defaultValue, invalidFilter{key, nil}
return defaultValue, &invalidFilter{key, nil}
}
isFalse := fieldValues["0"] || fieldValues["false"]
@ -216,7 +216,7 @@ func (args Args) GetBoolOrDefault(key string, defaultValue bool) (bool, error) {
invalid := !isFalse && !isTrue
if conflicting || invalid {
return defaultValue, invalidFilter{key, args.Get(key)}
return defaultValue, &invalidFilter{key, args.Get(key)}
} else if isFalse {
return false, nil
} else if isTrue {
@ -224,7 +224,7 @@ func (args Args) GetBoolOrDefault(key string, defaultValue bool) (bool, error) {
}
// This code shouldn't be reached.
return defaultValue, unreachableCode{Filter: key, Value: args.Get(key)}
return defaultValue, &unreachableCode{Filter: key, Value: args.Get(key)}
}
// ExactMatch returns true if the source matches exactly one of the values.
@ -282,7 +282,7 @@ func (args Args) Contains(field string) bool {
func (args Args) Validate(accepted map[string]bool) error {
for name := range args.fields {
if !accepted[name] {
return invalidFilter{name, nil}
return &invalidFilter{name, nil}
}
}
return nil

View File

@ -1,11 +1,11 @@
package types
package image
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
// ImageDeleteResponseItem image delete response item
// swagger:model ImageDeleteResponseItem
type ImageDeleteResponseItem struct {
// DeleteResponse delete response
// swagger:model DeleteResponse
type DeleteResponse struct {
// The image ID of an image that was deleted
Deleted string `json:"Deleted,omitempty"`

View File

@ -0,0 +1,9 @@
package image
import "time"
// Metadata contains engine-local data about the image.
type Metadata struct {
// LastTagTime is the date and time at which the image was last tagged.
LastTagTime time.Time `json:",omitempty"`
}

View File

@ -1,11 +1,11 @@
package types
package image
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
// ImageSummary image summary
// swagger:model ImageSummary
type ImageSummary struct {
// Summary summary
// swagger:model Summary
type Summary struct {
// Number of containers using this image. Includes both stopped and running
// containers.
@ -84,11 +84,6 @@ type ImageSummary struct {
// Total size of the image including all layers it is composed of.
//
// In versions of Docker before v1.10, this field was calculated from
// the image itself and all of its parent images. Images are now stored
// self-contained, and no longer use a parent-chain, making this field
// an equivalent of the Size field.
//
// Deprecated: this field is kept for backward compatibility, and will be removed in API v1.44.
// Deprecated: this field is omitted in API v1.44, but kept for backward compatibility. Use Size instead.
VirtualSize int64 `json:"VirtualSize,omitempty"`
}

View File

@ -29,7 +29,7 @@ type Mount struct {
// Source is not supported for tmpfs (must be an empty value)
Source string `json:",omitempty"`
Target string `json:",omitempty"`
ReadOnly bool `json:",omitempty"`
ReadOnly bool `json:",omitempty"` // attempts recursive read-only if possible
Consistency Consistency `json:",omitempty"`
BindOptions *BindOptions `json:",omitempty"`
@ -85,6 +85,11 @@ type BindOptions struct {
Propagation Propagation `json:",omitempty"`
NonRecursive bool `json:",omitempty"`
CreateMountpoint bool `json:",omitempty"`
// ReadOnlyNonRecursive makes the mount non-recursively read-only, but still leaves the mount recursive
// (unless NonRecursive is set to true in conjunction).
ReadOnlyNonRecursive bool `json:",omitempty"`
// ReadOnlyForceRecursive raises an error if the mount cannot be made recursively read-only.
ReadOnlyForceRecursive bool `json:",omitempty"`
}
// VolumeOptions represents the options for a mount of type volume.

View File

@ -0,0 +1,135 @@
package network
import (
"errors"
"fmt"
"net"
"github.com/docker/docker/internal/multierror"
)
// EndpointSettings stores the network endpoint details
type EndpointSettings struct {
// Configurations
IPAMConfig *EndpointIPAMConfig
Links []string
Aliases []string
MacAddress string
// Operational data
NetworkID string
EndpointID string
Gateway string
IPAddress string
IPPrefixLen int
IPv6Gateway string
GlobalIPv6Address string
GlobalIPv6PrefixLen int
DriverOpts map[string]string
}
// Copy makes a deep copy of `EndpointSettings`
func (es *EndpointSettings) Copy() *EndpointSettings {
epCopy := *es
if es.IPAMConfig != nil {
epCopy.IPAMConfig = es.IPAMConfig.Copy()
}
if es.Links != nil {
links := make([]string, 0, len(es.Links))
epCopy.Links = append(links, es.Links...)
}
if es.Aliases != nil {
aliases := make([]string, 0, len(es.Aliases))
epCopy.Aliases = append(aliases, es.Aliases...)
}
return &epCopy
}
// EndpointIPAMConfig represents IPAM configurations for the endpoint
type EndpointIPAMConfig struct {
IPv4Address string `json:",omitempty"`
IPv6Address string `json:",omitempty"`
LinkLocalIPs []string `json:",omitempty"`
}
// Copy makes a copy of the endpoint ipam config
func (cfg *EndpointIPAMConfig) Copy() *EndpointIPAMConfig {
cfgCopy := *cfg
cfgCopy.LinkLocalIPs = make([]string, 0, len(cfg.LinkLocalIPs))
cfgCopy.LinkLocalIPs = append(cfgCopy.LinkLocalIPs, cfg.LinkLocalIPs...)
return &cfgCopy
}
// NetworkSubnet describes a user-defined subnet for a specific network. It's only used to validate if an
// EndpointIPAMConfig is valid for a specific network.
type NetworkSubnet interface {
// Contains checks whether the NetworkSubnet contains [addr].
Contains(addr net.IP) bool
// IsStatic checks whether the subnet was statically allocated (ie. user-defined).
IsStatic() bool
}
// IsInRange checks whether static IP addresses are valid in a specific network.
func (cfg *EndpointIPAMConfig) IsInRange(v4Subnets []NetworkSubnet, v6Subnets []NetworkSubnet) error {
var errs []error
if err := validateEndpointIPAddress(cfg.IPv4Address, v4Subnets); err != nil {
errs = append(errs, err)
}
if err := validateEndpointIPAddress(cfg.IPv6Address, v6Subnets); err != nil {
errs = append(errs, err)
}
return multierror.Join(errs...)
}
func validateEndpointIPAddress(epAddr string, ipamSubnets []NetworkSubnet) error {
if epAddr == "" {
return nil
}
var staticSubnet bool
parsedAddr := net.ParseIP(epAddr)
for _, subnet := range ipamSubnets {
if subnet.IsStatic() {
staticSubnet = true
if subnet.Contains(parsedAddr) {
return nil
}
}
}
if staticSubnet {
return fmt.Errorf("no configured subnet or ip-range contain the IP address %s", epAddr)
}
return errors.New("user specified IP address is supported only when connecting to networks with user configured subnets")
}
// Validate checks whether cfg is valid.
func (cfg *EndpointIPAMConfig) Validate() error {
if cfg == nil {
return nil
}
var errs []error
if cfg.IPv4Address != "" {
if addr := net.ParseIP(cfg.IPv4Address); addr == nil || addr.To4() == nil || addr.IsUnspecified() {
errs = append(errs, fmt.Errorf("invalid IPv4 address: %s", cfg.IPv4Address))
}
}
if cfg.IPv6Address != "" {
if addr := net.ParseIP(cfg.IPv6Address); addr == nil || addr.To4() != nil || addr.IsUnspecified() {
errs = append(errs, fmt.Errorf("invalid IPv6 address: %s", cfg.IPv6Address))
}
}
for _, addr := range cfg.LinkLocalIPs {
if parsed := net.ParseIP(addr); parsed == nil || parsed.IsUnspecified() {
errs = append(errs, fmt.Errorf("invalid link-local IP address: %s", addr))
}
}
return multierror.Join(errs...)
}

View File

@ -0,0 +1,151 @@
package network
import (
"errors"
"fmt"
"net/netip"
"github.com/docker/docker/internal/multierror"
)
// IPAM represents IP Address Management
type IPAM struct {
Driver string
Options map[string]string // Per network IPAM driver options
Config []IPAMConfig
}
// IPAMConfig represents IPAM configurations
type IPAMConfig struct {
Subnet string `json:",omitempty"`
IPRange string `json:",omitempty"`
Gateway string `json:",omitempty"`
AuxAddress map[string]string `json:"AuxiliaryAddresses,omitempty"`
}
type ipFamily string
const (
ip4 ipFamily = "IPv4"
ip6 ipFamily = "IPv6"
)
// HasIPv6Subnets checks whether there's any IPv6 subnets in the ipam parameter. It ignores any invalid Subnet and nil
// ipam.
func HasIPv6Subnets(ipam *IPAM) bool {
if ipam == nil {
return false
}
for _, cfg := range ipam.Config {
subnet, err := netip.ParsePrefix(cfg.Subnet)
if err != nil {
continue
}
if subnet.Addr().Is6() {
return true
}
}
return false
}
// ValidateIPAM checks whether the network's IPAM passed as argument is valid. It returns a joinError of the list of
// errors found.
func ValidateIPAM(ipam *IPAM) error {
if ipam == nil {
return nil
}
var errs []error
for _, cfg := range ipam.Config {
subnet, err := netip.ParsePrefix(cfg.Subnet)
if err != nil {
errs = append(errs, fmt.Errorf("invalid subnet %s: invalid CIDR block notation", cfg.Subnet))
continue
}
subnetFamily := ip4
if subnet.Addr().Is6() {
subnetFamily = ip6
}
if subnet != subnet.Masked() {
errs = append(errs, fmt.Errorf("invalid subnet %s: it should be %s", subnet, subnet.Masked()))
}
if ipRangeErrs := validateIPRange(cfg.IPRange, subnet, subnetFamily); len(ipRangeErrs) > 0 {
errs = append(errs, ipRangeErrs...)
}
if err := validateAddress(cfg.Gateway, subnet, subnetFamily); err != nil {
errs = append(errs, fmt.Errorf("invalid gateway %s: %w", cfg.Gateway, err))
}
for auxName, aux := range cfg.AuxAddress {
if err := validateAddress(aux, subnet, subnetFamily); err != nil {
errs = append(errs, fmt.Errorf("invalid auxiliary address %s: %w", auxName, err))
}
}
}
if err := multierror.Join(errs...); err != nil {
return fmt.Errorf("invalid network config:\n%w", err)
}
return nil
}
func validateIPRange(ipRange string, subnet netip.Prefix, subnetFamily ipFamily) []error {
if ipRange == "" {
return nil
}
prefix, err := netip.ParsePrefix(ipRange)
if err != nil {
return []error{fmt.Errorf("invalid ip-range %s: invalid CIDR block notation", ipRange)}
}
family := ip4
if prefix.Addr().Is6() {
family = ip6
}
if family != subnetFamily {
return []error{fmt.Errorf("invalid ip-range %s: parent subnet is an %s block", ipRange, subnetFamily)}
}
var errs []error
if prefix.Bits() < subnet.Bits() {
errs = append(errs, fmt.Errorf("invalid ip-range %s: CIDR block is bigger than its parent subnet %s", ipRange, subnet))
}
if prefix != prefix.Masked() {
errs = append(errs, fmt.Errorf("invalid ip-range %s: it should be %s", prefix, prefix.Masked()))
}
if !subnet.Overlaps(prefix) {
errs = append(errs, fmt.Errorf("invalid ip-range %s: parent subnet %s doesn't contain ip-range", ipRange, subnet))
}
return errs
}
func validateAddress(address string, subnet netip.Prefix, subnetFamily ipFamily) error {
if address == "" {
return nil
}
addr, err := netip.ParseAddr(address)
if err != nil {
return errors.New("invalid address")
}
family := ip4
if addr.Is6() {
family = ip6
}
if family != subnetFamily {
return fmt.Errorf("parent subnet is an %s block", subnetFamily)
}
if !subnet.Contains(addr) {
return fmt.Errorf("parent subnet %s doesn't contain this address", subnet)
}
return nil
}

View File

@ -9,61 +9,12 @@ type Address struct {
PrefixLen int
}
// IPAM represents IP Address Management
type IPAM struct {
Driver string
Options map[string]string // Per network IPAM driver options
Config []IPAMConfig
}
// IPAMConfig represents IPAM configurations
type IPAMConfig struct {
Subnet string `json:",omitempty"`
IPRange string `json:",omitempty"`
Gateway string `json:",omitempty"`
AuxAddress map[string]string `json:"AuxiliaryAddresses,omitempty"`
}
// EndpointIPAMConfig represents IPAM configurations for the endpoint
type EndpointIPAMConfig struct {
IPv4Address string `json:",omitempty"`
IPv6Address string `json:",omitempty"`
LinkLocalIPs []string `json:",omitempty"`
}
// Copy makes a copy of the endpoint ipam config
func (cfg *EndpointIPAMConfig) Copy() *EndpointIPAMConfig {
cfgCopy := *cfg
cfgCopy.LinkLocalIPs = make([]string, 0, len(cfg.LinkLocalIPs))
cfgCopy.LinkLocalIPs = append(cfgCopy.LinkLocalIPs, cfg.LinkLocalIPs...)
return &cfgCopy
}
// PeerInfo represents one peer of an overlay network
type PeerInfo struct {
Name string
IP string
}
// EndpointSettings stores the network endpoint details
type EndpointSettings struct {
// Configurations
IPAMConfig *EndpointIPAMConfig
Links []string
Aliases []string
// Operational data
NetworkID string
EndpointID string
Gateway string
IPAddress string
IPPrefixLen int
IPv6Gateway string
GlobalIPv6Address string
GlobalIPv6PrefixLen int
MacAddress string
DriverOpts map[string]string
}
// Task carries the information about one backend task
type Task struct {
Name string
@ -80,25 +31,6 @@ type ServiceInfo struct {
Tasks []Task
}
// Copy makes a deep copy of `EndpointSettings`
func (es *EndpointSettings) Copy() *EndpointSettings {
epCopy := *es
if es.IPAMConfig != nil {
epCopy.IPAMConfig = es.IPAMConfig.Copy()
}
if es.Links != nil {
links := make([]string, 0, len(es.Links))
epCopy.Links = append(links, es.Links...)
}
if es.Aliases != nil {
aliases := make([]string, 0, len(es.Aliases))
epCopy.Aliases = append(aliases, es.Aliases...)
}
return &epCopy
}
// NetworkingConfig represents the container's networking configuration for each of its interfaces
// Carries the networking configs specified in the `docker run` and `docker network connect` commands
type NetworkingConfig struct {

View File

@ -92,7 +92,9 @@ type SearchResult struct {
IsOfficial bool `json:"is_official"`
// Name is the name of the repository
Name string `json:"name"`
// IsAutomated indicates whether the result is automated
// IsAutomated indicates whether the result is automated.
//
// Deprecated: the "is_automated" field is deprecated and will always be "false" in the future.
IsAutomated bool `json:"is_automated"`
// Description is a textual description of the repository
Description string `json:"description"`

View File

@ -32,6 +32,42 @@ type SELinuxContext struct {
Level string
}
// SeccompMode is the type used for the enumeration of possible seccomp modes
// in SeccompOpts
type SeccompMode string
const (
SeccompModeDefault SeccompMode = "default"
SeccompModeUnconfined SeccompMode = "unconfined"
SeccompModeCustom SeccompMode = "custom"
)
// SeccompOpts defines the options for configuring seccomp on a swarm-managed
// container.
type SeccompOpts struct {
// Mode is the SeccompMode used for the container.
Mode SeccompMode `json:",omitempty"`
// Profile is the custom seccomp profile as a json object to be used with
// the container. Mode should be set to SeccompModeCustom when using a
// custom profile in this manner.
Profile []byte `json:",omitempty"`
}
// AppArmorMode is type used for the enumeration of possible AppArmor modes in
// AppArmorOpts
type AppArmorMode string
const (
AppArmorModeDefault AppArmorMode = "default"
AppArmorModeDisabled AppArmorMode = "disabled"
)
// AppArmorOpts defines the options for configuring AppArmor on a swarm-managed
// container. Currently, custom AppArmor profiles are not supported.
type AppArmorOpts struct {
Mode AppArmorMode `json:",omitempty"`
}
// CredentialSpec for managed service account (Windows only)
type CredentialSpec struct {
Config string
@ -41,8 +77,11 @@ type CredentialSpec struct {
// Privileges defines the security options for the container.
type Privileges struct {
CredentialSpec *CredentialSpec
SELinuxContext *SELinuxContext
CredentialSpec *CredentialSpec
SELinuxContext *SELinuxContext
Seccomp *SeccompOpts `json:",omitempty"`
AppArmor *AppArmorOpts `json:",omitempty"`
NoNewPrivileges bool
}
// ContainerSpec represents the spec of a container.

View File

@ -1,3 +1,3 @@
//go:generate protoc -I . --gogofast_out=import_path=github.com/docker/docker/api/types/swarm/runtime:. plugin.proto
//go:generate protoc --gogofaster_out=import_path=github.com/docker/docker/api/types/swarm/runtime:. plugin.proto
package runtime // import "github.com/docker/docker/api/types/swarm/runtime"

View File

@ -1,23 +1,15 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: plugin.proto
/*
Package runtime is a generated protocol buffer package.
It is generated from these files:
plugin.proto
It has these top-level messages:
PluginSpec
PluginPrivilege
*/
package runtime
import proto "github.com/gogo/protobuf/proto"
import fmt "fmt"
import math "math"
import io "io"
import (
fmt "fmt"
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
math_bits "math/bits"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
@ -28,22 +20,50 @@ var _ = math.Inf
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
// PluginSpec defines the base payload which clients can specify for creating
// a service with the plugin runtime.
type PluginSpec struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Remote string `protobuf:"bytes,2,opt,name=remote,proto3" json:"remote,omitempty"`
Privileges []*PluginPrivilege `protobuf:"bytes,3,rep,name=privileges" json:"privileges,omitempty"`
Privileges []*PluginPrivilege `protobuf:"bytes,3,rep,name=privileges,proto3" json:"privileges,omitempty"`
Disabled bool `protobuf:"varint,4,opt,name=disabled,proto3" json:"disabled,omitempty"`
Env []string `protobuf:"bytes,5,rep,name=env" json:"env,omitempty"`
Env []string `protobuf:"bytes,5,rep,name=env,proto3" json:"env,omitempty"`
}
func (m *PluginSpec) Reset() { *m = PluginSpec{} }
func (m *PluginSpec) String() string { return proto.CompactTextString(m) }
func (*PluginSpec) ProtoMessage() {}
func (*PluginSpec) Descriptor() ([]byte, []int) { return fileDescriptorPlugin, []int{0} }
func (m *PluginSpec) Reset() { *m = PluginSpec{} }
func (m *PluginSpec) String() string { return proto.CompactTextString(m) }
func (*PluginSpec) ProtoMessage() {}
func (*PluginSpec) Descriptor() ([]byte, []int) {
return fileDescriptor_22a625af4bc1cc87, []int{0}
}
func (m *PluginSpec) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *PluginSpec) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_PluginSpec.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *PluginSpec) XXX_Merge(src proto.Message) {
xxx_messageInfo_PluginSpec.Merge(m, src)
}
func (m *PluginSpec) XXX_Size() int {
return m.Size()
}
func (m *PluginSpec) XXX_DiscardUnknown() {
xxx_messageInfo_PluginSpec.DiscardUnknown(m)
}
var xxx_messageInfo_PluginSpec proto.InternalMessageInfo
func (m *PluginSpec) GetName() string {
if m != nil {
@ -85,13 +105,41 @@ func (m *PluginSpec) GetEnv() []string {
type PluginPrivilege struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"`
Value []string `protobuf:"bytes,3,rep,name=value" json:"value,omitempty"`
Value []string `protobuf:"bytes,3,rep,name=value,proto3" json:"value,omitempty"`
}
func (m *PluginPrivilege) Reset() { *m = PluginPrivilege{} }
func (m *PluginPrivilege) String() string { return proto.CompactTextString(m) }
func (*PluginPrivilege) ProtoMessage() {}
func (*PluginPrivilege) Descriptor() ([]byte, []int) { return fileDescriptorPlugin, []int{1} }
func (m *PluginPrivilege) Reset() { *m = PluginPrivilege{} }
func (m *PluginPrivilege) String() string { return proto.CompactTextString(m) }
func (*PluginPrivilege) ProtoMessage() {}
func (*PluginPrivilege) Descriptor() ([]byte, []int) {
return fileDescriptor_22a625af4bc1cc87, []int{1}
}
func (m *PluginPrivilege) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *PluginPrivilege) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_PluginPrivilege.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *PluginPrivilege) XXX_Merge(src proto.Message) {
xxx_messageInfo_PluginPrivilege.Merge(m, src)
}
func (m *PluginPrivilege) XXX_Size() int {
return m.Size()
}
func (m *PluginPrivilege) XXX_DiscardUnknown() {
xxx_messageInfo_PluginPrivilege.DiscardUnknown(m)
}
var xxx_messageInfo_PluginPrivilege proto.InternalMessageInfo
func (m *PluginPrivilege) GetName() string {
if m != nil {
@ -118,10 +166,32 @@ func init() {
proto.RegisterType((*PluginSpec)(nil), "PluginSpec")
proto.RegisterType((*PluginPrivilege)(nil), "PluginPrivilege")
}
func init() { proto.RegisterFile("plugin.proto", fileDescriptor_22a625af4bc1cc87) }
var fileDescriptor_22a625af4bc1cc87 = []byte{
// 225 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x29, 0xc8, 0x29, 0x4d,
0xcf, 0xcc, 0xd3, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x57, 0x9a, 0xc1, 0xc8, 0xc5, 0x15, 0x00, 0x16,
0x08, 0x2e, 0x48, 0x4d, 0x16, 0x12, 0xe2, 0x62, 0xc9, 0x4b, 0xcc, 0x4d, 0x95, 0x60, 0x54, 0x60,
0xd4, 0xe0, 0x0c, 0x02, 0xb3, 0x85, 0xc4, 0xb8, 0xd8, 0x8a, 0x52, 0x73, 0xf3, 0x4b, 0x52, 0x25,
0x98, 0xc0, 0xa2, 0x50, 0x9e, 0x90, 0x01, 0x17, 0x57, 0x41, 0x51, 0x66, 0x59, 0x66, 0x4e, 0x6a,
0x7a, 0x6a, 0xb1, 0x04, 0xb3, 0x02, 0xb3, 0x06, 0xb7, 0x91, 0x80, 0x1e, 0xc4, 0xb0, 0x00, 0x98,
0x44, 0x10, 0x92, 0x1a, 0x21, 0x29, 0x2e, 0x8e, 0x94, 0xcc, 0xe2, 0xc4, 0xa4, 0x9c, 0xd4, 0x14,
0x09, 0x16, 0x05, 0x46, 0x0d, 0x8e, 0x20, 0x38, 0x5f, 0x48, 0x80, 0x8b, 0x39, 0x35, 0xaf, 0x4c,
0x82, 0x55, 0x81, 0x59, 0x83, 0x33, 0x08, 0xc4, 0x54, 0x8a, 0xe5, 0xe2, 0x47, 0x33, 0x0c, 0xab,
0xf3, 0x14, 0xb8, 0xb8, 0x53, 0x52, 0x8b, 0x93, 0x8b, 0x32, 0x0b, 0x4a, 0x32, 0xf3, 0xf3, 0xa0,
0x6e, 0x44, 0x16, 0x12, 0x12, 0xe1, 0x62, 0x2d, 0x4b, 0xcc, 0x29, 0x4d, 0x05, 0xbb, 0x91, 0x33,
0x08, 0xc2, 0x71, 0x92, 0x38, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4,
0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x24, 0x36,
0x70, 0xd0, 0x18, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x37, 0xea, 0xe2, 0xca, 0x2a, 0x01, 0x00,
0x00,
}
func (m *PluginSpec) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
@ -129,66 +199,69 @@ func (m *PluginSpec) Marshal() (dAtA []byte, err error) {
}
func (m *PluginSpec) MarshalTo(dAtA []byte) (int, error) {
var i int
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *PluginSpec) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Name) > 0 {
dAtA[i] = 0xa
i++
i = encodeVarintPlugin(dAtA, i, uint64(len(m.Name)))
i += copy(dAtA[i:], m.Name)
}
if len(m.Remote) > 0 {
dAtA[i] = 0x12
i++
i = encodeVarintPlugin(dAtA, i, uint64(len(m.Remote)))
i += copy(dAtA[i:], m.Remote)
}
if len(m.Privileges) > 0 {
for _, msg := range m.Privileges {
dAtA[i] = 0x1a
i++
i = encodeVarintPlugin(dAtA, i, uint64(msg.Size()))
n, err := msg.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n
if len(m.Env) > 0 {
for iNdEx := len(m.Env) - 1; iNdEx >= 0; iNdEx-- {
i -= len(m.Env[iNdEx])
copy(dAtA[i:], m.Env[iNdEx])
i = encodeVarintPlugin(dAtA, i, uint64(len(m.Env[iNdEx])))
i--
dAtA[i] = 0x2a
}
}
if m.Disabled {
dAtA[i] = 0x20
i++
i--
if m.Disabled {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i++
i--
dAtA[i] = 0x20
}
if len(m.Env) > 0 {
for _, s := range m.Env {
dAtA[i] = 0x2a
i++
l = len(s)
for l >= 1<<7 {
dAtA[i] = uint8(uint64(l)&0x7f | 0x80)
l >>= 7
i++
if len(m.Privileges) > 0 {
for iNdEx := len(m.Privileges) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.Privileges[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintPlugin(dAtA, i, uint64(size))
}
dAtA[i] = uint8(l)
i++
i += copy(dAtA[i:], s)
i--
dAtA[i] = 0x1a
}
}
return i, nil
if len(m.Remote) > 0 {
i -= len(m.Remote)
copy(dAtA[i:], m.Remote)
i = encodeVarintPlugin(dAtA, i, uint64(len(m.Remote)))
i--
dAtA[i] = 0x12
}
if len(m.Name) > 0 {
i -= len(m.Name)
copy(dAtA[i:], m.Name)
i = encodeVarintPlugin(dAtA, i, uint64(len(m.Name)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func (m *PluginPrivilege) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
@ -196,50 +269,56 @@ func (m *PluginPrivilege) Marshal() (dAtA []byte, err error) {
}
func (m *PluginPrivilege) MarshalTo(dAtA []byte) (int, error) {
var i int
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *PluginPrivilege) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Name) > 0 {
dAtA[i] = 0xa
i++
i = encodeVarintPlugin(dAtA, i, uint64(len(m.Name)))
i += copy(dAtA[i:], m.Name)
}
if len(m.Description) > 0 {
dAtA[i] = 0x12
i++
i = encodeVarintPlugin(dAtA, i, uint64(len(m.Description)))
i += copy(dAtA[i:], m.Description)
}
if len(m.Value) > 0 {
for _, s := range m.Value {
for iNdEx := len(m.Value) - 1; iNdEx >= 0; iNdEx-- {
i -= len(m.Value[iNdEx])
copy(dAtA[i:], m.Value[iNdEx])
i = encodeVarintPlugin(dAtA, i, uint64(len(m.Value[iNdEx])))
i--
dAtA[i] = 0x1a
i++
l = len(s)
for l >= 1<<7 {
dAtA[i] = uint8(uint64(l)&0x7f | 0x80)
l >>= 7
i++
}
dAtA[i] = uint8(l)
i++
i += copy(dAtA[i:], s)
}
}
return i, nil
if len(m.Description) > 0 {
i -= len(m.Description)
copy(dAtA[i:], m.Description)
i = encodeVarintPlugin(dAtA, i, uint64(len(m.Description)))
i--
dAtA[i] = 0x12
}
if len(m.Name) > 0 {
i -= len(m.Name)
copy(dAtA[i:], m.Name)
i = encodeVarintPlugin(dAtA, i, uint64(len(m.Name)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func encodeVarintPlugin(dAtA []byte, offset int, v uint64) int {
offset -= sovPlugin(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return offset + 1
return base
}
func (m *PluginSpec) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Name)
@ -269,6 +348,9 @@ func (m *PluginSpec) Size() (n int) {
}
func (m *PluginPrivilege) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Name)
@ -289,14 +371,7 @@ func (m *PluginPrivilege) Size() (n int) {
}
func sovPlugin(x uint64) (n int) {
for {
n++
x >>= 7
if x == 0 {
break
}
}
return n
return (math_bits.Len64(x|1) + 6) / 7
}
func sozPlugin(x uint64) (n int) {
return sovPlugin(uint64((x << 1) ^ uint64((int64(x) >> 63))))
@ -316,7 +391,7 @@ func (m *PluginSpec) Unmarshal(dAtA []byte) error {
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
@ -344,7 +419,7 @@ func (m *PluginSpec) Unmarshal(dAtA []byte) error {
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
@ -354,6 +429,9 @@ func (m *PluginSpec) Unmarshal(dAtA []byte) error {
return ErrInvalidLengthPlugin
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthPlugin
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
@ -373,7 +451,7 @@ func (m *PluginSpec) Unmarshal(dAtA []byte) error {
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
@ -383,6 +461,9 @@ func (m *PluginSpec) Unmarshal(dAtA []byte) error {
return ErrInvalidLengthPlugin
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthPlugin
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
@ -402,7 +483,7 @@ func (m *PluginSpec) Unmarshal(dAtA []byte) error {
}
b := dAtA[iNdEx]
iNdEx++
msglen |= (int(b) & 0x7F) << shift
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
@ -411,6 +492,9 @@ func (m *PluginSpec) Unmarshal(dAtA []byte) error {
return ErrInvalidLengthPlugin
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthPlugin
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
@ -433,7 +517,7 @@ func (m *PluginSpec) Unmarshal(dAtA []byte) error {
}
b := dAtA[iNdEx]
iNdEx++
v |= (int(b) & 0x7F) << shift
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
@ -453,7 +537,7 @@ func (m *PluginSpec) Unmarshal(dAtA []byte) error {
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
@ -463,6 +547,9 @@ func (m *PluginSpec) Unmarshal(dAtA []byte) error {
return ErrInvalidLengthPlugin
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthPlugin
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
@ -474,7 +561,7 @@ func (m *PluginSpec) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPlugin
}
if (iNdEx + skippy) > l {
@ -504,7 +591,7 @@ func (m *PluginPrivilege) Unmarshal(dAtA []byte) error {
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
@ -532,7 +619,7 @@ func (m *PluginPrivilege) Unmarshal(dAtA []byte) error {
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
@ -542,6 +629,9 @@ func (m *PluginPrivilege) Unmarshal(dAtA []byte) error {
return ErrInvalidLengthPlugin
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthPlugin
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
@ -561,7 +651,7 @@ func (m *PluginPrivilege) Unmarshal(dAtA []byte) error {
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
@ -571,6 +661,9 @@ func (m *PluginPrivilege) Unmarshal(dAtA []byte) error {
return ErrInvalidLengthPlugin
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthPlugin
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
@ -590,7 +683,7 @@ func (m *PluginPrivilege) Unmarshal(dAtA []byte) error {
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
@ -600,6 +693,9 @@ func (m *PluginPrivilege) Unmarshal(dAtA []byte) error {
return ErrInvalidLengthPlugin
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthPlugin
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
@ -611,7 +707,7 @@ func (m *PluginPrivilege) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthPlugin
}
if (iNdEx + skippy) > l {
@ -629,6 +725,7 @@ func (m *PluginPrivilege) Unmarshal(dAtA []byte) error {
func skipPlugin(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
@ -660,10 +757,8 @@ func skipPlugin(dAtA []byte) (n int, err error) {
break
}
}
return iNdEx, nil
case 1:
iNdEx += 8
return iNdEx, nil
case 2:
var length int
for shift := uint(0); ; shift += 7 {
@ -680,75 +775,34 @@ func skipPlugin(dAtA []byte) (n int, err error) {
break
}
}
iNdEx += length
if length < 0 {
return 0, ErrInvalidLengthPlugin
}
return iNdEx, nil
iNdEx += length
case 3:
for {
var innerWire uint64
var start int = iNdEx
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowPlugin
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
innerWire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
innerWireType := int(innerWire & 0x7)
if innerWireType == 4 {
break
}
next, err := skipPlugin(dAtA[start:])
if err != nil {
return 0, err
}
iNdEx = start + next
}
return iNdEx, nil
depth++
case 4:
return iNdEx, nil
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupPlugin
}
depth--
case 5:
iNdEx += 4
return iNdEx, nil
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthPlugin
}
if depth == 0 {
return iNdEx, nil
}
}
panic("unreachable")
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthPlugin = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowPlugin = fmt.Errorf("proto: integer overflow")
ErrInvalidLengthPlugin = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowPlugin = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupPlugin = fmt.Errorf("proto: unexpected end of group")
)
func init() { proto.RegisterFile("plugin.proto", fileDescriptorPlugin) }
var fileDescriptorPlugin = []byte{
// 256 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0x4d, 0x4b, 0xc3, 0x30,
0x18, 0xc7, 0x89, 0xdd, 0xc6, 0xfa, 0x4c, 0x70, 0x04, 0x91, 0xe2, 0xa1, 0x94, 0x9d, 0x7a, 0x6a,
0x45, 0x2f, 0x82, 0x37, 0x0f, 0x9e, 0x47, 0xbc, 0x09, 0x1e, 0xd2, 0xf6, 0xa1, 0x06, 0x9b, 0x17,
0x92, 0xb4, 0xe2, 0x37, 0xf1, 0x23, 0x79, 0xf4, 0x23, 0x48, 0x3f, 0x89, 0x98, 0x75, 0x32, 0x64,
0xa7, 0xff, 0x4b, 0xc2, 0x9f, 0x1f, 0x0f, 0x9c, 0x9a, 0xae, 0x6f, 0x85, 0x2a, 0x8c, 0xd5, 0x5e,
0x6f, 0x3e, 0x08, 0xc0, 0x36, 0x14, 0x8f, 0x06, 0x6b, 0x4a, 0x61, 0xa6, 0xb8, 0xc4, 0x84, 0x64,
0x24, 0x8f, 0x59, 0xf0, 0xf4, 0x02, 0x16, 0x16, 0xa5, 0xf6, 0x98, 0x9c, 0x84, 0x76, 0x4a, 0xf4,
0x0a, 0xc0, 0x58, 0x31, 0x88, 0x0e, 0x5b, 0x74, 0x49, 0x94, 0x45, 0xf9, 0xea, 0x7a, 0x5d, 0xec,
0xc6, 0xb6, 0xfb, 0x07, 0x76, 0xf0, 0x87, 0x5e, 0xc2, 0xb2, 0x11, 0x8e, 0x57, 0x1d, 0x36, 0xc9,
0x2c, 0x23, 0xf9, 0x92, 0xfd, 0x65, 0xba, 0x86, 0x08, 0xd5, 0x90, 0xcc, 0xb3, 0x28, 0x8f, 0xd9,
0xaf, 0xdd, 0x3c, 0xc3, 0xd9, 0xbf, 0xb1, 0xa3, 0x78, 0x19, 0xac, 0x1a, 0x74, 0xb5, 0x15, 0xc6,
0x0b, 0xad, 0x26, 0xc6, 0xc3, 0x8a, 0x9e, 0xc3, 0x7c, 0xe0, 0x5d, 0x8f, 0x81, 0x31, 0x66, 0xbb,
0x70, 0xff, 0xf0, 0x39, 0xa6, 0xe4, 0x6b, 0x4c, 0xc9, 0xf7, 0x98, 0x92, 0xa7, 0xdb, 0x56, 0xf8,
0x97, 0xbe, 0x2a, 0x6a, 0x2d, 0xcb, 0x46, 0xd7, 0xaf, 0x68, 0xf7, 0xc2, 0x8d, 0x28, 0xfd, 0xbb,
0x41, 0x57, 0xba, 0x37, 0x6e, 0x65, 0x69, 0x7b, 0xe5, 0x85, 0xc4, 0xbb, 0x49, 0xab, 0x45, 0x38,
0xe4, 0xcd, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x99, 0xa8, 0xd9, 0x9b, 0x58, 0x01, 0x00, 0x00,
}

View File

@ -1,7 +1,5 @@
syntax = "proto3";
option go_package = "github.com/docker/docker/api/types/swarm/runtime;runtime";
// PluginSpec defines the base payload which clients can specify for creating
// a service with the plugin runtime.
message PluginSpec {

View File

@ -0,0 +1,20 @@
package swarm
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
// ServiceCreateResponse contains the information returned to a client on the
// creation of a new service.
//
// swagger:model ServiceCreateResponse
type ServiceCreateResponse struct {
// The ID of the created service.
ID string `json:"ID,omitempty"`
// Optional warning message.
//
// FIXME(thaJeztah): this should have "omitempty" in the generated type.
//
Warnings []string `json:"Warnings"`
}

View File

@ -1,4 +1,4 @@
package types
package swarm
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command

View File

@ -0,0 +1,116 @@
package system
import (
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/registry"
"github.com/docker/docker/api/types/swarm"
)
// Info contains response of Engine API:
// GET "/info"
type Info struct {
ID string
Containers int
ContainersRunning int
ContainersPaused int
ContainersStopped int
Images int
Driver string
DriverStatus [][2]string
SystemStatus [][2]string `json:",omitempty"` // SystemStatus is only propagated by the Swarm standalone API
Plugins PluginsInfo
MemoryLimit bool
SwapLimit bool
KernelMemory bool `json:",omitempty"` // Deprecated: kernel 5.4 deprecated kmem.limit_in_bytes
KernelMemoryTCP bool `json:",omitempty"` // KernelMemoryTCP is not supported on cgroups v2.
CPUCfsPeriod bool `json:"CpuCfsPeriod"`
CPUCfsQuota bool `json:"CpuCfsQuota"`
CPUShares bool
CPUSet bool
PidsLimit bool
IPv4Forwarding bool
BridgeNfIptables bool
BridgeNfIP6tables bool `json:"BridgeNfIp6tables"`
Debug bool
NFd int
OomKillDisable bool
NGoroutines int
SystemTime string
LoggingDriver string
CgroupDriver string
CgroupVersion string `json:",omitempty"`
NEventsListener int
KernelVersion string
OperatingSystem string
OSVersion string
OSType string
Architecture string
IndexServerAddress string
RegistryConfig *registry.ServiceConfig
NCPU int
MemTotal int64
GenericResources []swarm.GenericResource
DockerRootDir string
HTTPProxy string `json:"HttpProxy"`
HTTPSProxy string `json:"HttpsProxy"`
NoProxy string
Name string
Labels []string
ExperimentalBuild bool
ServerVersion string
Runtimes map[string]Runtime
DefaultRuntime string
Swarm swarm.Info
// LiveRestoreEnabled determines whether containers should be kept
// running when the daemon is shutdown or upon daemon start if
// running containers are detected
LiveRestoreEnabled bool
Isolation container.Isolation
InitBinary string
ContainerdCommit Commit
RuncCommit Commit
InitCommit Commit
SecurityOptions []string
ProductLicense string `json:",omitempty"`
DefaultAddressPools []NetworkAddressPool `json:",omitempty"`
CDISpecDirs []string
// Legacy API fields for older API versions.
legacyFields
// Warnings contains a slice of warnings that occurred while collecting
// system information. These warnings are intended to be informational
// messages for the user, and are not intended to be parsed / used for
// other purposes, as they do not have a fixed format.
Warnings []string
}
type legacyFields struct {
ExecutionDriver string `json:",omitempty"` // Deprecated: deprecated since API v1.25, but returned for older versions.
}
// PluginsInfo is a temp struct holding Plugins name
// registered with docker daemon. It is used by [Info] struct
type PluginsInfo struct {
// List of Volume plugins registered
Volume []string
// List of Network plugins registered
Network []string
// List of Authorization plugins registered
Authorization []string
// List of Log plugins registered
Log []string
}
// Commit holds the Git-commit (SHA1) that a binary was built from, as reported
// in the version-string of external tools, such as containerd, or runC.
type Commit struct {
ID string // ID is the actual commit ID of external tool.
Expected string // Expected is the commit ID of external tool expected by dockerd as set at build time.
}
// NetworkAddressPool is a temp struct used by [Info] struct.
type NetworkAddressPool struct {
Base string
Size int
}

View File

@ -0,0 +1,14 @@
package system
// Runtime describes an OCI runtime
type Runtime struct {
// "Legacy" runtime configuration for runc-compatible runtimes.
Path string `json:"path,omitempty"`
Args []string `json:"runtimeArgs,omitempty"`
// Shimv2 runtime configuration. Mutually exclusive with the legacy config above.
Type string `json:"runtimeType,omitempty"`
Options map[string]interface{} `json:"options,omitempty"`
}

View File

@ -0,0 +1,48 @@
package system
import (
"errors"
"fmt"
"strings"
)
// SecurityOpt contains the name and options of a security option
type SecurityOpt struct {
Name string
Options []KeyValue
}
// DecodeSecurityOptions decodes a security options string slice to a
// type-safe [SecurityOpt].
func DecodeSecurityOptions(opts []string) ([]SecurityOpt, error) {
so := []SecurityOpt{}
for _, opt := range opts {
// support output from a < 1.13 docker daemon
if !strings.Contains(opt, "=") {
so = append(so, SecurityOpt{Name: opt})
continue
}
secopt := SecurityOpt{}
for _, s := range strings.Split(opt, ",") {
k, v, ok := strings.Cut(s, "=")
if !ok {
return nil, fmt.Errorf("invalid security option %q", s)
}
if k == "" || v == "" {
return nil, errors.New("invalid empty security option")
}
if k == "name" {
secopt.Name = v
continue
}
secopt.Options = append(secopt.Options, KeyValue{Key: k, Value: v})
}
so = append(so, secopt)
}
return so, nil
}
// KeyValue holds a key/value pair.
type KeyValue struct {
Key, Value string
}

View File

@ -1,18 +1,15 @@
package types // import "github.com/docker/docker/api/types"
import (
"errors"
"fmt"
"io"
"os"
"strings"
"time"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/api/types/mount"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/api/types/registry"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/api/types/volume"
"github.com/docker/go-connections/nat"
@ -118,12 +115,7 @@ type ImageInspect struct {
// VirtualSize is the total size of the image including all layers it is
// composed of.
//
// In versions of Docker before v1.10, this field was calculated from
// the image itself and all of its parent images. Docker v1.10 and up
// store images self-contained, and no longer use a parent-chain, making
// this field an equivalent of the Size field.
//
// Deprecated: Unused in API 1.43 and up, but kept for backward compatibility with older API versions.
// Deprecated: this field is omitted in API v1.44, but kept for backward compatibility. Use Size instead.
VirtualSize int64 `json:"VirtualSize,omitempty"`
// GraphDriver holds information about the storage driver used to store the
@ -137,13 +129,7 @@ type ImageInspect struct {
// Metadata of the image in the local cache.
//
// This information is local to the daemon, and not part of the image itself.
Metadata ImageMetadata
}
// ImageMetadata contains engine-local data about the image
type ImageMetadata struct {
// LastTagTime is the date and time at which the image was last tagged.
LastTagTime time.Time `json:",omitempty"`
Metadata image.Metadata
}
// Container contains response of Engine API:
@ -237,148 +223,6 @@ type Version struct {
BuildTime string `json:",omitempty"`
}
// Commit holds the Git-commit (SHA1) that a binary was built from, as reported
// in the version-string of external tools, such as containerd, or runC.
type Commit struct {
ID string // ID is the actual commit ID of external tool.
Expected string // Expected is the commit ID of external tool expected by dockerd as set at build time.
}
// Info contains response of Engine API:
// GET "/info"
type Info struct {
ID string
Containers int
ContainersRunning int
ContainersPaused int
ContainersStopped int
Images int
Driver string
DriverStatus [][2]string
SystemStatus [][2]string `json:",omitempty"` // SystemStatus is only propagated by the Swarm standalone API
Plugins PluginsInfo
MemoryLimit bool
SwapLimit bool
KernelMemory bool `json:",omitempty"` // Deprecated: kernel 5.4 deprecated kmem.limit_in_bytes
KernelMemoryTCP bool `json:",omitempty"` // KernelMemoryTCP is not supported on cgroups v2.
CPUCfsPeriod bool `json:"CpuCfsPeriod"`
CPUCfsQuota bool `json:"CpuCfsQuota"`
CPUShares bool
CPUSet bool
PidsLimit bool
IPv4Forwarding bool
BridgeNfIptables bool
BridgeNfIP6tables bool `json:"BridgeNfIp6tables"`
Debug bool
NFd int
OomKillDisable bool
NGoroutines int
SystemTime string
LoggingDriver string
CgroupDriver string
CgroupVersion string `json:",omitempty"`
NEventsListener int
KernelVersion string
OperatingSystem string
OSVersion string
OSType string
Architecture string
IndexServerAddress string
RegistryConfig *registry.ServiceConfig
NCPU int
MemTotal int64
GenericResources []swarm.GenericResource
DockerRootDir string
HTTPProxy string `json:"HttpProxy"`
HTTPSProxy string `json:"HttpsProxy"`
NoProxy string
Name string
Labels []string
ExperimentalBuild bool
ServerVersion string
Runtimes map[string]Runtime
DefaultRuntime string
Swarm swarm.Info
// LiveRestoreEnabled determines whether containers should be kept
// running when the daemon is shutdown or upon daemon start if
// running containers are detected
LiveRestoreEnabled bool
Isolation container.Isolation
InitBinary string
ContainerdCommit Commit
RuncCommit Commit
InitCommit Commit
SecurityOptions []string
ProductLicense string `json:",omitempty"`
DefaultAddressPools []NetworkAddressPool `json:",omitempty"`
// Warnings contains a slice of warnings that occurred while collecting
// system information. These warnings are intended to be informational
// messages for the user, and are not intended to be parsed / used for
// other purposes, as they do not have a fixed format.
Warnings []string
}
// KeyValue holds a key/value pair
type KeyValue struct {
Key, Value string
}
// NetworkAddressPool is a temp struct used by Info struct
type NetworkAddressPool struct {
Base string
Size int
}
// SecurityOpt contains the name and options of a security option
type SecurityOpt struct {
Name string
Options []KeyValue
}
// DecodeSecurityOptions decodes a security options string slice to a type safe
// SecurityOpt
func DecodeSecurityOptions(opts []string) ([]SecurityOpt, error) {
so := []SecurityOpt{}
for _, opt := range opts {
// support output from a < 1.13 docker daemon
if !strings.Contains(opt, "=") {
so = append(so, SecurityOpt{Name: opt})
continue
}
secopt := SecurityOpt{}
for _, s := range strings.Split(opt, ",") {
k, v, ok := strings.Cut(s, "=")
if !ok {
return nil, fmt.Errorf("invalid security option %q", s)
}
if k == "" || v == "" {
return nil, errors.New("invalid empty security option")
}
if k == "name" {
secopt.Name = v
continue
}
secopt.Options = append(secopt.Options, KeyValue{Key: k, Value: v})
}
so = append(so, secopt)
}
return so, nil
}
// PluginsInfo is a temp struct holding Plugins name
// registered with docker daemon. It is used by Info struct
type PluginsInfo struct {
// List of Volume plugins registered
Volume []string
// List of Network plugins registered
Network []string
// List of Authorization plugins registered
Authorization []string
// List of Log plugins registered
Log []string
}
// ExecStartCheck is a temp struct used by execStart
// Config fields is part of ExecConfig in runconfig package
type ExecStartCheck struct {
@ -594,14 +438,9 @@ type EndpointResource struct {
// NetworkCreate is the expected body of the "create network" http request message
type NetworkCreate struct {
// Check for networks with duplicate names.
// Network is primarily keyed based on a random ID and not on the name.
// Network name is strictly a user-friendly alias to the network
// which is uniquely identified using ID.
// And there is no guaranteed way to check for duplicates.
// Option CheckDuplicate is there to provide a best effort checking of any networks
// which has the same name but it is not guaranteed to catch all name collisions.
CheckDuplicate bool
// Deprecated: CheckDuplicate is deprecated since API v1.44, but it defaults to true when sent by the client
// package to older daemons.
CheckDuplicate bool `json:",omitempty"`
Driver string
Scope string
EnableIPv6 bool
@ -645,33 +484,6 @@ type NetworkInspectOptions struct {
Verbose bool
}
// Checkpoint represents the details of a checkpoint
type Checkpoint struct {
Name string // Name is the name of the checkpoint
}
// Runtime describes an OCI runtime
type Runtime struct {
// "Legacy" runtime configuration for runc-compatible runtimes.
Path string `json:"path,omitempty"`
Args []string `json:"runtimeArgs,omitempty"`
// Shimv2 runtime configuration. Mutually exclusive with the legacy config above.
Type string `json:"runtimeType,omitempty"`
Options map[string]interface{} `json:"options,omitempty"`
// This is exposed here only for internal use
ShimConfig *ShimConfig `json:"-"`
}
// ShimConfig is used by runtime to configure containerd shims
type ShimConfig struct {
Binary string
Opts interface{}
}
// DiskUsageObject represents an object type used for disk usage query filtering.
type DiskUsageObject string
@ -697,7 +509,7 @@ type DiskUsageOptions struct {
// GET "/system/df"
type DiskUsage struct {
LayersSize int64
Images []*ImageSummary
Images []*image.Summary
Containers []*Container
Volumes []*volume.Volume
BuildCache []*BuildCache
@ -721,7 +533,7 @@ type VolumesPruneReport struct {
// ImagesPruneReport contains the response for Engine API:
// POST "/images/prune"
type ImagesPruneReport struct {
ImagesDeleted []ImageDeleteResponseItem
ImagesDeleted []image.DeleteResponse
SpaceReclaimed uint64
}

View File

@ -0,0 +1,138 @@
package types
import (
"github.com/docker/docker/api/types/checkpoint"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/api/types/system"
)
// CheckpointCreateOptions holds parameters to create a checkpoint from a container.
//
// Deprecated: use [checkpoint.CreateOptions].
type CheckpointCreateOptions = checkpoint.CreateOptions
// CheckpointListOptions holds parameters to list checkpoints for a container
//
// Deprecated: use [checkpoint.ListOptions].
type CheckpointListOptions = checkpoint.ListOptions
// CheckpointDeleteOptions holds parameters to delete a checkpoint from a container
//
// Deprecated: use [checkpoint.DeleteOptions].
type CheckpointDeleteOptions = checkpoint.DeleteOptions
// Checkpoint represents the details of a checkpoint when listing endpoints.
//
// Deprecated: use [checkpoint.Summary].
type Checkpoint = checkpoint.Summary
// Info contains response of Engine API:
// GET "/info"
//
// Deprecated: use [system.Info].
type Info = system.Info
// Commit holds the Git-commit (SHA1) that a binary was built from, as reported
// in the version-string of external tools, such as containerd, or runC.
//
// Deprecated: use [system.Commit].
type Commit = system.Commit
// PluginsInfo is a temp struct holding Plugins name
// registered with docker daemon. It is used by [system.Info] struct
//
// Deprecated: use [system.PluginsInfo].
type PluginsInfo = system.PluginsInfo
// NetworkAddressPool is a temp struct used by [system.Info] struct.
//
// Deprecated: use [system.NetworkAddressPool].
type NetworkAddressPool = system.NetworkAddressPool
// Runtime describes an OCI runtime.
//
// Deprecated: use [system.Runtime].
type Runtime = system.Runtime
// SecurityOpt contains the name and options of a security option.
//
// Deprecated: use [system.SecurityOpt].
type SecurityOpt = system.SecurityOpt
// KeyValue holds a key/value pair.
//
// Deprecated: use [system.KeyValue].
type KeyValue = system.KeyValue
// ImageDeleteResponseItem image delete response item.
//
// Deprecated: use [image.DeleteResponse].
type ImageDeleteResponseItem = image.DeleteResponse
// ImageSummary image summary.
//
// Deprecated: use [image.Summary].
type ImageSummary = image.Summary
// ImageMetadata contains engine-local data about the image.
//
// Deprecated: use [image.Metadata].
type ImageMetadata = image.Metadata
// ServiceCreateResponse contains the information returned to a client
// on the creation of a new service.
//
// Deprecated: use [swarm.ServiceCreateResponse].
type ServiceCreateResponse = swarm.ServiceCreateResponse
// ServiceUpdateResponse service update response.
//
// Deprecated: use [swarm.ServiceUpdateResponse].
type ServiceUpdateResponse = swarm.ServiceUpdateResponse
// ContainerStartOptions holds parameters to start containers.
//
// Deprecated: use [container.StartOptions].
type ContainerStartOptions = container.StartOptions
// ResizeOptions holds parameters to resize a TTY.
// It can be used to resize container TTYs and
// exec process TTYs too.
//
// Deprecated: use [container.ResizeOptions].
type ResizeOptions = container.ResizeOptions
// ContainerAttachOptions holds parameters to attach to a container.
//
// Deprecated: use [container.AttachOptions].
type ContainerAttachOptions = container.AttachOptions
// ContainerCommitOptions holds parameters to commit changes into a container.
//
// Deprecated: use [container.CommitOptions].
type ContainerCommitOptions = container.CommitOptions
// ContainerListOptions holds parameters to list containers with.
//
// Deprecated: use [container.ListOptions].
type ContainerListOptions = container.ListOptions
// ContainerLogsOptions holds parameters to filter logs with.
//
// Deprecated: use [container.LogsOptions].
type ContainerLogsOptions = container.LogsOptions
// ContainerRemoveOptions holds parameters to remove containers.
//
// Deprecated: use [container.RemoveOptions].
type ContainerRemoveOptions = container.RemoveOptions
// DecodeSecurityOptions decodes a security options string slice to a type safe
// [system.SecurityOpt].
//
// Deprecated: use [system.DecodeSecurityOptions].
func DecodeSecurityOptions(opts []string) ([]system.SecurityOpt, error) {
return system.DecodeSecurityOptions(opts)
}

View File

@ -16,11 +16,11 @@ func compare(v1, v2 string) int {
otherTab = strings.Split(v2, ".")
)
max := len(currTab)
if len(otherTab) > max {
max = len(otherTab)
maxVer := len(currTab)
if len(otherTab) > maxVer {
maxVer = len(otherTab)
}
for i := 0; i < max; i++ {
for i := 0; i < maxVer; i++ {
var currInt, otherInt int
if len(currTab) > i {

View File

@ -20,6 +20,7 @@ func main() {
if err != nil {
panic(err)
}
defer cli.Close()
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{})
if err != nil {

View File

@ -13,7 +13,7 @@ import (
// BuildCachePrune requests the daemon to delete unused cache data
func (cli *Client) BuildCachePrune(ctx context.Context, opts types.BuildCachePruneOptions) (*types.BuildCachePruneReport, error) {
if err := cli.NewVersionError("1.31", "build prune"); err != nil {
if err := cli.NewVersionError(ctx, "1.31", "build prune"); err != nil {
return nil, err
}

View File

@ -3,11 +3,11 @@ package client // import "github.com/docker/docker/client"
import (
"context"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/checkpoint"
)
// CheckpointCreate creates a checkpoint from the given container with the given name
func (cli *Client) CheckpointCreate(ctx context.Context, container string, options types.CheckpointCreateOptions) error {
func (cli *Client) CheckpointCreate(ctx context.Context, container string, options checkpoint.CreateOptions) error {
resp, err := cli.post(ctx, "/containers/"+container+"/checkpoints", nil, options, nil)
ensureReaderClosed(resp)
return err

View File

@ -4,11 +4,11 @@ import (
"context"
"net/url"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/checkpoint"
)
// CheckpointDelete deletes the checkpoint with the given name from the given container
func (cli *Client) CheckpointDelete(ctx context.Context, containerID string, options types.CheckpointDeleteOptions) error {
func (cli *Client) CheckpointDelete(ctx context.Context, containerID string, options checkpoint.DeleteOptions) error {
query := url.Values{}
if options.CheckpointDir != "" {
query.Set("dir", options.CheckpointDir)

View File

@ -5,12 +5,12 @@ import (
"encoding/json"
"net/url"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/checkpoint"
)
// CheckpointList returns the checkpoints of the given container in the docker host
func (cli *Client) CheckpointList(ctx context.Context, container string, options types.CheckpointListOptions) ([]types.Checkpoint, error) {
var checkpoints []types.Checkpoint
func (cli *Client) CheckpointList(ctx context.Context, container string, options checkpoint.ListOptions) ([]checkpoint.Summary, error) {
var checkpoints []checkpoint.Summary
query := url.Values{}
if options.CheckpointDir != "" {

View File

@ -19,7 +19,7 @@ For example, to list running containers (the equivalent of "docker ps"):
"context"
"fmt"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
)
@ -29,13 +29,13 @@ For example, to list running containers (the equivalent of "docker ps"):
panic(err)
}
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{})
containers, err := cli.ContainerList(context.Background(), container.ListOptions{})
if err != nil {
panic(err)
}
for _, container := range containers {
fmt.Printf("%s %s\n", container.ID[:10], container.Image)
for _, ctr := range containers {
fmt.Printf("%s %s\n", ctr.ID, ctr.Image)
}
}
*/
@ -43,17 +43,21 @@ package client // import "github.com/docker/docker/client"
import (
"context"
"crypto/tls"
"net"
"net/http"
"net/url"
"path"
"strings"
"time"
"github.com/docker/docker/api"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/versions"
"github.com/docker/go-connections/sockets"
"github.com/pkg/errors"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
"go.opentelemetry.io/otel/trace"
)
// DummyHost is a hostname used for local communication.
@ -86,9 +90,6 @@ import (
// [Go stdlib]: https://github.com/golang/go/blob/6244b1946bc2101b01955468f1be502dbadd6807/src/net/http/transport.go#L558-L569
const DummyHost = "api.moby.localhost"
// ErrRedirect is the error returned by checkRedirect when the request is non-GET.
var ErrRedirect = errors.New("unexpected redirect in response")
// Client is the API client that performs all operations
// against a docker server.
type Client struct {
@ -106,7 +107,12 @@ type Client struct {
client *http.Client
// version of the server to talk to.
version string
// custom http headers configured by users.
// userAgent is the User-Agent header to use for HTTP requests. It takes
// precedence over User-Agent headers set in customHTTPHeaders, and other
// header variables. When set to an empty string, the User-Agent header
// is removed, and no header is sent.
userAgent *string
// custom HTTP headers configured by users.
customHTTPHeaders map[string]string
// manualOverride is set to true when the version was set by users.
manualOverride bool
@ -119,22 +125,33 @@ type Client struct {
// negotiated indicates that API version negotiation took place
negotiated bool
tp trace.TracerProvider
// When the client transport is an *http.Transport (default) we need to do some extra things (like closing idle connections).
// Store the original transport as the http.Client transport will be wrapped with tracing libs.
baseTransport *http.Transport
}
// CheckRedirect specifies the policy for dealing with redirect responses:
// If the request is non-GET return ErrRedirect, otherwise use the last response.
// ErrRedirect is the error returned by checkRedirect when the request is non-GET.
var ErrRedirect = errors.New("unexpected redirect in response")
// CheckRedirect specifies the policy for dealing with redirect responses. It
// can be set on [http.Client.CheckRedirect] to prevent HTTP redirects for
// non-GET requests. It returns an [ErrRedirect] for non-GET request, otherwise
// returns a [http.ErrUseLastResponse], which is special-cased by http.Client
// to use the last response.
//
// Go 1.8 changes behavior for HTTP redirects (specifically 301, 307, and 308)
// in the client. The Docker client (and by extension docker API client) can be
// made to send a request like POST /containers//start where what would normally
// be in the name section of the URL is empty. This triggers an HTTP 301 from
// the daemon.
// Go 1.8 changed behavior for HTTP redirects (specifically 301, 307, and 308)
// in the client. The client (and by extension API client) can be made to send
// a request like "POST /containers//start" where what would normally be in the
// name section of the URL is empty. This triggers an HTTP 301 from the daemon.
//
// In go 1.8 this 301 will be converted to a GET request, and ends up getting
// In go 1.8 this 301 is converted to a GET request, and ends up getting
// a 404 from the daemon. This behavior change manifests in the client in that
// before, the 301 was not followed and the client did not generate an error,
// but now results in a message like Error response from daemon: page not found.
func CheckRedirect(req *http.Request, via []*http.Request) error {
// but now results in a message like "Error response from daemon: page not found".
func CheckRedirect(_ *http.Request, via []*http.Request) error {
if via[0].Method == http.MethodGet {
return http.ErrUseLastResponse
}
@ -145,11 +162,11 @@ func CheckRedirect(req *http.Request, via []*http.Request) error {
// default API host and version. It also initializes the custom HTTP headers to
// add to each request.
//
// It takes an optional list of Opt functional arguments, which are applied in
// It takes an optional list of [Opt] functional arguments, which are applied in
// the order they're provided, which allows modifying the defaults when creating
// the client. For example, the following initializes a client that configures
// itself with values from environment variables (client.FromEnv), and has
// automatic API version negotiation enabled (client.WithAPIVersionNegotiation()).
// itself with values from environment variables ([FromEnv]), and has automatic
// API version negotiation enabled ([WithAPIVersionNegotiation]).
//
// cli, err := client.NewClientWithOpts(
// client.FromEnv,
@ -179,23 +196,43 @@ func NewClientWithOpts(ops ...Opt) (*Client, error) {
}
}
if c.scheme == "" {
c.scheme = "http"
if tr, ok := c.client.Transport.(*http.Transport); ok {
// Store the base transport before we wrap it in tracing libs below
// This is used, as an example, to close idle connections when the client is closed
c.baseTransport = tr
}
tlsConfig := resolveTLSConfig(c.client.Transport)
if tlsConfig != nil {
// TODO(stevvooe): This isn't really the right way to write clients in Go.
// `NewClient` should probably only take an `*http.Client` and work from there.
// Unfortunately, the model of having a host-ish/url-thingy as the connection
// string has us confusing protocol and transport layers. We continue doing
// this to avoid breaking existing clients but this should be addressed.
if c.scheme == "" {
// TODO(stevvooe): This isn't really the right way to write clients in Go.
// `NewClient` should probably only take an `*http.Client` and work from there.
// Unfortunately, the model of having a host-ish/url-thingy as the connection
// string has us confusing protocol and transport layers. We continue doing
// this to avoid breaking existing clients but this should be addressed.
if c.tlsConfig() != nil {
c.scheme = "https"
} else {
c.scheme = "http"
}
}
c.client.Transport = otelhttp.NewTransport(
c.client.Transport,
otelhttp.WithTracerProvider(c.tp),
otelhttp.WithSpanNameFormatter(func(_ string, req *http.Request) string {
return req.Method + " " + req.URL.Path
}),
)
return c, nil
}
func (cli *Client) tlsConfig() *tls.Config {
if cli.baseTransport == nil {
return nil
}
return cli.baseTransport.TLSClientConfig
}
func defaultHTTPClient(hostURL *url.URL) (*http.Client, error) {
transport := &http.Transport{}
err := sockets.ConfigureTransport(transport, hostURL.Scheme, hostURL.Host)
@ -210,19 +247,28 @@ func defaultHTTPClient(hostURL *url.URL) (*http.Client, error) {
// Close the transport used by the client
func (cli *Client) Close() error {
if t, ok := cli.client.Transport.(*http.Transport); ok {
t.CloseIdleConnections()
if cli.baseTransport != nil {
cli.baseTransport.CloseIdleConnections()
return nil
}
return nil
}
// getAPIPath returns the versioned request path to call the api.
// It appends the query parameters to the path if they are not empty.
func (cli *Client) getAPIPath(ctx context.Context, p string, query url.Values) string {
var apiPath string
// checkVersion manually triggers API version negotiation (if configured).
// This allows for version-dependent code to use the same version as will
// be negotiated when making the actual requests, and for which cases
// we cannot do the negotiation lazily.
func (cli *Client) checkVersion(ctx context.Context) {
if cli.negotiateVersion && !cli.negotiated {
cli.NegotiateAPIVersion(ctx)
}
}
// getAPIPath returns the versioned request path to call the API.
// It appends the query parameters to the path if they are not empty.
func (cli *Client) getAPIPath(ctx context.Context, p string, query url.Values) string {
var apiPath string
cli.checkVersion(ctx)
if cli.version != "" {
v := strings.TrimPrefix(cli.version, "v")
apiPath = path.Join(cli.basePath, "/v"+v, p)
@ -244,8 +290,8 @@ func (cli *Client) ClientVersion() string {
// by the client, it uses the client's maximum version.
//
// If a manual override is in place, either through the "DOCKER_API_VERSION"
// (EnvOverrideAPIVersion) environment variable, or if the client is initialized
// with a fixed version (WithVersion(xx)), no negotiation is performed.
// ([EnvOverrideAPIVersion]) environment variable, or if the client is initialized
// with a fixed version ([WithVersion]), no negotiation is performed.
//
// If the API server's ping response does not contain an API version, or if the
// client did not get a successful ping response, it assumes it is connected with
@ -265,8 +311,8 @@ func (cli *Client) NegotiateAPIVersion(ctx context.Context) {
// version.
//
// If a manual override is in place, either through the "DOCKER_API_VERSION"
// (EnvOverrideAPIVersion) environment variable, or if the client is initialized
// with a fixed version (WithVersion(xx)), no negotiation is performed.
// ([EnvOverrideAPIVersion]) environment variable, or if the client is initialized
// with a fixed version ([WithVersion]), no negotiation is performed.
//
// If the API server's ping response does not contain an API version, we assume
// we are connected with an old daemon without API version negotiation support,
@ -338,17 +384,40 @@ func ParseHostURL(host string) (*url.URL, error) {
}, nil
}
func (cli *Client) dialerFromTransport() func(context.Context, string, string) (net.Conn, error) {
if cli.baseTransport == nil || cli.baseTransport.DialContext == nil {
return nil
}
if cli.baseTransport.TLSClientConfig != nil {
// When using a tls config we don't use the configured dialer but instead a fallback dialer...
// Note: It seems like this should use the normal dialer and wrap the returned net.Conn in a tls.Conn
// I honestly don't know why it doesn't do that, but it doesn't and such a change is entirely unrelated to the change in this commit.
return nil
}
return cli.baseTransport.DialContext
}
// Dialer returns a dialer for a raw stream connection, with an HTTP/1.1 header,
// that can be used for proxying the daemon connection.
// that can be used for proxying the daemon connection. It is used by
// ["docker dial-stdio"].
//
// Used by `docker dial-stdio` (docker/cli#889).
// ["docker dial-stdio"]: https://github.com/docker/cli/pull/1014
func (cli *Client) Dialer() func(context.Context) (net.Conn, error) {
return func(ctx context.Context) (net.Conn, error) {
if transport, ok := cli.client.Transport.(*http.Transport); ok {
if transport.DialContext != nil && transport.TLSClientConfig == nil {
return transport.DialContext(ctx, cli.proto, cli.addr)
}
if dialFn := cli.dialerFromTransport(); dialFn != nil {
return dialFn(ctx, cli.proto, cli.addr)
}
switch cli.proto {
case "unix":
return net.Dial(cli.proto, cli.addr)
case "npipe":
return sockets.DialPipe(cli.addr, 32*time.Second)
default:
if tlsConfig := cli.tlsConfig(); tlsConfig != nil {
return tls.Dial(cli.proto, cli.addr, tlsConfig)
}
return net.Dial(cli.proto, cli.addr)
}
return fallbackDial(cli.proto, cli.addr, resolveTLSConfig(cli.client.Transport))
}
}

View File

@ -1,5 +1,4 @@
//go:build !windows
// +build !windows
package client // import "github.com/docker/docker/client"

View File

@ -11,7 +11,7 @@ import (
// ConfigCreate creates a new config.
func (cli *Client) ConfigCreate(ctx context.Context, config swarm.ConfigSpec) (types.ConfigCreateResponse, error) {
var response types.ConfigCreateResponse
if err := cli.NewVersionError("1.30", "config create"); err != nil {
if err := cli.NewVersionError(ctx, "1.30", "config create"); err != nil {
return response, err
}
resp, err := cli.post(ctx, "/configs/create", nil, config, nil)

View File

@ -14,7 +14,7 @@ func (cli *Client) ConfigInspectWithRaw(ctx context.Context, id string) (swarm.C
if id == "" {
return swarm.Config{}, nil, objectNotFoundError{object: "config", id: id}
}
if err := cli.NewVersionError("1.30", "config inspect"); err != nil {
if err := cli.NewVersionError(ctx, "1.30", "config inspect"); err != nil {
return swarm.Config{}, nil, err
}
resp, err := cli.get(ctx, "/configs/"+id, nil, nil)

View File

@ -12,7 +12,7 @@ import (
// ConfigList returns the list of configs.
func (cli *Client) ConfigList(ctx context.Context, options types.ConfigListOptions) ([]swarm.Config, error) {
if err := cli.NewVersionError("1.30", "config list"); err != nil {
if err := cli.NewVersionError(ctx, "1.30", "config list"); err != nil {
return nil, err
}
query := url.Values{}

View File

@ -4,7 +4,7 @@ import "context"
// ConfigRemove removes a config.
func (cli *Client) ConfigRemove(ctx context.Context, id string) error {
if err := cli.NewVersionError("1.30", "config remove"); err != nil {
if err := cli.NewVersionError(ctx, "1.30", "config remove"); err != nil {
return err
}
resp, err := cli.delete(ctx, "/configs/"+id, nil, nil)

View File

@ -9,7 +9,7 @@ import (
// ConfigUpdate attempts to update a config
func (cli *Client) ConfigUpdate(ctx context.Context, id string, version swarm.Version, config swarm.ConfigSpec) error {
if err := cli.NewVersionError("1.30", "config update"); err != nil {
if err := cli.NewVersionError(ctx, "1.30", "config update"); err != nil {
return err
}
query := url.Values{}

View File

@ -2,9 +2,11 @@ package client // import "github.com/docker/docker/client"
import (
"context"
"net/http"
"net/url"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
)
// ContainerAttach attaches a connection to a container in the server.
@ -31,7 +33,7 @@ import (
//
// You can use github.com/docker/docker/pkg/stdcopy.StdCopy to demultiplex this
// stream.
func (cli *Client) ContainerAttach(ctx context.Context, container string, options types.ContainerAttachOptions) (types.HijackedResponse, error) {
func (cli *Client) ContainerAttach(ctx context.Context, container string, options container.AttachOptions) (types.HijackedResponse, error) {
query := url.Values{}
if options.Stream {
query.Set("stream", "1")
@ -52,8 +54,7 @@ func (cli *Client) ContainerAttach(ctx context.Context, container string, option
query.Set("logs", "1")
}
headers := map[string][]string{
return cli.postHijacked(ctx, "/containers/"+container+"/attach", query, nil, http.Header{
"Content-Type": {"text/plain"},
}
return cli.postHijacked(ctx, "/containers/"+container+"/attach", query, nil, headers)
})
}

View File

@ -6,12 +6,13 @@ import (
"errors"
"net/url"
"github.com/docker/distribution/reference"
"github.com/distribution/reference"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
)
// ContainerCommit applies changes to a container and creates a new tagged image.
func (cli *Client) ContainerCommit(ctx context.Context, container string, options types.ContainerCommitOptions) (types.IDResponse, error) {
func (cli *Client) ContainerCommit(ctx context.Context, container string, options container.CommitOptions) (types.IDResponse, error) {
var repository, tag string
if options.Reference != "" {
ref, err := reference.ParseNormalizedNamed(options.Reference)

View File

@ -23,10 +23,23 @@ type configWrapper struct {
func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *ocispec.Platform, containerName string) (container.CreateResponse, error) {
var response container.CreateResponse
if err := cli.NewVersionError("1.25", "stop timeout"); config != nil && config.StopTimeout != nil && err != nil {
// Make sure we negotiated (if the client is configured to do so),
// as code below contains API-version specific handling of options.
//
// Normally, version-negotiation (if enabled) would not happen until
// the API request is made.
cli.checkVersion(ctx)
if err := cli.NewVersionError(ctx, "1.25", "stop timeout"); config != nil && config.StopTimeout != nil && err != nil {
return response, err
}
if err := cli.NewVersionError("1.41", "specify container image platform"); platform != nil && err != nil {
if err := cli.NewVersionError(ctx, "1.41", "specify container image platform"); platform != nil && err != nil {
return response, err
}
if err := cli.NewVersionError(ctx, "1.44", "specify health-check start interval"); config != nil && config.Healthcheck != nil && config.Healthcheck.StartInterval != 0 && err != nil {
return response, err
}
if err := cli.NewVersionError(ctx, "1.44", "specify mac-address per network"); hasEndpointSpecificMacAddress(networkingConfig) && err != nil {
return response, err
}
@ -45,6 +58,11 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config
}
}
// Since API 1.44, the container-wide MacAddress is deprecated and will trigger a WARNING if it's specified.
if versions.GreaterThanOrEqualTo(cli.ClientVersion(), "1.44") {
config.MacAddress = "" //nolint:staticcheck // ignore SA1019: field is deprecated, but still used on API < v1.44.
}
query := url.Values{}
if p := formatPlatform(platform); p != "" {
query.Set("platform", p)
@ -81,3 +99,16 @@ func formatPlatform(platform *ocispec.Platform) string {
}
return path.Join(platform.OS, platform.Architecture, platform.Variant)
}
// hasEndpointSpecificMacAddress checks whether one of the endpoint in networkingConfig has a MacAddress defined.
func hasEndpointSpecificMacAddress(networkingConfig *network.NetworkingConfig) bool {
if networkingConfig == nil {
return false
}
for _, endpoint := range networkingConfig.EndpointsConfig {
if endpoint.MacAddress != "" {
return true
}
}
return false
}

View File

@ -3,6 +3,7 @@ package client // import "github.com/docker/docker/client"
import (
"context"
"encoding/json"
"net/http"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/versions"
@ -12,7 +13,14 @@ import (
func (cli *Client) ContainerExecCreate(ctx context.Context, container string, config types.ExecConfig) (types.IDResponse, error) {
var response types.IDResponse
if err := cli.NewVersionError("1.25", "env"); len(config.Env) != 0 && err != nil {
// Make sure we negotiated (if the client is configured to do so),
// as code below contains API-version specific handling of options.
//
// Normally, version-negotiation (if enabled) would not happen until
// the API request is made.
cli.checkVersion(ctx)
if err := cli.NewVersionError(ctx, "1.25", "env"); len(config.Env) != 0 && err != nil {
return response, err
}
if versions.LessThan(cli.ClientVersion(), "1.42") {
@ -46,10 +54,9 @@ func (cli *Client) ContainerExecAttach(ctx context.Context, execID string, confi
if versions.LessThan(cli.ClientVersion(), "1.42") {
config.ConsoleSize = nil
}
headers := map[string][]string{
return cli.postHijacked(ctx, "/exec/"+execID+"/start", nil, config, http.Header{
"Content-Type": {"application/json"},
}
return cli.postHijacked(ctx, "/exec/"+execID+"/start", nil, config, headers)
})
}
// ContainerExecInspect returns information about a specific exec process on the docker host.

View File

@ -7,11 +7,12 @@ import (
"strconv"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters"
)
// ContainerList returns the list of containers in the docker host.
func (cli *Client) ContainerList(ctx context.Context, options types.ContainerListOptions) ([]types.Container, error) {
func (cli *Client) ContainerList(ctx context.Context, options container.ListOptions) ([]types.Container, error) {
query := url.Values{}
if options.All {
@ -37,7 +38,6 @@ func (cli *Client) ContainerList(ctx context.Context, options types.ContainerLis
if options.Filters.Len() > 0 {
//nolint:staticcheck // ignore SA1019 for old code
filterJSON, err := filters.ToParamWithVersion(cli.version, options.Filters)
if err != nil {
return nil, err
}

View File

@ -6,7 +6,7 @@ import (
"net/url"
"time"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
timetypes "github.com/docker/docker/api/types/time"
"github.com/pkg/errors"
)
@ -33,7 +33,7 @@ import (
//
// You can use github.com/docker/docker/pkg/stdcopy.StdCopy to demultiplex this
// stream.
func (cli *Client) ContainerLogs(ctx context.Context, container string, options types.ContainerLogsOptions) (io.ReadCloser, error) {
func (cli *Client) ContainerLogs(ctx context.Context, container string, options container.LogsOptions) (io.ReadCloser, error) {
query := url.Values{}
if options.ShowStdout {
query.Set("stdout", "1")

View File

@ -13,7 +13,7 @@ import (
func (cli *Client) ContainersPrune(ctx context.Context, pruneFilters filters.Args) (types.ContainersPruneReport, error) {
var report types.ContainersPruneReport
if err := cli.NewVersionError("1.25", "container prune"); err != nil {
if err := cli.NewVersionError(ctx, "1.25", "container prune"); err != nil {
return report, err
}

View File

@ -4,11 +4,11 @@ import (
"context"
"net/url"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
)
// ContainerRemove kills and removes a container from the docker host.
func (cli *Client) ContainerRemove(ctx context.Context, containerID string, options types.ContainerRemoveOptions) error {
func (cli *Client) ContainerRemove(ctx context.Context, containerID string, options container.RemoveOptions) error {
query := url.Values{}
if options.RemoveVolumes {
query.Set("v", "1")

View File

@ -5,16 +5,16 @@ import (
"net/url"
"strconv"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
)
// ContainerResize changes the size of the tty for a container.
func (cli *Client) ContainerResize(ctx context.Context, containerID string, options types.ResizeOptions) error {
func (cli *Client) ContainerResize(ctx context.Context, containerID string, options container.ResizeOptions) error {
return cli.resize(ctx, "/containers/"+containerID, options.Height, options.Width)
}
// ContainerExecResize changes the size of the tty for an exec process running inside a container.
func (cli *Client) ContainerExecResize(ctx context.Context, execID string, options types.ResizeOptions) error {
func (cli *Client) ContainerExecResize(ctx context.Context, execID string, options container.ResizeOptions) error {
return cli.resize(ctx, "/exec/"+execID, options.Height, options.Width)
}

View File

@ -17,8 +17,16 @@ func (cli *Client) ContainerRestart(ctx context.Context, containerID string, opt
if options.Timeout != nil {
query.Set("t", strconv.Itoa(*options.Timeout))
}
if options.Signal != "" && versions.GreaterThanOrEqualTo(cli.version, "1.42") {
query.Set("signal", options.Signal)
if options.Signal != "" {
// Make sure we negotiated (if the client is configured to do so),
// as code below contains API-version specific handling of options.
//
// Normally, version-negotiation (if enabled) would not happen until
// the API request is made.
cli.checkVersion(ctx)
if versions.GreaterThanOrEqualTo(cli.version, "1.42") {
query.Set("signal", options.Signal)
}
}
resp, err := cli.post(ctx, "/containers/"+containerID+"/restart", query, nil, nil)
ensureReaderClosed(resp)

View File

@ -4,11 +4,11 @@ import (
"context"
"net/url"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
)
// ContainerStart sends a request to the docker daemon to start a container.
func (cli *Client) ContainerStart(ctx context.Context, containerID string, options types.ContainerStartOptions) error {
func (cli *Client) ContainerStart(ctx context.Context, containerID string, options container.StartOptions) error {
query := url.Values{}
if len(options.CheckpointID) != 0 {
query.Set("checkpoint", options.CheckpointID)

View File

@ -21,8 +21,10 @@ func (cli *Client) ContainerStats(ctx context.Context, containerID string, strea
return types.ContainerStats{}, err
}
osType := getDockerOS(resp.header.Get("Server"))
return types.ContainerStats{Body: resp.body, OSType: osType}, err
return types.ContainerStats{
Body: resp.body,
OSType: getDockerOS(resp.header.Get("Server")),
}, nil
}
// ContainerStatsOneShot gets a single stat entry from a container.
@ -37,6 +39,8 @@ func (cli *Client) ContainerStatsOneShot(ctx context.Context, containerID string
return types.ContainerStats{}, err
}
osType := getDockerOS(resp.header.Get("Server"))
return types.ContainerStats{Body: resp.body, OSType: osType}, err
return types.ContainerStats{
Body: resp.body,
OSType: getDockerOS(resp.header.Get("Server")),
}, nil
}

View File

@ -21,8 +21,16 @@ func (cli *Client) ContainerStop(ctx context.Context, containerID string, option
if options.Timeout != nil {
query.Set("t", strconv.Itoa(*options.Timeout))
}
if options.Signal != "" && versions.GreaterThanOrEqualTo(cli.version, "1.42") {
query.Set("signal", options.Signal)
if options.Signal != "" {
// Make sure we negotiated (if the client is configured to do so),
// as code below contains API-version specific handling of options.
//
// Normally, version-negotiation (if enabled) would not happen until
// the API request is made.
cli.checkVersion(ctx)
if versions.GreaterThanOrEqualTo(cli.version, "1.42") {
query.Set("signal", options.Signal)
}
}
resp, err := cli.post(ctx, "/containers/"+containerID+"/stop", query, nil, nil)
ensureReaderClosed(resp)

Some files were not shown because too many files have changed in this diff Show More