go.mod: github.com/docker/docker, docker/cli v24.0.7

Update to v24.0, and remove uses of deprecated types.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2024-07-15 10:16:27 +02:00
parent 966ad05338
commit 6f85b653d4
No known key found for this signature in database
GPG key ID: 76698F39D527CE8C
74 changed files with 772 additions and 694 deletions

View file

@ -19,7 +19,7 @@ RUN CGO_ENABLED=0 GOOS=linux GOARCH=${GOARCH} GOARM=${GOARM} \
FROM ${BASE_IMAGE_BUILDER}:${GO_VERSION}-alpine${ALPINE_VERSION} AS docker-builder FROM ${BASE_IMAGE_BUILDER}:${GO_VERSION}-alpine${ALPINE_VERSION} AS docker-builder
ARG GOARCH=amd64 ARG GOARCH=amd64
ARG GOARM ARG GOARM
ARG DOCKER_VERSION=v23.0.10 ARG DOCKER_VERSION=v24.0.7
RUN apk add -U -q --progress --no-cache git bash coreutils gcc musl-dev RUN apk add -U -q --progress --no-cache git bash coreutils gcc musl-dev
WORKDIR /go/src/github.com/docker/cli WORKDIR /go/src/github.com/docker/cli
RUN git clone --branch ${DOCKER_VERSION} --single-branch --depth 1 https://github.com/docker/cli.git . > /dev/null 2>&1 RUN git clone --branch ${DOCKER_VERSION} --single-branch --depth 1 https://github.com/docker/cli.git . > /dev/null 2>&1

6
go.mod
View file

@ -6,8 +6,8 @@ require (
github.com/OpenPeeDeeP/xdg v0.2.1-0.20190312153938-4ba9e1eb294c github.com/OpenPeeDeeP/xdg v0.2.1-0.20190312153938-4ba9e1eb294c
github.com/boz/go-throttle v0.0.0-20160922054636-fdc4eab740c1 github.com/boz/go-throttle v0.0.0-20160922054636-fdc4eab740c1
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21
github.com/docker/cli v23.0.10+incompatible github.com/docker/cli v24.0.7+incompatible
github.com/docker/docker v23.0.10+incompatible github.com/docker/docker v24.0.7+incompatible
github.com/fatih/color v1.10.0 github.com/fatih/color v1.10.0
github.com/go-errors/errors v1.5.1 github.com/go-errors/errors v1.5.1
github.com/gookit/color v1.5.0 github.com/gookit/color v1.5.0
@ -50,7 +50,7 @@ require (
github.com/onsi/ginkgo v1.8.0 // indirect github.com/onsi/ginkgo v1.8.0 // indirect
github.com/onsi/gomega v1.5.0 // indirect github.com/onsi/gomega v1.5.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b // indirect github.com/opencontainers/image-spec v1.1.0 // indirect
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/rivo/uniseg v0.4.7 // indirect github.com/rivo/uniseg v0.4.7 // indirect

12
go.sum
View file

@ -10,12 +10,12 @@ github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21/go.mod
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/docker/cli v23.0.10+incompatible h1:0XA+Tl8mMBj3/qDySQz5UbQAfrK2EbXok82L3xJWYLU= github.com/docker/cli v24.0.7+incompatible h1:wa/nIwYFW7BVTGa7SWPVyyXU9lgORqUb1xfI36MSkFg=
github.com/docker/cli v23.0.10+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v24.0.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= 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/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v23.0.10+incompatible h1:VAVIseM4r70Sun8zg+CNJ4anVnSJcCXea47V/cjmeeY= github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM=
github.com/docker/docker v23.0.10+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v24.0.7+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 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8=
github.com/docker/docker-credential-helpers v0.8.0/go.mod h1:UGFXcuoQ5TxPiB54nHOZ32AWRqQdECoh/Mg0AlEYb40= github.com/docker/docker-credential-helpers v0.8.0/go.mod h1:UGFXcuoQ5TxPiB54nHOZ32AWRqQdECoh/Mg0AlEYb40=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
@ -90,8 +90,8 @@ github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b h1:YWuSjZCQAPM8UUBLkYUk1e+rZcvWHJmFb6i6rM44Xs8= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ=
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=

View file

@ -21,7 +21,7 @@ type Volume struct {
// RefreshVolumes gets the volumes and stores them // RefreshVolumes gets the volumes and stores them
func (c *DockerCommand) RefreshVolumes() ([]*Volume, error) { func (c *DockerCommand) RefreshVolumes() ([]*Volume, error) {
result, err := c.Client.VolumeList(context.Background(), filters.Args{}) result, err := c.Client.VolumeList(context.Background(), volume.ListOptions{})
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -37,7 +37,6 @@ type ConfigFile struct {
PruneFilters []string `json:"pruneFilters,omitempty"` PruneFilters []string `json:"pruneFilters,omitempty"`
Proxies map[string]ProxyConfig `json:"proxies,omitempty"` Proxies map[string]ProxyConfig `json:"proxies,omitempty"`
Experimental string `json:"experimental,omitempty"` Experimental string `json:"experimental,omitempty"`
StackOrchestrator string `json:"stackOrchestrator,omitempty"` // Deprecated: swarm is now the default orchestrator, and this option is ignored.
CurrentContext string `json:"currentContext,omitempty"` CurrentContext string `json:"currentContext,omitempty"`
CLIPluginsExtraDirs []string `json:"cliPluginsExtraDirs,omitempty"` CLIPluginsExtraDirs []string `json:"cliPluginsExtraDirs,omitempty"`
Plugins map[string]map[string]string `json:"plugins,omitempty"` Plugins map[string]map[string]string `json:"plugins,omitempty"`

View file

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

View file

@ -23,6 +23,7 @@ import (
"runtime" "runtime"
"strings" "strings"
"sync" "sync"
"sync/atomic"
"syscall" "syscall"
"time" "time"
@ -64,81 +65,68 @@ func New(_ context.Context, cmd string, args ...string) (net.Conn, error) {
// commandConn implements net.Conn // commandConn implements net.Conn
type commandConn struct { type commandConn struct {
cmd *exec.Cmd cmdMutex sync.Mutex // for cmd, cmdWaitErr
cmdExited bool cmd *exec.Cmd
cmdWaitErr error cmdWaitErr error
cmdMutex sync.Mutex cmdExited atomic.Bool
stdin io.WriteCloser stdin io.WriteCloser
stdout io.ReadCloser stdout io.ReadCloser
stderrMu sync.Mutex stderrMu sync.Mutex // for stderr
stderr bytes.Buffer stderr bytes.Buffer
stdioClosedMu sync.Mutex // for stdinClosed and stdoutClosed stdinClosed atomic.Bool
stdinClosed bool stdoutClosed atomic.Bool
stdoutClosed bool closing atomic.Bool
localAddr net.Addr localAddr net.Addr
remoteAddr net.Addr remoteAddr net.Addr
} }
// killIfStdioClosed kills the cmd if both stdin and stdout are closed. // kill terminates the process. On Windows it kills the process directly,
func (c *commandConn) killIfStdioClosed() error { // whereas on other platforms, a SIGTERM is sent, before forcefully terminating
c.stdioClosedMu.Lock() // the process after 3 seconds.
stdioClosed := c.stdoutClosed && c.stdinClosed func (c *commandConn) kill() {
c.stdioClosedMu.Unlock() if c.cmdExited.Load() {
if !stdioClosed { return
return nil
} }
return c.kill() c.cmdMutex.Lock()
}
// killAndWait tries sending SIGTERM to the process before sending SIGKILL.
func killAndWait(cmd *exec.Cmd) error {
var werr error var werr error
if runtime.GOOS != "windows" { if runtime.GOOS != "windows" {
werrCh := make(chan error) werrCh := make(chan error)
go func() { werrCh <- cmd.Wait() }() go func() { werrCh <- c.cmd.Wait() }()
cmd.Process.Signal(syscall.SIGTERM) _ = c.cmd.Process.Signal(syscall.SIGTERM)
select { select {
case werr = <-werrCh: case werr = <-werrCh:
case <-time.After(3 * time.Second): case <-time.After(3 * time.Second):
cmd.Process.Kill() _ = c.cmd.Process.Kill()
werr = <-werrCh werr = <-werrCh
} }
} else { } else {
cmd.Process.Kill() _ = c.cmd.Process.Kill()
werr = cmd.Wait() werr = c.cmd.Wait()
}
return werr
}
// kill returns nil if the command terminated, regardless to the exit status.
func (c *commandConn) kill() error {
var werr error
c.cmdMutex.Lock()
if c.cmdExited {
werr = c.cmdWaitErr
} else {
werr = killAndWait(c.cmd)
c.cmdWaitErr = werr
c.cmdExited = true
} }
c.cmdWaitErr = werr
c.cmdMutex.Unlock() c.cmdMutex.Unlock()
if werr == nil { c.cmdExited.Store(true)
return nil
}
wExitErr, ok := werr.(*exec.ExitError)
if ok {
if wExitErr.ProcessState.Exited() {
return nil
}
}
return errors.Wrapf(werr, "commandconn: failed to wait")
} }
func (c *commandConn) onEOF(eof error) error { // handleEOF handles io.EOF errors while reading or writing from the underlying
// when we got EOF, the command is going to be terminated // command pipes.
var werr error //
// When we've received an EOF we expect that the command will
// be terminated soon. As such, we call Wait() on the command
// and return EOF or the error depending on whether the command
// exited with an error.
//
// If Wait() does not return within 10s, an error is returned
func (c *commandConn) handleEOF(err error) error {
if err != io.EOF {
return err
}
c.cmdMutex.Lock() c.cmdMutex.Lock()
if c.cmdExited { defer c.cmdMutex.Unlock()
var werr error
if c.cmdExited.Load() {
werr = c.cmdWaitErr werr = c.cmdWaitErr
} else { } else {
werrCh := make(chan error) werrCh := make(chan error)
@ -146,18 +134,17 @@ func (c *commandConn) onEOF(eof error) error {
select { select {
case werr = <-werrCh: case werr = <-werrCh:
c.cmdWaitErr = werr c.cmdWaitErr = werr
c.cmdExited = true c.cmdExited.Store(true)
case <-time.After(10 * time.Second): case <-time.After(10 * time.Second):
c.cmdMutex.Unlock()
c.stderrMu.Lock() c.stderrMu.Lock()
stderr := c.stderr.String() stderr := c.stderr.String()
c.stderrMu.Unlock() c.stderrMu.Unlock()
return errors.Errorf("command %v did not exit after %v: stderr=%q", c.cmd.Args, eof, stderr) return errors.Errorf("command %v did not exit after %v: stderr=%q", c.cmd.Args, err, stderr)
} }
} }
c.cmdMutex.Unlock()
if werr == nil { if werr == nil {
return eof return err
} }
c.stderrMu.Lock() c.stderrMu.Lock()
stderr := c.stderr.String() stderr := c.stderr.String()
@ -166,71 +153,86 @@ func (c *commandConn) onEOF(eof error) error {
} }
func ignorableCloseError(err error) bool { func ignorableCloseError(err error) bool {
errS := err.Error() return strings.Contains(err.Error(), os.ErrClosed.Error())
ss := []string{
os.ErrClosed.Error(),
}
for _, s := range ss {
if strings.Contains(errS, s) {
return true
}
}
return false
}
func (c *commandConn) CloseRead() error {
// NOTE: maybe already closed here
if err := c.stdout.Close(); err != nil && !ignorableCloseError(err) {
logrus.Warnf("commandConn.CloseRead: %v", err)
}
c.stdioClosedMu.Lock()
c.stdoutClosed = true
c.stdioClosedMu.Unlock()
if err := c.killIfStdioClosed(); err != nil {
logrus.Warnf("commandConn.CloseRead: %v", err)
}
return nil
} }
func (c *commandConn) Read(p []byte) (int, error) { func (c *commandConn) Read(p []byte) (int, error) {
n, err := c.stdout.Read(p) n, err := c.stdout.Read(p)
if err == io.EOF { // check after the call to Read, since
err = c.onEOF(err) // it is blocking, and while waiting on it
// Close might get called
if c.closing.Load() {
// If we're currently closing the connection
// we don't want to call onEOF
return n, err
} }
return n, err
}
func (c *commandConn) CloseWrite() error { return n, c.handleEOF(err)
// NOTE: maybe already closed here
if err := c.stdin.Close(); err != nil && !ignorableCloseError(err) {
logrus.Warnf("commandConn.CloseWrite: %v", err)
}
c.stdioClosedMu.Lock()
c.stdinClosed = true
c.stdioClosedMu.Unlock()
if err := c.killIfStdioClosed(); err != nil {
logrus.Warnf("commandConn.CloseWrite: %v", err)
}
return nil
} }
func (c *commandConn) Write(p []byte) (int, error) { func (c *commandConn) Write(p []byte) (int, error) {
n, err := c.stdin.Write(p) n, err := c.stdin.Write(p)
if err == io.EOF { // check after the call to Write, since
err = c.onEOF(err) // it is blocking, and while waiting on it
// Close might get called
if c.closing.Load() {
// If we're currently closing the connection
// we don't want to call onEOF
return n, err
} }
return n, err
return n, c.handleEOF(err)
} }
// CloseRead allows commandConn to implement halfCloser
func (c *commandConn) CloseRead() error {
// NOTE: maybe already closed here
if err := c.stdout.Close(); err != nil && !ignorableCloseError(err) {
return err
}
c.stdoutClosed.Store(true)
if c.stdinClosed.Load() {
c.kill()
}
return nil
}
// CloseWrite allows commandConn to implement halfCloser
func (c *commandConn) CloseWrite() error {
// NOTE: maybe already closed here
if err := c.stdin.Close(); err != nil && !ignorableCloseError(err) {
return err
}
c.stdinClosed.Store(true)
if c.stdoutClosed.Load() {
c.kill()
}
return nil
}
// Close is the net.Conn func that gets called
// by the transport when a dial is cancelled
// due to it's context timing out. Any blocked
// Read or Write calls will be unblocked and
// return errors. It will block until the underlying
// command has terminated.
func (c *commandConn) Close() error { func (c *commandConn) Close() error {
var err error c.closing.Store(true)
if err = c.CloseRead(); err != nil { defer c.closing.Store(false)
if err := c.CloseRead(); err != nil {
logrus.Warnf("commandConn.Close: CloseRead: %v", err) logrus.Warnf("commandConn.Close: CloseRead: %v", err)
return err
} }
if err = c.CloseWrite(); err != nil { if err := c.CloseWrite(); err != nil {
logrus.Warnf("commandConn.Close: CloseWrite: %v", err) logrus.Warnf("commandConn.Close: CloseWrite: %v", err)
return err
} }
return err
return nil
} }
func (c *commandConn) LocalAddr() net.Addr { func (c *commandConn) LocalAddr() net.Addr {

View file

@ -5,6 +5,7 @@ import (
"context" "context"
"net" "net"
"net/url" "net/url"
"strings"
"github.com/docker/cli/cli/connhelper/commandconn" "github.com/docker/cli/cli/connhelper/commandconn"
"github.com/docker/cli/cli/connhelper/ssh" "github.com/docker/cli/cli/connhelper/ssh"
@ -47,7 +48,13 @@ func getConnectionHelper(daemonURL string, sshFlags []string) (*ConnectionHelper
} }
return &ConnectionHelper{ return &ConnectionHelper{
Dialer: func(ctx context.Context, network, addr string) (net.Conn, error) { Dialer: func(ctx context.Context, network, addr string) (net.Conn, error) {
return commandconn.New(ctx, "ssh", append(sshFlags, sp.Args("docker", "system", "dial-stdio")...)...) args := []string{"docker"}
if sp.Path != "" {
args = append(args, "--host", "unix://"+sp.Path)
}
sshFlags = addSSHTimeout(sshFlags)
args = append(args, "system", "dial-stdio")
return commandconn.New(ctx, "ssh", append(sshFlags, sp.Args(args...)...)...)
}, },
Host: "http://docker.example.com", Host: "http://docker.example.com",
}, nil }, nil
@ -66,3 +73,10 @@ func GetCommandConnectionHelper(cmd string, flags ...string) (*ConnectionHelper,
Host: "http://docker.example.com", Host: "http://docker.example.com",
}, nil }, nil
} }
func addSSHTimeout(sshFlags []string) []string {
if !strings.Contains(strings.Join(sshFlags, ""), "ConnectTimeout") {
sshFlags = append(sshFlags, "-o ConnectTimeout=30")
}
return sshFlags
}

View file

@ -30,9 +30,7 @@ func ParseURL(daemonURL string) (*Spec, error) {
return nil, errors.Errorf("no host specified") return nil, errors.Errorf("no host specified")
} }
sp.Port = u.Port() sp.Port = u.Port()
if u.Path != "" { sp.Path = u.Path
return nil, errors.Errorf("extra path after the host: %q", u.Path)
}
if u.RawQuery != "" { if u.RawQuery != "" {
return nil, errors.Errorf("extra query after the host: %q", u.RawQuery) return nil, errors.Errorf("extra query after the host: %q", u.RawQuery)
} }
@ -47,6 +45,7 @@ type Spec struct {
User string User string
Host string Host string
Port string Port string
Path string
} }
// Args returns args except "ssh" itself combined with optional additional command args // Args returns args except "ssh" itself combined with optional additional command args

View file

@ -25,12 +25,6 @@ type EndpointMeta = context.EndpointMetaBase
type Endpoint struct { type Endpoint struct {
EndpointMeta EndpointMeta
TLSData *context.TLSData TLSData *context.TLSData
// Deprecated: Use of encrypted TLS private keys has been deprecated, and
// will be removed in a future release. Golang has deprecated support for
// legacy PEM encryption (as specified in RFC 1423), as it is insecure by
// design (see https://go-review.googlesource.com/c/go/+/264159).
TLSPassword string
} }
// WithTLSData loads TLS materials for the endpoint // WithTLSData loads TLS materials for the endpoint

View file

@ -494,20 +494,6 @@ func importEndpointTLS(tlsData *ContextTLSData, path string, data []byte) error
return nil return nil
} }
// IsErrContextDoesNotExist checks if the given error is a "context does not exist" condition.
//
// Deprecated: use github.com/docker/docker/errdefs.IsNotFound()
func IsErrContextDoesNotExist(err error) bool {
return errdefs.IsNotFound(err)
}
// IsErrTLSDataDoesNotExist checks if the given error is a "context does not exist" condition
//
// Deprecated: use github.com/docker/docker/errdefs.IsNotFound()
func IsErrTLSDataDoesNotExist(err error) bool {
return errdefs.IsNotFound(err)
}
type contextdir string type contextdir string
func contextdirOf(name string) contextdir { func contextdirOf(name string) contextdir {

View file

@ -29,6 +29,7 @@ Adam Pointer <adam.pointer@skybettingandgaming.com>
Adam Singer <financeCoding@gmail.com> Adam Singer <financeCoding@gmail.com>
Adam Walz <adam@adamwalz.net> Adam Walz <adam@adamwalz.net>
Adam Williams <awilliams@mirantis.com> Adam Williams <awilliams@mirantis.com>
AdamKorcz <adam@adalogics.com>
Addam Hardy <addam.hardy@gmail.com> Addam Hardy <addam.hardy@gmail.com>
Aditi Rajagopal <arajagopal@us.ibm.com> Aditi Rajagopal <arajagopal@us.ibm.com>
Aditya <aditya@netroy.in> Aditya <aditya@netroy.in>
@ -81,6 +82,7 @@ Alex Goodman <wagoodman@gmail.com>
Alex Nordlund <alexander.nordlund@nasdaq.com> Alex Nordlund <alexander.nordlund@nasdaq.com>
Alex Olshansky <i@creagenics.com> Alex Olshansky <i@creagenics.com>
Alex Samorukov <samm@os2.kiev.ua> Alex Samorukov <samm@os2.kiev.ua>
Alex Stockinger <alex@atomicjar.com>
Alex Warhawk <ax.warhawk@gmail.com> Alex Warhawk <ax.warhawk@gmail.com>
Alexander Artemenko <svetlyak.40wt@gmail.com> Alexander Artemenko <svetlyak.40wt@gmail.com>
Alexander Boyd <alex@opengroove.org> Alexander Boyd <alex@opengroove.org>
@ -198,6 +200,7 @@ Anusha Ragunathan <anusha.ragunathan@docker.com>
Anyu Wang <wanganyu@outlook.com> Anyu Wang <wanganyu@outlook.com>
apocas <petermdias@gmail.com> apocas <petermdias@gmail.com>
Arash Deshmeh <adeshmeh@ca.ibm.com> Arash Deshmeh <adeshmeh@ca.ibm.com>
arcosx <arcosx@outlook.com>
ArikaChen <eaglesora@gmail.com> ArikaChen <eaglesora@gmail.com>
Arko Dasgupta <arko@tetrate.io> Arko Dasgupta <arko@tetrate.io>
Arnaud Lefebvre <a.lefebvre@outlook.fr> Arnaud Lefebvre <a.lefebvre@outlook.fr>
@ -241,6 +244,7 @@ Benjamin Atkin <ben@benatkin.com>
Benjamin Baker <Benjamin.baker@utexas.edu> Benjamin Baker <Benjamin.baker@utexas.edu>
Benjamin Boudreau <boudreau.benjamin@gmail.com> Benjamin Boudreau <boudreau.benjamin@gmail.com>
Benjamin Böhmke <benjamin@boehmke.net> Benjamin Böhmke <benjamin@boehmke.net>
Benjamin Wang <wachao@vmware.com>
Benjamin Yolken <yolken@stripe.com> Benjamin Yolken <yolken@stripe.com>
Benny Ng <benny.tpng@gmail.com> Benny Ng <benny.tpng@gmail.com>
Benoit Chesneau <bchesneau@gmail.com> Benoit Chesneau <bchesneau@gmail.com>
@ -634,6 +638,7 @@ Eng Zer Jun <engzerjun@gmail.com>
Enguerran <engcolson@gmail.com> Enguerran <engcolson@gmail.com>
Eohyung Lee <liquidnuker@gmail.com> Eohyung Lee <liquidnuker@gmail.com>
epeterso <epeterson@breakpoint-labs.com> epeterso <epeterson@breakpoint-labs.com>
er0k <er0k@er0k.net>
Eric Barch <barch@tomesoftware.com> Eric Barch <barch@tomesoftware.com>
Eric Curtin <ericcurtin17@gmail.com> Eric Curtin <ericcurtin17@gmail.com>
Eric G. Noriega <enoriega@vizuri.com> Eric G. Noriega <enoriega@vizuri.com>
@ -754,6 +759,7 @@ Félix Baylac-Jacqué <baylac.felix@gmail.com>
Félix Cantournet <felix.cantournet@cloudwatt.com> Félix Cantournet <felix.cantournet@cloudwatt.com>
Gabe Rosenhouse <gabe@missionst.com> Gabe Rosenhouse <gabe@missionst.com>
Gabor Nagy <mail@aigeruth.hu> Gabor Nagy <mail@aigeruth.hu>
Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
Gabriel Goller <gabrielgoller123@gmail.com> Gabriel Goller <gabrielgoller123@gmail.com>
Gabriel L. Somlo <gsomlo@gmail.com> Gabriel L. Somlo <gsomlo@gmail.com>
Gabriel Linder <linder.gabriel@gmail.com> Gabriel Linder <linder.gabriel@gmail.com>
@ -855,6 +861,7 @@ Hongbin Lu <hongbin034@gmail.com>
Hongxu Jia <hongxu.jia@windriver.com> Hongxu Jia <hongxu.jia@windriver.com>
Honza Pokorny <me@honza.ca> Honza Pokorny <me@honza.ca>
Hsing-Hui Hsu <hsinghui@amazon.com> Hsing-Hui Hsu <hsinghui@amazon.com>
Hsing-Yu (David) Chen <davidhsingyuchen@gmail.com>
hsinko <21551195@zju.edu.cn> hsinko <21551195@zju.edu.cn>
Hu Keping <hukeping@huawei.com> Hu Keping <hukeping@huawei.com>
Hu Tao <hutao@cn.fujitsu.com> Hu Tao <hutao@cn.fujitsu.com>
@ -887,6 +894,7 @@ Igor Dolzhikov <bluesriverz@gmail.com>
Igor Karpovich <i.karpovich@currencysolutions.com> Igor Karpovich <i.karpovich@currencysolutions.com>
Iliana Weller <iweller@amazon.com> Iliana Weller <iweller@amazon.com>
Ilkka Laukkanen <ilkka@ilkka.io> Ilkka Laukkanen <ilkka@ilkka.io>
Illia Antypenko <ilya@antipenko.pp.ua>
Illo Abdulrahim <abdulrahim.illo@nokia.com> Illo Abdulrahim <abdulrahim.illo@nokia.com>
Ilya Dmitrichenko <errordeveloper@gmail.com> Ilya Dmitrichenko <errordeveloper@gmail.com>
Ilya Gusev <mail@igusev.ru> Ilya Gusev <mail@igusev.ru>
@ -938,6 +946,7 @@ Jamie Hannaford <jamie@limetree.org>
Jamshid Afshar <jafshar@yahoo.com> Jamshid Afshar <jafshar@yahoo.com>
Jan Breig <git@pygos.space> Jan Breig <git@pygos.space>
Jan Chren <dev.rindeal@gmail.com> Jan Chren <dev.rindeal@gmail.com>
Jan Garcia <github-public@n-garcia.com>
Jan Götte <jaseg@jaseg.net> Jan Götte <jaseg@jaseg.net>
Jan Keromnes <janx@linux.com> Jan Keromnes <janx@linux.com>
Jan Koprowski <jan.koprowski@gmail.com> Jan Koprowski <jan.koprowski@gmail.com>
@ -1206,6 +1215,7 @@ Kimbro Staken <kstaken@kstaken.com>
Kir Kolyshkin <kolyshkin@gmail.com> Kir Kolyshkin <kolyshkin@gmail.com>
Kiran Gangadharan <kiran.daredevil@gmail.com> Kiran Gangadharan <kiran.daredevil@gmail.com>
Kirill SIbirev <l0kix2@gmail.com> Kirill SIbirev <l0kix2@gmail.com>
Kirk Easterson <kirk.easterson@gmail.com>
knappe <tyler.knappe@gmail.com> knappe <tyler.knappe@gmail.com>
Kohei Tsuruta <coheyxyz@gmail.com> Kohei Tsuruta <coheyxyz@gmail.com>
Koichi Shiraishi <k@zchee.io> Koichi Shiraishi <k@zchee.io>
@ -1240,10 +1250,12 @@ Lars Kellogg-Stedman <lars@redhat.com>
Lars R. Damerow <lars@pixar.com> Lars R. Damerow <lars@pixar.com>
Lars-Magnus Skog <ralphtheninja@riseup.net> Lars-Magnus Skog <ralphtheninja@riseup.net>
Laszlo Meszaros <lacienator@gmail.com> Laszlo Meszaros <lacienator@gmail.com>
Laura Brehm <laurabrehm@hey.com>
Laura Frank <ljfrank@gmail.com> Laura Frank <ljfrank@gmail.com>
Laurent Bernaille <laurent.bernaille@datadoghq.com> Laurent Bernaille <laurent.bernaille@datadoghq.com>
Laurent Erignoux <lerignoux@gmail.com> Laurent Erignoux <lerignoux@gmail.com>
Laurie Voss <github@seldo.com> Laurie Voss <github@seldo.com>
Leandro Motta Barros <lmb@stackedboxes.org>
Leandro Siqueira <leandro.siqueira@gmail.com> Leandro Siqueira <leandro.siqueira@gmail.com>
Lee Calcote <leecalcote@gmail.com> Lee Calcote <leecalcote@gmail.com>
Lee Chao <932819864@qq.com> Lee Chao <932819864@qq.com>
@ -1563,6 +1575,7 @@ Nick Neisen <nwneisen@gmail.com>
Nick Parker <nikaios@gmail.com> Nick Parker <nikaios@gmail.com>
Nick Payne <nick@kurai.co.uk> Nick Payne <nick@kurai.co.uk>
Nick Russo <nicholasjamesrusso@gmail.com> Nick Russo <nicholasjamesrusso@gmail.com>
Nick Santos <nick.santos@docker.com>
Nick Stenning <nick.stenning@digital.cabinet-office.gov.uk> Nick Stenning <nick.stenning@digital.cabinet-office.gov.uk>
Nick Stinemates <nick@stinemates.org> Nick Stinemates <nick@stinemates.org>
Nick Wood <nwood@microsoft.com> Nick Wood <nwood@microsoft.com>
@ -1584,6 +1597,7 @@ NikolaMandic <mn080202@gmail.com>
Nikolas Garofil <nikolas.garofil@uantwerpen.be> Nikolas Garofil <nikolas.garofil@uantwerpen.be>
Nikolay Edigaryev <edigaryev@gmail.com> Nikolay Edigaryev <edigaryev@gmail.com>
Nikolay Milovanov <nmil@itransformers.net> Nikolay Milovanov <nmil@itransformers.net>
ningmingxiao <ning.mingxiao@zte.com.cn>
Nirmal Mehta <nirmalkmehta@gmail.com> Nirmal Mehta <nirmalkmehta@gmail.com>
Nishant Totla <nishanttotla@gmail.com> Nishant Totla <nishanttotla@gmail.com>
NIWA Hideyuki <niwa.niwa@nifty.ne.jp> NIWA Hideyuki <niwa.niwa@nifty.ne.jp>
@ -1615,6 +1629,7 @@ Omri Shiv <Omri.Shiv@teradata.com>
Onur Filiz <onur.filiz@microsoft.com> Onur Filiz <onur.filiz@microsoft.com>
Oriol Francès <oriolfa@gmail.com> Oriol Francès <oriolfa@gmail.com>
Oscar Bonilla <6f6231@gmail.com> Oscar Bonilla <6f6231@gmail.com>
oscar.chen <2972789494@qq.com>
Oskar Niburski <oskarniburski@gmail.com> Oskar Niburski <oskarniburski@gmail.com>
Otto Kekäläinen <otto@seravo.fi> Otto Kekäläinen <otto@seravo.fi>
Ouyang Liduo <oyld0210@163.com> Ouyang Liduo <oyld0210@163.com>
@ -1822,6 +1837,7 @@ Rory Hunter <roryhunter2@gmail.com>
Rory McCune <raesene@gmail.com> Rory McCune <raesene@gmail.com>
Ross Boucher <rboucher@gmail.com> Ross Boucher <rboucher@gmail.com>
Rovanion Luckey <rovanion.luckey@gmail.com> Rovanion Luckey <rovanion.luckey@gmail.com>
Roy Reznik <roy@wiz.io>
Royce Remer <royceremer@gmail.com> Royce Remer <royceremer@gmail.com>
Rozhnov Alexandr <nox73@ya.ru> Rozhnov Alexandr <nox73@ya.ru>
Rudolph Gottesheim <r.gottesheim@loot.at> Rudolph Gottesheim <r.gottesheim@loot.at>
@ -2271,6 +2287,7 @@ Xiaoyu Zhang <zhang.xiaoyu33@zte.com.cn>
xichengliudui <1693291525@qq.com> xichengliudui <1693291525@qq.com>
xiekeyang <xiekeyang@huawei.com> xiekeyang <xiekeyang@huawei.com>
Ximo Guanter Gonzálbez <joaquin.guantergonzalbez@telefonica.com> Ximo Guanter Gonzálbez <joaquin.guantergonzalbez@telefonica.com>
xin.li <xin.li@daocloud.io>
Xinbo Weng <xihuanbo_0521@zju.edu.cn> Xinbo Weng <xihuanbo_0521@zju.edu.cn>
Xinfeng Liu <xinfeng.liu@gmail.com> Xinfeng Liu <xinfeng.liu@gmail.com>
Xinzi Zhou <imdreamrunner@gmail.com> Xinzi Zhou <imdreamrunner@gmail.com>
@ -2282,6 +2299,7 @@ Yahya <ya7yaz@gmail.com>
yalpul <yalpul@gmail.com> yalpul <yalpul@gmail.com>
YAMADA Tsuyoshi <tyamada@minimum2scp.org> YAMADA Tsuyoshi <tyamada@minimum2scp.org>
Yamasaki Masahide <masahide.y@gmail.com> Yamasaki Masahide <masahide.y@gmail.com>
Yamazaki Masashi <masi19bw@gmail.com>
Yan Feng <yanfeng2@huawei.com> Yan Feng <yanfeng2@huawei.com>
Yan Zhu <yanzhu@alauda.io> Yan Zhu <yanzhu@alauda.io>
Yang Bai <hamo.by@gmail.com> Yang Bai <hamo.by@gmail.com>

View file

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

View file

@ -19,10 +19,10 @@ produces:
consumes: consumes:
- "application/json" - "application/json"
- "text/plain" - "text/plain"
basePath: "/v1.42" basePath: "/v1.43"
info: info:
title: "Docker Engine API" title: "Docker Engine API"
version: "1.42" version: "1.43"
x-logo: x-logo:
url: "https://docs.docker.com/assets/images/logo-docker-main.png" url: "https://docs.docker.com/assets/images/logo-docker-main.png"
description: | description: |
@ -55,8 +55,8 @@ info:
the URL is not supported by the daemon, a HTTP `400 Bad Request` error message the URL is not supported by the daemon, a HTTP `400 Bad Request` error message
is returned. is returned.
If you omit the version-prefix, the current version of the API (v1.42) is used. 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.42/info`. Using the For example, calling `/info` is the same as calling `/v1.43/info`. Using the
API without a version-prefix is deprecated and will be removed in a future release. 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, Engine releases in the near future should support this version of the API,
@ -976,6 +976,13 @@ definitions:
items: items:
type: "integer" type: "integer"
minimum: 0 minimum: 0
Annotations:
type: "object"
description: |
Arbitrary non-identifying metadata attached to container and
provided to the runtime when the container is started.
additionalProperties:
type: "string"
# Applicable to UNIX platforms # Applicable to UNIX platforms
CapAdd: CapAdd:
@ -1122,6 +1129,7 @@ definitions:
remapping option is enabled. remapping option is enabled.
ShmSize: ShmSize:
type: "integer" type: "integer"
format: "int64"
description: | description: |
Size of `/dev/shm` in bytes. If omitted, the system uses 64MB. Size of `/dev/shm` in bytes. If omitted, the system uses 64MB.
minimum: 0 minimum: 0
@ -1610,6 +1618,34 @@ definitions:
"WorkDir": "/var/lib/docker/overlay2/ef749362d13333e65fc95c572eb525abbe0052e16e086cb64bc3b98ae9aa6d74/work" "WorkDir": "/var/lib/docker/overlay2/ef749362d13333e65fc95c572eb525abbe0052e16e086cb64bc3b98ae9aa6d74/work"
} }
FilesystemChange:
description: |
Change in the container's filesystem.
type: "object"
required: [Path, Kind]
properties:
Path:
description: |
Path to file or directory that has changed.
type: "string"
x-nullable: false
Kind:
$ref: "#/definitions/ChangeType"
ChangeType:
description: |
Kind of change
Can be one of:
- `0`: Modified ("C")
- `1`: Added ("A")
- `2`: Deleted ("D")
type: "integer"
format: "uint8"
enum: [0, 1, 2]
x-nullable: false
ImageInspect: ImageInspect:
description: | description: |
Information about an image in the local image cache. Information about an image in the local image cache.
@ -1746,15 +1782,14 @@ definitions:
Total size of the image including all layers it is composed of. Total size of the image including all layers it is composed of.
In versions of Docker before v1.10, this field was calculated from 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 the image itself and all of its parent images. Images are now stored
store images self-contained, and no longer use a parent-chain, making self-contained, and no longer use a parent-chain, making this field
this field an equivalent of the Size field. an equivalent of the Size field.
This field is kept for backward compatibility, but may be removed in > **Deprecated**: this field is kept for backward compatibility, but
a future version of the API. > will be removed in API v1.44.
type: "integer" type: "integer"
format: "int64" format: "int64"
x-nullable: false
example: 1239828 example: 1239828
GraphDriver: GraphDriver:
$ref: "#/definitions/GraphDriverData" $ref: "#/definitions/GraphDriverData"
@ -1802,7 +1837,6 @@ definitions:
- Created - Created
- Size - Size
- SharedSize - SharedSize
- VirtualSize
- Labels - Labels
- Containers - Containers
properties: properties:
@ -1888,19 +1922,17 @@ definitions:
x-nullable: false x-nullable: false
example: 1239828 example: 1239828
VirtualSize: VirtualSize:
description: | description: |-
Total size of the image including all layers it is composed of. Total size of the image including all layers it is composed of.
In versions of Docker before v1.10, this field was calculated from 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 the image itself and all of its parent images. Images are now stored
store images self-contained, and no longer use a parent-chain, making self-contained, and no longer use a parent-chain, making this field
this field an equivalent of the Size field. an equivalent of the Size field.
This field is kept for backward compatibility, but may be removed in Deprecated: this field is kept for backward compatibility, and will be removed in API v1.44.
a future version of the API.
type: "integer" type: "integer"
format: "int64" format: "int64"
x-nullable: false
example: 172064416 example: 172064416
Labels: Labels:
description: "User-defined key/value metadata." description: "User-defined key/value metadata."
@ -4652,7 +4684,8 @@ definitions:
example: false example: false
OOMKilled: OOMKilled:
description: | description: |
Whether this container has been killed because it ran out of memory. Whether a process within this container has been killed because it ran
out of memory since the container was last started.
type: "boolean" type: "boolean"
example: false example: false
Dead: Dead:
@ -5035,7 +5068,7 @@ definitions:
Go runtime (`GOOS`). Go runtime (`GOOS`).
Currently returned values are "linux" and "windows". A full list of 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" type: "string"
example: "linux" example: "linux"
Architecture: Architecture:
@ -5043,7 +5076,7 @@ definitions:
Hardware architecture of the host, as returned by the Go runtime Hardware architecture of the host, as returned by the Go runtime
(`GOARCH`). (`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" type: "string"
example: "x86_64" example: "x86_64"
NCPU: NCPU:
@ -5129,42 +5162,8 @@ definitions:
ServerVersion: ServerVersion:
description: | description: |
Version string of the daemon. Version string of the daemon.
> **Note**: the [standalone Swarm API](https://docs.docker.com/swarm/swarm-api/)
> returns the Swarm version instead of the daemon version, for example
> `swarm/1.2.8`.
type: "string" type: "string"
example: "17.06.0-ce" example: "24.0.2"
ClusterStore:
description: |
URL of the distributed storage backend.
The storage backend is used for multihost networking (to store
network and endpoint information) and by the node discovery mechanism.
<p><br /></p>
> **Deprecated**: This field is only propagated when using standalone Swarm
> mode, and overlay networking using an external k/v store. Overlay
> networks with Swarm mode enabled use the built-in raft store, and
> this field will be empty.
type: "string"
example: "consul://consul.corp.example.com:8600/some/path"
ClusterAdvertise:
description: |
The network endpoint that the Engine advertises for the purpose of
node discovery. ClusterAdvertise is a `host:port` combination on which
the daemon is reachable by other hosts.
<p><br /></p>
> **Deprecated**: This field is only propagated when using standalone Swarm
> mode, and overlay networking using an external k/v store. Overlay
> networks with Swarm mode enabled use the built-in raft store, and
> this field will be empty.
type: "string"
example: "node5.corp.example.com:8000"
Runtimes: Runtimes:
description: | description: |
List of [OCI compliant](https://github.com/opencontainers/runtime-spec) List of [OCI compliant](https://github.com/opencontainers/runtime-spec)
@ -5242,7 +5241,8 @@ definitions:
SecurityOptions: SecurityOptions:
description: | description: |
List of security features that are enabled on the daemon, such as List of security features that are enabled on the daemon, such as
apparmor, seccomp, SELinux, user-namespaces (userns), and rootless. apparmor, seccomp, SELinux, user-namespaces (userns), rootless and
no-new-privileges.
Additional configuration options for each security feature may Additional configuration options for each security feature may
be present, and are included as a comma-separated list of key/value be present, and are included as a comma-separated list of key/value
@ -6875,9 +6875,9 @@ paths:
Returns which files in a container's filesystem have been added, deleted, Returns which files in a container's filesystem have been added, deleted,
or modified. The `Kind` of modification can be one of: or modified. The `Kind` of modification can be one of:
- `0`: Modified - `0`: Modified ("C")
- `1`: Added - `1`: Added ("A")
- `2`: Deleted - `2`: Deleted ("D")
operationId: "ContainerChanges" operationId: "ContainerChanges"
produces: ["application/json"] produces: ["application/json"]
responses: responses:
@ -6886,22 +6886,7 @@ paths:
schema: schema:
type: "array" type: "array"
items: items:
type: "object" $ref: "#/definitions/FilesystemChange"
x-go-name: "ContainerChangeResponseItem"
title: "ContainerChangeResponseItem"
description: "change item in response to ContainerChanges operation"
required: [Path, Kind]
properties:
Path:
description: "Path to file that has changed"
type: "string"
x-nullable: false
Kind:
description: "Kind of change"
type: "integer"
format: "uint8"
enum: [0, 1, 2]
x-nullable: false
examples: examples:
application/json: application/json:
- Path: "/dev" - Path: "/dev"
@ -8228,7 +8213,7 @@ paths:
Available filters: Available filters:
- `until=<duration>`: duration relative to daemon's time, during which build cache was not used, in Go's duration format (e.g., '24h') - `until=<timestamp>` remove cache older than `<timestamp>`. The `<timestamp>` can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. `10m`, `1h30m`) computed relative to the daemon's local time.
- `id=<id>` - `id=<id>`
- `parent=<id>` - `parent=<id>`
- `type=<string>` - `type=<string>`
@ -9911,7 +9896,9 @@ paths:
Id: "22be93d5babb089c5aab8dbc369042fad48ff791584ca2da2100db837a1c7c30" Id: "22be93d5babb089c5aab8dbc369042fad48ff791584ca2da2100db837a1c7c30"
Warning: "" Warning: ""
403: 403:
description: "operation not supported for pre-defined networks" description: |
Forbidden operation. This happens when trying to create a network named after a pre-defined network,
or when trying to create an overlay network on a daemon which is not part of a Swarm cluster.
schema: schema:
$ref: "#/definitions/ErrorResponse" $ref: "#/definitions/ErrorResponse"
404: 404:
@ -10374,6 +10361,12 @@ paths:
default if omitted. default if omitted.
required: true required: true
type: "string" type: "string"
- name: "force"
in: "query"
description: |
Force disable a plugin even if still in use.
required: false
type: "boolean"
tags: ["Plugin"] tags: ["Plugin"]
/plugins/{name}/upgrade: /plugins/{name}/upgrade:
post: post:

View file

@ -1,22 +1,7 @@
package types // import "github.com/docker/docker/api/types" 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 // AuthConfig contains authorization information for connecting to a Registry.
type AuthConfig struct { //
Username string `json:"username,omitempty"` // Deprecated: use github.com/docker/docker/api/types/registry.AuthConfig
Password string `json:"password,omitempty"` type AuthConfig = registry.AuthConfig
Auth string `json:"auth,omitempty"`
// Email is an optional value associated with the username.
// This field is deprecated and will be removed in a later
// version of docker.
Email string `json:"email,omitempty"`
ServerAddress string `json:"serveraddress,omitempty"`
// IdentityToken is used to authenticate the user and get
// an access token for the registry.
IdentityToken string `json:"identitytoken,omitempty"`
// RegistryToken is a bearer token to be sent to a registry
RegistryToken string `json:"registrytoken,omitempty"`
}

View file

@ -7,6 +7,7 @@ import (
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/registry"
units "github.com/docker/go-units" units "github.com/docker/go-units"
) )
@ -180,7 +181,7 @@ type ImageBuildOptions struct {
// at all (nil). See the parsing of buildArgs in // at all (nil). See the parsing of buildArgs in
// api/server/router/build/build_routes.go for even more info. // api/server/router/build/build_routes.go for even more info.
BuildArgs map[string]*string BuildArgs map[string]*string
AuthConfigs map[string]AuthConfig AuthConfigs map[string]registry.AuthConfig
Context io.Reader Context io.Reader
Labels map[string]string Labels map[string]string
// squash the resulting image's layers to the parent // squash the resulting image's layers to the parent

View file

@ -3,7 +3,7 @@ package types // import "github.com/docker/docker/api/types"
import ( import (
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/network" "github.com/docker/docker/api/types/network"
specs "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
) )
// configs holds structs used for internal communication between the // configs holds structs used for internal communication between the
@ -16,7 +16,7 @@ type ContainerCreateConfig struct {
Config *container.Config Config *container.Config
HostConfig *container.HostConfig HostConfig *container.HostConfig
NetworkingConfig *network.NetworkingConfig NetworkingConfig *network.NetworkingConfig
Platform *specs.Platform Platform *ocispec.Platform
AdjustCPUShares bool AdjustCPUShares bool
} }

View file

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

View file

@ -0,0 +1,15 @@
package container
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
// ChangeType Kind of change
//
// Can be one of:
//
// - `0`: Modified ("C")
// - `1`: Added ("A")
// - `2`: Deleted ("D")
//
// swagger:model ChangeType
type ChangeType uint8

View file

@ -0,0 +1,23 @@
package container
const (
// ChangeModify represents the modify operation.
ChangeModify ChangeType = 0
// ChangeAdd represents the add operation.
ChangeAdd ChangeType = 1
// ChangeDelete represents the delete operation.
ChangeDelete ChangeType = 2
)
func (ct ChangeType) String() string {
switch ct {
case ChangeModify:
return "C"
case ChangeAdd:
return "A"
case ChangeDelete:
return "D"
default:
return ""
}
}

View file

@ -1,20 +0,0 @@
package container // import "github.com/docker/docker/api/types/container"
// ----------------------------------------------------------------------------
// Code generated by `swagger generate operation`. DO NOT EDIT.
//
// See hack/generate-swagger-api.sh
// ----------------------------------------------------------------------------
// ContainerChangeResponseItem change item in response to ContainerChanges operation
// swagger:model ContainerChangeResponseItem
type ContainerChangeResponseItem struct {
// Kind of change
// Required: true
Kind uint8 `json:"Kind"`
// Path to file that has changed
// Required: true
Path string `json:"Path"`
}

View file

@ -1,16 +0,0 @@
package container // import "github.com/docker/docker/api/types/container"
// ContainerCreateCreatedBody OK response to ContainerCreate operation
//
// Deprecated: use CreateResponse
type ContainerCreateCreatedBody = CreateResponse
// ContainerWaitOKBody OK response to ContainerWait operation
//
// Deprecated: use WaitResponse
type ContainerWaitOKBody = WaitResponse
// ContainerWaitOKBodyError container waiting error, if any
//
// Deprecated: use WaitExitError
type ContainerWaitOKBodyError = WaitExitError

View file

@ -0,0 +1,19 @@
package container
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
// FilesystemChange Change in the container's filesystem.
//
// swagger:model FilesystemChange
type FilesystemChange struct {
// kind
// Required: true
Kind ChangeType `json:"Kind"`
// Path to file or directory that has changed.
//
// Required: true
Path string `json:"Path"`
}

View file

@ -101,7 +101,8 @@ func (n IpcMode) IsShareable() bool {
// IsContainer indicates whether the container uses another container's ipc namespace. // IsContainer indicates whether the container uses another container's ipc namespace.
func (n IpcMode) IsContainer() bool { func (n IpcMode) IsContainer() bool {
return strings.HasPrefix(string(n), string(IPCModeContainer)+":") _, ok := containerID(string(n))
return ok
} }
// IsNone indicates whether container IpcMode is set to "none". // IsNone indicates whether container IpcMode is set to "none".
@ -116,15 +117,14 @@ func (n IpcMode) IsEmpty() bool {
// Valid indicates whether the ipc mode is valid. // Valid indicates whether the ipc mode is valid.
func (n IpcMode) Valid() bool { func (n IpcMode) Valid() bool {
// TODO(thaJeztah): align with PidMode, and consider container-mode without a container name/ID to be invalid.
return n.IsEmpty() || n.IsNone() || n.IsPrivate() || n.IsHost() || n.IsShareable() || n.IsContainer() return n.IsEmpty() || n.IsNone() || n.IsPrivate() || n.IsHost() || n.IsShareable() || n.IsContainer()
} }
// Container returns the name of the container ipc stack is going to be used. // Container returns the name of the container ipc stack is going to be used.
func (n IpcMode) Container() string { func (n IpcMode) Container() (idOrName string) {
if n.IsContainer() { idOrName, _ = containerID(string(n))
return strings.TrimPrefix(string(n), string(IPCModeContainer)+":") return idOrName
}
return ""
} }
// NetworkMode represents the container network stack. // NetworkMode represents the container network stack.
@ -147,17 +147,14 @@ func (n NetworkMode) IsPrivate() bool {
// IsContainer indicates whether container uses a container network stack. // IsContainer indicates whether container uses a container network stack.
func (n NetworkMode) IsContainer() bool { func (n NetworkMode) IsContainer() bool {
parts := strings.SplitN(string(n), ":", 2) _, ok := containerID(string(n))
return len(parts) > 1 && parts[0] == "container" return ok
} }
// ConnectedContainer is the id of the container which network this container is connected to. // ConnectedContainer is the id of the container which network this container is connected to.
func (n NetworkMode) ConnectedContainer() string { func (n NetworkMode) ConnectedContainer() (idOrName string) {
parts := strings.SplitN(string(n), ":", 2) idOrName, _ = containerID(string(n))
if len(parts) > 1 { return idOrName
return parts[1]
}
return ""
} }
// UserDefined indicates user-created network // UserDefined indicates user-created network
@ -178,18 +175,12 @@ func (n UsernsMode) IsHost() bool {
// IsPrivate indicates whether the container uses the a private userns. // IsPrivate indicates whether the container uses the a private userns.
func (n UsernsMode) IsPrivate() bool { func (n UsernsMode) IsPrivate() bool {
return !(n.IsHost()) return !n.IsHost()
} }
// Valid indicates whether the userns is valid. // Valid indicates whether the userns is valid.
func (n UsernsMode) Valid() bool { func (n UsernsMode) Valid() bool {
parts := strings.Split(string(n), ":") return n == "" || n.IsHost()
switch mode := parts[0]; mode {
case "", "host":
default:
return false
}
return true
} }
// CgroupSpec represents the cgroup to use for the container. // CgroupSpec represents the cgroup to use for the container.
@ -197,22 +188,20 @@ type CgroupSpec string
// IsContainer indicates whether the container is using another container cgroup // IsContainer indicates whether the container is using another container cgroup
func (c CgroupSpec) IsContainer() bool { func (c CgroupSpec) IsContainer() bool {
parts := strings.SplitN(string(c), ":", 2) _, ok := containerID(string(c))
return len(parts) > 1 && parts[0] == "container" return ok
} }
// Valid indicates whether the cgroup spec is valid. // Valid indicates whether the cgroup spec is valid.
func (c CgroupSpec) Valid() bool { func (c CgroupSpec) Valid() bool {
return c.IsContainer() || c == "" // TODO(thaJeztah): align with PidMode, and consider container-mode without a container name/ID to be invalid.
return c == "" || c.IsContainer()
} }
// Container returns the name of the container whose cgroup will be used. // Container returns the ID or name of the container whose cgroup will be used.
func (c CgroupSpec) Container() string { func (c CgroupSpec) Container() (idOrName string) {
parts := strings.SplitN(string(c), ":", 2) idOrName, _ = containerID(string(c))
if len(parts) > 1 { return idOrName
return parts[1]
}
return ""
} }
// UTSMode represents the UTS namespace of the container. // UTSMode represents the UTS namespace of the container.
@ -220,7 +209,7 @@ type UTSMode string
// IsPrivate indicates whether the container uses its private UTS namespace. // IsPrivate indicates whether the container uses its private UTS namespace.
func (n UTSMode) IsPrivate() bool { func (n UTSMode) IsPrivate() bool {
return !(n.IsHost()) return !n.IsHost()
} }
// IsHost indicates whether the container uses the host's UTS namespace. // IsHost indicates whether the container uses the host's UTS namespace.
@ -230,13 +219,7 @@ func (n UTSMode) IsHost() bool {
// Valid indicates whether the UTS namespace is valid. // Valid indicates whether the UTS namespace is valid.
func (n UTSMode) Valid() bool { func (n UTSMode) Valid() bool {
parts := strings.Split(string(n), ":") return n == "" || n.IsHost()
switch mode := parts[0]; mode {
case "", "host":
default:
return false
}
return true
} }
// PidMode represents the pid namespace of the container. // PidMode represents the pid namespace of the container.
@ -254,32 +237,19 @@ func (n PidMode) IsHost() bool {
// IsContainer indicates whether the container uses a container's pid namespace. // IsContainer indicates whether the container uses a container's pid namespace.
func (n PidMode) IsContainer() bool { func (n PidMode) IsContainer() bool {
parts := strings.SplitN(string(n), ":", 2) _, ok := containerID(string(n))
return len(parts) > 1 && parts[0] == "container" return ok
} }
// Valid indicates whether the pid namespace is valid. // Valid indicates whether the pid namespace is valid.
func (n PidMode) Valid() bool { func (n PidMode) Valid() bool {
parts := strings.Split(string(n), ":") return n == "" || n.IsHost() || validContainer(string(n))
switch mode := parts[0]; mode {
case "", "host":
case "container":
if len(parts) != 2 || parts[1] == "" {
return false
}
default:
return false
}
return true
} }
// Container returns the name of the container whose pid namespace is going to be used. // Container returns the name of the container whose pid namespace is going to be used.
func (n PidMode) Container() string { func (n PidMode) Container() (idOrName string) {
parts := strings.SplitN(string(n), ":", 2) idOrName, _ = containerID(string(n))
if len(parts) > 1 { return idOrName
return parts[1]
}
return ""
} }
// DeviceRequest represents a request for devices from a device driver. // DeviceRequest represents a request for devices from a device driver.
@ -408,16 +378,17 @@ type UpdateConfig struct {
// Portable information *should* appear in Config. // Portable information *should* appear in Config.
type HostConfig struct { type HostConfig struct {
// Applicable to all platforms // Applicable to all platforms
Binds []string // List of volume bindings for this container Binds []string // List of volume bindings for this container
ContainerIDFile string // File (path) where the containerId is written ContainerIDFile string // File (path) where the containerId is written
LogConfig LogConfig // Configuration of the logs for this container LogConfig LogConfig // Configuration of the logs for this container
NetworkMode NetworkMode // Network mode to use for the container NetworkMode NetworkMode // Network mode to use for the container
PortBindings nat.PortMap // Port mapping between the exposed port (container) and the host PortBindings nat.PortMap // Port mapping between the exposed port (container) and the host
RestartPolicy RestartPolicy // Restart policy to be used for the container RestartPolicy RestartPolicy // Restart policy to be used for the container
AutoRemove bool // Automatically remove container when it exits AutoRemove bool // Automatically remove container when it exits
VolumeDriver string // Name of the volume driver used to mount volumes VolumeDriver string // Name of the volume driver used to mount volumes
VolumesFrom []string // List of volumes to take from other container VolumesFrom []string // List of volumes to take from other container
ConsoleSize [2]uint // Initial console size (height,width) ConsoleSize [2]uint // Initial console size (height,width)
Annotations map[string]string `json:",omitempty"` // Arbitrary non-identifying metadata attached to container and provided to the runtime
// Applicable to UNIX platforms // Applicable to UNIX platforms
CapAdd strslice.StrSlice // List of kernel capabilities to add to the container CapAdd strslice.StrSlice // List of kernel capabilities to add to the container
@ -463,3 +434,23 @@ type HostConfig struct {
// Run a custom init inside the container, if null, use the daemon's configured settings // Run a custom init inside the container, if null, use the daemon's configured settings
Init *bool `json:",omitempty"` Init *bool `json:",omitempty"`
} }
// containerID splits "container:<ID|name>" values. It returns the container
// ID or name, and whether an ID/name was found. It returns an empty string and
// a "false" if the value does not have a "container:" prefix. Further validation
// of the returned, including checking if the value is empty, should be handled
// by the caller.
func containerID(val string) (idOrName string, ok bool) {
k, v, hasSep := strings.Cut(val, ":")
if !hasSep || k != "container" {
return "", false
}
return v, true
}
// validContainer checks if the given value is a "container:" mode with
// a non-empty name/ID.
func validContainer(val string) bool {
id, ok := containerID(val)
return ok && id != ""
}

View file

@ -1,14 +0,0 @@
package types // import "github.com/docker/docker/api/types"
import "github.com/docker/docker/api/types/volume"
// Volume volume
//
// Deprecated: use github.com/docker/docker/api/types/volume.Volume
type Volume = volume.Volume
// VolumeUsageData Usage details about the volume. This information is used by the
// `GET /system/df` endpoint, and omitted in other endpoints.
//
// Deprecated: use github.com/docker/docker/api/types/volume.UsageData
type VolumeUsageData = volume.UsageData

View file

@ -0,0 +1,37 @@
package filters
import "fmt"
// invalidFilter indicates that the provided filter or its value is invalid
type invalidFilter struct {
Filter string
Value []string
}
func (e invalidFilter) Error() string {
msg := "invalid filter"
if e.Filter != "" {
msg += " '" + e.Filter
if e.Value != nil {
msg = fmt.Sprintf("%s=%s", msg, e.Value)
}
msg += "'"
}
return msg
}
// InvalidParameter marks this error as ErrInvalidParameter
func (e invalidFilter) InvalidParameter() {}
// unreachableCode is an error indicating that the code path was not expected to be reached.
type unreachableCode struct {
Filter string
Value []string
}
// System marks this error as ErrSystem
func (e unreachableCode) System() {}
func (e unreachableCode) Error() string {
return fmt.Sprintf("unreachable code reached for filter: %q with values: %s", e.Filter, e.Value)
}

View file

@ -10,7 +10,6 @@ import (
"strings" "strings"
"github.com/docker/docker/api/types/versions" "github.com/docker/docker/api/types/versions"
"github.com/pkg/errors"
) )
// Args stores a mapping of keys to a set of multiple values. // Args stores a mapping of keys to a set of multiple values.
@ -99,7 +98,7 @@ func FromJSON(p string) (Args, error) {
// Fallback to parsing arguments in the legacy slice format // Fallback to parsing arguments in the legacy slice format
deprecated := map[string][]string{} deprecated := map[string][]string{}
if legacyErr := json.Unmarshal(raw, &deprecated); legacyErr != nil { if legacyErr := json.Unmarshal(raw, &deprecated); legacyErr != nil {
return args, invalidFilter{errors.Wrap(err, "invalid filter")} return args, &invalidFilter{}
} }
args.fields = deprecatedArgs(deprecated) args.fields = deprecatedArgs(deprecated)
@ -163,13 +162,13 @@ func (args Args) MatchKVList(key string, sources map[string]string) bool {
} }
for value := range fieldValues { for value := range fieldValues {
testKV := strings.SplitN(value, "=", 2) testK, testV, hasValue := strings.Cut(value, "=")
v, ok := sources[testKV[0]] v, ok := sources[testK]
if !ok { if !ok {
return false return false
} }
if len(testKV) == 2 && testKV[1] != v { if hasValue && testV != v {
return false return false
} }
} }
@ -196,6 +195,38 @@ func (args Args) Match(field, source string) bool {
return false return false
} }
// GetBoolOrDefault returns a boolean value of the key if the key is present
// and is intepretable as a boolean value. Otherwise the default value is returned.
// Error is not nil only if the filter values are not valid boolean or are conflicting.
func (args Args) GetBoolOrDefault(key string, defaultValue bool) (bool, error) {
fieldValues, ok := args.fields[key]
if !ok {
return defaultValue, nil
}
if len(fieldValues) == 0 {
return defaultValue, &invalidFilter{key, nil}
}
isFalse := fieldValues["0"] || fieldValues["false"]
isTrue := fieldValues["1"] || fieldValues["true"]
conflicting := isFalse && isTrue
invalid := !isFalse && !isTrue
if conflicting || invalid {
return defaultValue, &invalidFilter{key, args.Get(key)}
} else if isFalse {
return false, nil
} else if isTrue {
return true, nil
}
// This code shouldn't be reached.
return defaultValue, &unreachableCode{Filter: key, Value: args.Get(key)}
}
// ExactMatch returns true if the source matches exactly one of the values. // ExactMatch returns true if the source matches exactly one of the values.
func (args Args) ExactMatch(key, source string) bool { func (args Args) ExactMatch(key, source string) bool {
fieldValues, ok := args.fields[key] fieldValues, ok := args.fields[key]
@ -246,20 +277,12 @@ func (args Args) Contains(field string) bool {
return ok return ok
} }
type invalidFilter struct{ error }
func (e invalidFilter) Error() string {
return e.error.Error()
}
func (invalidFilter) InvalidParameter() {}
// Validate compared the set of accepted keys against the keys in the mapping. // Validate compared the set of accepted keys against the keys in the mapping.
// An error is returned if any mapping keys are not in the accepted set. // An error is returned if any mapping keys are not in the accepted set.
func (args Args) Validate(accepted map[string]bool) error { func (args Args) Validate(accepted map[string]bool) error {
for name := range args.fields { for name := range args.fields {
if !accepted[name] { if !accepted[name] {
return invalidFilter{errors.New("invalid filter '" + name + "'")} return &invalidFilter{name, nil}
} }
} }
return nil return nil

View file

@ -0,0 +1,9 @@
package image
import ocispec "github.com/opencontainers/image-spec/specs-go/v1"
// GetImageOpts holds parameters to inspect an image.
type GetImageOpts struct {
Platform *ocispec.Platform
Details bool
}

View file

@ -85,13 +85,10 @@ type ImageSummary struct {
// Total size of the image including all layers it is composed of. // Total size of the image including all layers it is composed of.
// //
// In versions of Docker before v1.10, this field was calculated from // 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 // the image itself and all of its parent images. Images are now stored
// store images self-contained, and no longer use a parent-chain, making // self-contained, and no longer use a parent-chain, making this field
// this field an equivalent of the Size field. // an equivalent of the Size field.
// //
// This field is kept for backward compatibility, but may be removed in // Deprecated: this field is kept for backward compatibility, and will be removed in API v1.44.
// a future version of the API. VirtualSize int64 `json:"VirtualSize,omitempty"`
//
// Required: true
VirtualSize int64 `json:"VirtualSize"`
} }

View file

@ -0,0 +1,99 @@
package registry // import "github.com/docker/docker/api/types/registry"
import (
"encoding/base64"
"encoding/json"
"io"
"strings"
"github.com/pkg/errors"
)
// AuthHeader is the name of the header used to send encoded registry
// authorization credentials for registry operations (push/pull).
const AuthHeader = "X-Registry-Auth"
// AuthConfig contains authorization information for connecting to a Registry.
type AuthConfig struct {
Username string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
Auth string `json:"auth,omitempty"`
// Email is an optional value associated with the username.
// This field is deprecated and will be removed in a later
// version of docker.
Email string `json:"email,omitempty"`
ServerAddress string `json:"serveraddress,omitempty"`
// IdentityToken is used to authenticate the user and get
// an access token for the registry.
IdentityToken string `json:"identitytoken,omitempty"`
// RegistryToken is a bearer token to be sent to a registry
RegistryToken string `json:"registrytoken,omitempty"`
}
// EncodeAuthConfig serializes the auth configuration as a base64url encoded
// RFC4648, section 5) JSON string for sending through the X-Registry-Auth header.
//
// For details on base64url encoding, see:
// - RFC4648, section 5: https://tools.ietf.org/html/rfc4648#section-5
func EncodeAuthConfig(authConfig AuthConfig) (string, error) {
buf, err := json.Marshal(authConfig)
if err != nil {
return "", errInvalidParameter{err}
}
return base64.URLEncoding.EncodeToString(buf), nil
}
// DecodeAuthConfig decodes base64url encoded (RFC4648, section 5) JSON
// authentication information as sent through the X-Registry-Auth header.
//
// This function always returns an AuthConfig, even if an error occurs. It is up
// to the caller to decide if authentication is required, and if the error can
// be ignored.
//
// For details on base64url encoding, see:
// - RFC4648, section 5: https://tools.ietf.org/html/rfc4648#section-5
func DecodeAuthConfig(authEncoded string) (*AuthConfig, error) {
if authEncoded == "" {
return &AuthConfig{}, nil
}
authJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
return decodeAuthConfigFromReader(authJSON)
}
// DecodeAuthConfigBody decodes authentication information as sent as JSON in the
// body of a request. This function is to provide backward compatibility with old
// clients and API versions. Current clients and API versions expect authentication
// to be provided through the X-Registry-Auth header.
//
// Like DecodeAuthConfig, this function always returns an AuthConfig, even if an
// error occurs. It is up to the caller to decide if authentication is required,
// and if the error can be ignored.
func DecodeAuthConfigBody(rdr io.ReadCloser) (*AuthConfig, error) {
return decodeAuthConfigFromReader(rdr)
}
func decodeAuthConfigFromReader(rdr io.Reader) (*AuthConfig, error) {
authConfig := &AuthConfig{}
if err := json.NewDecoder(rdr).Decode(authConfig); err != nil {
// always return an (empty) AuthConfig to increase compatibility with
// the existing API.
return &AuthConfig{}, invalid(err)
}
return authConfig, nil
}
func invalid(err error) error {
return errInvalidParameter{errors.Wrap(err, "invalid X-Registry-Auth header")}
}
type errInvalidParameter struct{ error }
func (errInvalidParameter) InvalidParameter() {}
func (e errInvalidParameter) Cause() error { return e.error }
func (e errInvalidParameter) Unwrap() error { return e.error }

View file

@ -4,7 +4,7 @@ import (
"encoding/json" "encoding/json"
"net" "net"
v1 "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
) )
// ServiceConfig stores daemon registry services configuration. // ServiceConfig stores daemon registry services configuration.
@ -113,8 +113,8 @@ type SearchResults struct {
type DistributionInspect struct { type DistributionInspect struct {
// Descriptor contains information about the manifest, including // Descriptor contains information about the manifest, including
// the content addressable digest // the content addressable digest
Descriptor v1.Descriptor Descriptor ocispec.Descriptor
// Platforms contains the list of platforms supported by the image, // Platforms contains the list of platforms supported by the image,
// obtained by parsing the manifest // obtained by parsing the manifest
Platforms []v1.Platform Platforms []ocispec.Platform
} }

View file

@ -95,37 +95,37 @@ func GetTimestamp(value string, reference time.Time) (string, error) {
return fmt.Sprintf("%d.%09d", t.Unix(), int64(t.Nanosecond())), nil return fmt.Sprintf("%d.%09d", t.Unix(), int64(t.Nanosecond())), nil
} }
// ParseTimestamps returns seconds and nanoseconds from a timestamp that has the // ParseTimestamps returns seconds and nanoseconds from a timestamp that has
// format "%d.%09d", time.Unix(), int64(time.Nanosecond())) // the format ("%d.%09d", time.Unix(), int64(time.Nanosecond())).
// if the incoming nanosecond portion is longer or shorter than 9 digits it is // If the incoming nanosecond portion is longer than 9 digits it is truncated.
// converted to nanoseconds. The expectation is that the seconds and // The expectation is that the seconds and nanoseconds will be used to create a
// seconds will be used to create a time variable. For example: // time variable. For example:
// //
// seconds, nanoseconds, err := ParseTimestamp("1136073600.000000001",0) // seconds, nanoseconds, _ := ParseTimestamp("1136073600.000000001",0)
// if err == nil since := time.Unix(seconds, nanoseconds) // since := time.Unix(seconds, nanoseconds)
// //
// returns seconds as def(aultSeconds) if value == "" // returns seconds as defaultSeconds if value == ""
func ParseTimestamps(value string, def int64) (int64, int64, error) { func ParseTimestamps(value string, defaultSeconds int64) (seconds int64, nanoseconds int64, err error) {
if value == "" { if value == "" {
return def, 0, nil return defaultSeconds, 0, nil
} }
return parseTimestamp(value) return parseTimestamp(value)
} }
func parseTimestamp(value string) (int64, int64, error) { func parseTimestamp(value string) (sec int64, nsec int64, err error) {
sa := strings.SplitN(value, ".", 2) s, n, ok := strings.Cut(value, ".")
s, err := strconv.ParseInt(sa[0], 10, 64) sec, err = strconv.ParseInt(s, 10, 64)
if err != nil { if err != nil {
return s, 0, err return sec, 0, err
} }
if len(sa) != 2 { if !ok {
return s, 0, nil return sec, 0, nil
} }
n, err := strconv.ParseInt(sa[1], 10, 64) nsec, err = strconv.ParseInt(n, 10, 64)
if err != nil { if err != nil {
return s, n, err return sec, nsec, err
} }
// should already be in nanoseconds but just in case convert n to nanoseconds // should already be in nanoseconds but just in case convert n to nanoseconds
n = int64(float64(n) * math.Pow(float64(10), float64(9-len(sa[1])))) nsec = int64(float64(nsec) * math.Pow(float64(10), float64(9-len(n))))
return s, n, nil return sec, nsec, nil
} }

View file

@ -123,9 +123,8 @@ type ImageInspect struct {
// store images self-contained, and no longer use a parent-chain, making // store images self-contained, and no longer use a parent-chain, making
// this field an equivalent of the Size field. // this field an equivalent of the Size field.
// //
// This field is kept for backward compatibility, but may be removed in // Deprecated: Unused in API 1.43 and up, but kept for backward compatibility with older API versions.
// a future version of the API. VirtualSize int64 `json:"VirtualSize,omitempty"`
VirtualSize int64 // TODO(thaJeztah): deprecate this field
// GraphDriver holds information about the storage driver used to store the // GraphDriver holds information about the storage driver used to store the
// container's and image's filesystem. // container's and image's filesystem.
@ -297,8 +296,6 @@ type Info struct {
Labels []string Labels []string
ExperimentalBuild bool ExperimentalBuild bool
ServerVersion string ServerVersion string
ClusterStore string `json:",omitempty"` // Deprecated: host-discovery and overlay networks with external k/v stores are deprecated
ClusterAdvertise string `json:",omitempty"` // Deprecated: host-discovery and overlay networks with external k/v stores are deprecated
Runtimes map[string]Runtime Runtimes map[string]Runtime
DefaultRuntime string DefaultRuntime string
Swarm swarm.Info Swarm swarm.Info
@ -350,20 +347,19 @@ func DecodeSecurityOptions(opts []string) ([]SecurityOpt, error) {
continue continue
} }
secopt := SecurityOpt{} secopt := SecurityOpt{}
split := strings.Split(opt, ",") for _, s := range strings.Split(opt, ",") {
for _, s := range split { k, v, ok := strings.Cut(s, "=")
kv := strings.SplitN(s, "=", 2) if !ok {
if len(kv) != 2 {
return nil, fmt.Errorf("invalid security option %q", s) return nil, fmt.Errorf("invalid security option %q", s)
} }
if kv[0] == "" || kv[1] == "" { if k == "" || v == "" {
return nil, errors.New("invalid empty security option") return nil, errors.New("invalid empty security option")
} }
if kv[0] == "name" { if k == "name" {
secopt.Name = kv[1] secopt.Name = v
continue continue
} }
secopt.Options = append(secopt.Options, KeyValue{Key: kv[0], Value: kv[1]}) secopt.Options = append(secopt.Options, KeyValue{Key: k, Value: v})
} }
so = append(so, secopt) so = append(so, secopt)
} }
@ -656,12 +652,18 @@ type Checkpoint struct {
// Runtime describes an OCI runtime // Runtime describes an OCI runtime
type Runtime struct { type Runtime struct {
Path string `json:"path"` // "Legacy" runtime configuration for runc-compatible runtimes.
Path string `json:"path,omitempty"`
Args []string `json:"runtimeArgs,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 // This is exposed here only for internal use
// It is not currently supported to specify custom shim configs ShimConfig *ShimConfig `json:"-"`
Shim *ShimConfig `json:"-"`
} }
// ShimConfig is used by runtime to configure containerd shims // ShimConfig is used by runtime to configure containerd shims

View file

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

View file

@ -1,11 +0,0 @@
package volume // import "github.com/docker/docker/api/types/volume"
// VolumeCreateBody Volume configuration
//
// Deprecated: use CreateOptions
type VolumeCreateBody = CreateOptions
// VolumeListOKBody Volume list response
//
// Deprecated: use ListResponse
type VolumeListOKBody = ListResponse

View file

@ -3,8 +3,8 @@ package client // import "github.com/docker/docker/client"
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"fmt"
"net/url" "net/url"
"strconv"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
@ -23,12 +23,12 @@ func (cli *Client) BuildCachePrune(ctx context.Context, opts types.BuildCachePru
if opts.All { if opts.All {
query.Set("all", "1") query.Set("all", "1")
} }
query.Set("keep-storage", fmt.Sprintf("%d", opts.KeepStorage)) query.Set("keep-storage", strconv.Itoa(int(opts.KeepStorage)))
filters, err := filters.ToJSON(opts.Filters) f, err := filters.ToJSON(opts.Filters)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "prune could not marshal filters option") return nil, errors.Wrap(err, "prune could not marshal filters option")
} }
query.Set("filters", filters) query.Set("filters", f)
serverResp, err := cli.post(ctx, "/build/prune", query, nil, nil) serverResp, err := cli.post(ctx, "/build/prune", query, nil, nil)
defer ensureReaderClosed(serverResp) defer ensureReaderClosed(serverResp)
@ -38,7 +38,7 @@ func (cli *Client) BuildCachePrune(ctx context.Context, opts types.BuildCachePru
} }
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
return nil, fmt.Errorf("Error retrieving disk usage: %v", err) return nil, errors.Wrap(err, "error retrieving disk usage")
} }
return &report, nil return &report, nil

View file

@ -156,7 +156,12 @@ func CheckRedirect(req *http.Request, via []*http.Request) error {
// client.WithAPIVersionNegotiation(), // client.WithAPIVersionNegotiation(),
// ) // )
func NewClientWithOpts(ops ...Opt) (*Client, error) { func NewClientWithOpts(ops ...Opt) (*Client, error) {
client, err := defaultHTTPClient(DefaultDockerHost) hostURL, err := ParseHostURL(DefaultDockerHost)
if err != nil {
return nil, err
}
client, err := defaultHTTPClient(hostURL)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -164,8 +169,8 @@ func NewClientWithOpts(ops ...Opt) (*Client, error) {
host: DefaultDockerHost, host: DefaultDockerHost,
version: api.DefaultVersion, version: api.DefaultVersion,
client: client, client: client,
proto: defaultProto, proto: hostURL.Scheme,
addr: defaultAddr, addr: hostURL.Host,
} }
for _, op := range ops { for _, op := range ops {
@ -191,13 +196,12 @@ func NewClientWithOpts(ops ...Opt) (*Client, error) {
return c, nil return c, nil
} }
func defaultHTTPClient(host string) (*http.Client, error) { func defaultHTTPClient(hostURL *url.URL) (*http.Client, error) {
hostURL, err := ParseHostURL(host) transport := &http.Transport{}
err := sockets.ConfigureTransport(transport, hostURL.Scheme, hostURL.Host)
if err != nil { if err != nil {
return nil, err return nil, err
} }
transport := &http.Transport{}
_ = sockets.ConfigureTransport(transport, hostURL.Scheme, hostURL.Host)
return &http.Client{ return &http.Client{
Transport: transport, Transport: transport,
CheckRedirect: CheckRedirect, CheckRedirect: CheckRedirect,
@ -313,13 +317,12 @@ func (cli *Client) HTTPClient() *http.Client {
// ParseHostURL parses a url string, validates the string is a host url, and // ParseHostURL parses a url string, validates the string is a host url, and
// returns the parsed URL // returns the parsed URL
func ParseHostURL(host string) (*url.URL, error) { func ParseHostURL(host string) (*url.URL, error) {
protoAddrParts := strings.SplitN(host, "://", 2) proto, addr, ok := strings.Cut(host, "://")
if len(protoAddrParts) == 1 { if !ok || addr == "" {
return nil, errors.Errorf("unable to parse docker host `%s`", host) return nil, errors.Errorf("unable to parse docker host `%s`", host)
} }
var basePath string var basePath string
proto, addr := protoAddrParts[0], protoAddrParts[1]
if proto == "tcp" { if proto == "tcp" {
parsed, err := url.Parse("tcp://" + addr) parsed, err := url.Parse("tcp://" + addr)
if err != nil { if err != nil {

View file

@ -1,11 +1,8 @@
//go:build linux || freebsd || openbsd || netbsd || darwin || solaris || illumos || dragonfly //go:build !windows
// +build linux freebsd openbsd netbsd darwin solaris illumos dragonfly // +build !windows
package client // import "github.com/docker/docker/client" package client // import "github.com/docker/docker/client"
// DefaultDockerHost defines OS-specific default host if the DOCKER_HOST // DefaultDockerHost defines OS-specific default host if the DOCKER_HOST
// (EnvOverrideHost) environment variable is unset or empty. // (EnvOverrideHost) environment variable is unset or empty.
const DefaultDockerHost = "unix:///var/run/docker.sock" const DefaultDockerHost = "unix:///var/run/docker.sock"
const defaultProto = "unix"
const defaultAddr = "/var/run/docker.sock"

View file

@ -3,6 +3,3 @@ package client // import "github.com/docker/docker/client"
// DefaultDockerHost defines OS-specific default host if the DOCKER_HOST // DefaultDockerHost defines OS-specific default host if the DOCKER_HOST
// (EnvOverrideHost) environment variable is unset or empty. // (EnvOverrideHost) environment variable is unset or empty.
const DefaultDockerHost = "npipe:////./pipe/docker_engine" const DefaultDockerHost = "npipe:////./pipe/docker_engine"
const defaultProto = "npipe"
const defaultAddr = "//./pipe/docker_engine"

View file

@ -9,7 +9,7 @@ import (
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/network" "github.com/docker/docker/api/types/network"
"github.com/docker/docker/api/types/versions" "github.com/docker/docker/api/types/versions"
specs "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
) )
type configWrapper struct { type configWrapper struct {
@ -20,7 +20,7 @@ type configWrapper struct {
// ContainerCreate creates a new container based on the given configuration. // ContainerCreate creates a new container based on the given configuration.
// It can be associated with a name, but it's not mandatory. // It can be associated with a name, but it's not mandatory.
func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *specs.Platform, containerName string) (container.CreateResponse, error) { 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 var response container.CreateResponse
if err := cli.NewVersionError("1.25", "stop timeout"); config != nil && config.StopTimeout != nil && err != nil { if err := cli.NewVersionError("1.25", "stop timeout"); config != nil && config.StopTimeout != nil && err != nil {
@ -75,7 +75,7 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config
// Similar to containerd's platforms.Format(), but does allow components to be // Similar to containerd's platforms.Format(), but does allow components to be
// omitted (e.g. pass "architecture" only, without "os": // omitted (e.g. pass "architecture" only, without "os":
// https://github.com/containerd/containerd/blob/v1.5.2/platforms/platforms.go#L243-L263 // https://github.com/containerd/containerd/blob/v1.5.2/platforms/platforms.go#L243-L263
func formatPlatform(platform *specs.Platform) string { func formatPlatform(platform *ocispec.Platform) string {
if platform == nil { if platform == nil {
return "" return ""
} }

View file

@ -9,8 +9,8 @@ import (
) )
// ContainerDiff shows differences in a container filesystem since it was started. // ContainerDiff shows differences in a container filesystem since it was started.
func (cli *Client) ContainerDiff(ctx context.Context, containerID string) ([]container.ContainerChangeResponseItem, error) { func (cli *Client) ContainerDiff(ctx context.Context, containerID string) ([]container.FilesystemChange, error) {
var changes []container.ContainerChangeResponseItem var changes []container.FilesystemChange
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/changes", url.Values{}, nil) serverResp, err := cli.get(ctx, "/containers/"+containerID+"/changes", url.Values{}, nil)
defer ensureReaderClosed(serverResp) defer ensureReaderClosed(serverResp)

View file

@ -66,12 +66,8 @@ func (cli *Client) ContainerWait(ctx context.Context, containerID string, condit
// //
// If there's a JSON parsing error, read the real error message // If there's a JSON parsing error, read the real error message
// off the body and send it to the client. // off the body and send it to the client.
if errors.As(err, new(*json.SyntaxError)) { _, _ = io.ReadAll(io.LimitReader(stream, containerWaitErrorMsgLimit))
_, _ = io.ReadAll(io.LimitReader(stream, containerWaitErrorMsgLimit)) errC <- errors.New(responseText.String())
errC <- errors.New(responseText.String())
} else {
errC <- err
}
return return
} }

View file

@ -5,13 +5,13 @@ import (
"encoding/json" "encoding/json"
"net/url" "net/url"
registrytypes "github.com/docker/docker/api/types/registry" "github.com/docker/docker/api/types/registry"
) )
// DistributionInspect returns the image digest with the full manifest. // DistributionInspect returns the image digest with the full manifest.
func (cli *Client) DistributionInspect(ctx context.Context, image, encodedRegistryAuth string) (registrytypes.DistributionInspect, error) { func (cli *Client) DistributionInspect(ctx context.Context, image, encodedRegistryAuth string) (registry.DistributionInspect, error) {
// Contact the registry to retrieve digest and platform information // Contact the registry to retrieve digest and platform information
var distributionInspect registrytypes.DistributionInspect var distributionInspect registry.DistributionInspect
if image == "" { if image == "" {
return distributionInspect, objectNotFoundError{object: "distribution", id: image} return distributionInspect, objectNotFoundError{object: "distribution", id: image}
} }
@ -23,7 +23,7 @@ func (cli *Client) DistributionInspect(ctx context.Context, image, encodedRegist
if encodedRegistryAuth != "" { if encodedRegistryAuth != "" {
headers = map[string][]string{ headers = map[string][]string{
"X-Registry-Auth": {encodedRegistryAuth}, registry.AuthHeader: {encodedRegistryAuth},
} }
} }

View file

@ -58,31 +58,6 @@ func (e objectNotFoundError) Error() string {
return fmt.Sprintf("Error: No such %s: %s", e.object, e.id) return fmt.Sprintf("Error: No such %s: %s", e.object, e.id)
} }
// IsErrUnauthorized returns true if the error is caused
// when a remote registry authentication fails
//
// Deprecated: use errdefs.IsUnauthorized
func IsErrUnauthorized(err error) bool {
return errdefs.IsUnauthorized(err)
}
type pluginPermissionDenied struct {
name string
}
func (e pluginPermissionDenied) Error() string {
return "Permission denied while installing plugin " + e.name
}
// IsErrNotImplemented returns true if the error is a NotImplemented error.
// This is returned by the API when a requested feature has not been
// implemented.
//
// Deprecated: use errdefs.IsNotImplemented
func IsErrNotImplemented(err error) bool {
return errdefs.IsNotImplemented(err)
}
// NewVersionError returns an error if the APIVersion required // NewVersionError returns an error if the APIVersion required
// if less than the current supported version // if less than the current supported version
func (cli *Client) NewVersionError(APIrequired, feature string) error { func (cli *Client) NewVersionError(APIrequired, feature string) error {

View file

@ -23,14 +23,10 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu
if err != nil { if err != nil {
return types.HijackedResponse{}, err return types.HijackedResponse{}, err
} }
req, err := cli.buildRequest(http.MethodPost, cli.getAPIPath(ctx, path, query), bodyEncoded, headers)
apiPath := cli.getAPIPath(ctx, path, query)
req, err := http.NewRequest(http.MethodPost, apiPath, bodyEncoded)
if err != nil { if err != nil {
return types.HijackedResponse{}, err return types.HijackedResponse{}, err
} }
req = cli.addHeaders(req, headers)
conn, mediaType, err := cli.setupHijackConn(ctx, req, "tcp") conn, mediaType, err := cli.setupHijackConn(ctx, req, "tcp")
if err != nil { if err != nil {
return types.HijackedResponse{}, err return types.HijackedResponse{}, err
@ -64,11 +60,6 @@ func fallbackDial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) {
} }
func (cli *Client) setupHijackConn(ctx context.Context, req *http.Request, proto string) (net.Conn, string, error) { func (cli *Client) setupHijackConn(ctx context.Context, req *http.Request, proto string) (net.Conn, string, error) {
req.URL.Host = cli.addr
if cli.proto == "unix" || cli.proto == "npipe" {
// Override host header for non-tcp connections.
req.Host = DummyHost
}
req.Header.Set("Connection", "Upgrade") req.Header.Set("Connection", "Upgrade")
req.Header.Set("Upgrade", proto) req.Header.Set("Upgrade", proto)
@ -84,8 +75,8 @@ func (cli *Client) setupHijackConn(ctx context.Context, req *http.Request, proto
// state. Setting TCP KeepAlive on the socket connection will prohibit // state. Setting TCP KeepAlive on the socket connection will prohibit
// ECONNTIMEOUT unless the socket connection truly is broken // ECONNTIMEOUT unless the socket connection truly is broken
if tcpConn, ok := conn.(*net.TCPConn); ok { if tcpConn, ok := conn.(*net.TCPConn); ok {
tcpConn.SetKeepAlive(true) _ = tcpConn.SetKeepAlive(true)
tcpConn.SetKeepAlivePeriod(30 * time.Second) _ = tcpConn.SetKeepAlivePeriod(30 * time.Second)
} }
clientconn := httputil.NewClientConn(conn, nil) clientconn := httputil.NewClientConn(conn, nil)
@ -100,7 +91,7 @@ func (cli *Client) setupHijackConn(ctx context.Context, req *http.Request, proto
return nil, "", err return nil, "", err
} }
if resp.StatusCode != http.StatusSwitchingProtocols { if resp.StatusCode != http.StatusSwitchingProtocols {
resp.Body.Close() _ = resp.Body.Close()
return nil, "", fmt.Errorf("unable to upgrade to %s, received %d", proto, resp.StatusCode) return nil, "", fmt.Errorf("unable to upgrade to %s, received %d", proto, resp.StatusCode)
} }
} }

View file

@ -8,6 +8,7 @@ import (
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/registry"
) )
// ImageCreate creates a new image based on the parent options. // ImageCreate creates a new image based on the parent options.
@ -32,6 +33,6 @@ func (cli *Client) ImageCreate(ctx context.Context, parentReference string, opti
} }
func (cli *Client) tryImageCreate(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) { func (cli *Client) tryImageCreate(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) {
headers := map[string][]string{"X-Registry-Auth": {registryAuth}} headers := map[string][]string{registry.AuthHeader: {registryAuth}}
return cli.post(ctx, "/images/create", query, nil, headers) return cli.post(ctx, "/images/create", query, nil, headers)
} }

View file

@ -8,6 +8,7 @@ import (
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/registry"
"github.com/docker/docker/errdefs" "github.com/docker/docker/errdefs"
) )
@ -49,6 +50,6 @@ func (cli *Client) ImagePush(ctx context.Context, image string, options types.Im
} }
func (cli *Client) tryImagePush(ctx context.Context, imageID string, query url.Values, registryAuth string) (serverResponse, error) { func (cli *Client) tryImagePush(ctx context.Context, imageID string, query url.Values, registryAuth string) (serverResponse, error) {
headers := map[string][]string{"X-Registry-Auth": {registryAuth}} headers := map[string][]string{registry.AuthHeader: {registryAuth}}
return cli.post(ctx, "/images/"+imageID+"/push", query, nil, headers) return cli.post(ctx, "/images/"+imageID+"/push", query, nil, headers)
} }

View file

@ -48,6 +48,6 @@ func (cli *Client) ImageSearch(ctx context.Context, term string, options types.I
} }
func (cli *Client) tryImageSearch(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) { func (cli *Client) tryImageSearch(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) {
headers := map[string][]string{"X-Registry-Auth": {registryAuth}} headers := map[string][]string{registry.AuthHeader: {registryAuth}}
return cli.get(ctx, "/images/search", query, headers) return cli.get(ctx, "/images/search", query, headers)
} }

View file

@ -15,7 +15,7 @@ import (
"github.com/docker/docker/api/types/registry" "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/api/types/swarm" "github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/api/types/volume" "github.com/docker/docker/api/types/volume"
specs "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
) )
// CommonAPIClient is the common methods between stable and experimental versions of APIClient. // CommonAPIClient is the common methods between stable and experimental versions of APIClient.
@ -47,8 +47,8 @@ type CommonAPIClient interface {
type ContainerAPIClient interface { type ContainerAPIClient interface {
ContainerAttach(ctx context.Context, container string, options types.ContainerAttachOptions) (types.HijackedResponse, error) ContainerAttach(ctx context.Context, container string, options types.ContainerAttachOptions) (types.HijackedResponse, error)
ContainerCommit(ctx context.Context, container string, options types.ContainerCommitOptions) (types.IDResponse, error) ContainerCommit(ctx context.Context, container string, options types.ContainerCommitOptions) (types.IDResponse, error)
ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *specs.Platform, containerName string) (container.CreateResponse, error) ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *ocispec.Platform, containerName string) (container.CreateResponse, error)
ContainerDiff(ctx context.Context, container string) ([]container.ContainerChangeResponseItem, error) ContainerDiff(ctx context.Context, container string) ([]container.FilesystemChange, error)
ContainerExecAttach(ctx context.Context, execID string, config types.ExecStartCheck) (types.HijackedResponse, error) ContainerExecAttach(ctx context.Context, execID string, config types.ExecStartCheck) (types.HijackedResponse, error)
ContainerExecCreate(ctx context.Context, container string, config types.ExecConfig) (types.IDResponse, error) ContainerExecCreate(ctx context.Context, container string, config types.ExecConfig) (types.IDResponse, error)
ContainerExecInspect(ctx context.Context, execID string) (types.ContainerExecInspect, error) ContainerExecInspect(ctx context.Context, execID string) (types.ContainerExecInspect, error)
@ -166,7 +166,7 @@ type SwarmAPIClient interface {
type SystemAPIClient interface { type SystemAPIClient interface {
Events(ctx context.Context, options types.EventsOptions) (<-chan events.Message, <-chan error) Events(ctx context.Context, options types.EventsOptions) (<-chan events.Message, <-chan error)
Info(ctx context.Context) (types.Info, error) Info(ctx context.Context) (types.Info, error)
RegistryLogin(ctx context.Context, auth types.AuthConfig) (registry.AuthenticateOKBody, error) RegistryLogin(ctx context.Context, auth registry.AuthConfig) (registry.AuthenticateOKBody, error)
DiskUsage(ctx context.Context, options types.DiskUsageOptions) (types.DiskUsage, error) DiskUsage(ctx context.Context, options types.DiskUsageOptions) (types.DiskUsage, error)
Ping(ctx context.Context) (types.Ping, error) Ping(ctx context.Context) (types.Ping, error)
} }
@ -176,7 +176,7 @@ type VolumeAPIClient interface {
VolumeCreate(ctx context.Context, options volume.CreateOptions) (volume.Volume, error) VolumeCreate(ctx context.Context, options volume.CreateOptions) (volume.Volume, error)
VolumeInspect(ctx context.Context, volumeID string) (volume.Volume, error) VolumeInspect(ctx context.Context, volumeID string) (volume.Volume, error)
VolumeInspectWithRaw(ctx context.Context, volumeID string) (volume.Volume, []byte, error) VolumeInspectWithRaw(ctx context.Context, volumeID string) (volume.Volume, []byte, error)
VolumeList(ctx context.Context, filter filters.Args) (volume.ListResponse, error) VolumeList(ctx context.Context, options volume.ListOptions) (volume.ListResponse, error)
VolumeRemove(ctx context.Context, volumeID string, force bool) error VolumeRemove(ctx context.Context, volumeID string, force bool) error
VolumesPrune(ctx context.Context, pruneFilter filters.Args) (types.VolumesPruneReport, error) VolumesPrune(ctx context.Context, pruneFilter filters.Args) (types.VolumesPruneReport, error)
VolumeUpdate(ctx context.Context, volumeID string, version swarm.Version, options volume.UpdateOptions) error VolumeUpdate(ctx context.Context, volumeID string, version swarm.Version, options volume.UpdateOptions) error

View file

@ -5,13 +5,12 @@ import (
"encoding/json" "encoding/json"
"net/url" "net/url"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/registry" "github.com/docker/docker/api/types/registry"
) )
// RegistryLogin authenticates the docker server with a given docker registry. // RegistryLogin authenticates the docker server with a given docker registry.
// It returns unauthorizedError when the authentication fails. // It returns unauthorizedError when the authentication fails.
func (cli *Client) RegistryLogin(ctx context.Context, auth types.AuthConfig) (registry.AuthenticateOKBody, error) { func (cli *Client) RegistryLogin(ctx context.Context, auth registry.AuthConfig) (registry.AuthenticateOKBody, error) {
resp, err := cli.post(ctx, "/auth", url.Values{}, auth, nil) resp, err := cli.post(ctx, "/auth", url.Values{}, auth, nil)
defer ensureReaderClosed(resp) defer ensureReaderClosed(resp)

View file

@ -64,10 +64,10 @@ func parsePingResponse(cli *Client, resp serverResponse) (types.Ping, error) {
ping.BuilderVersion = types.BuilderVersion(bv) ping.BuilderVersion = types.BuilderVersion(bv)
} }
if si := resp.header.Get("Swarm"); si != "" { if si := resp.header.Get("Swarm"); si != "" {
parts := strings.SplitN(si, "/", 2) state, role, _ := strings.Cut(si, "/")
ping.SwarmStatus = &swarm.Status{ ping.SwarmStatus = &swarm.Status{
NodeState: swarm.LocalNodeState(parts[0]), NodeState: swarm.LocalNodeState(state),
ControlAvailable: len(parts) == 2 && parts[1] == "manager", ControlAvailable: role == "manager",
} }
} }
err := cli.checkResponseErr(resp) err := cli.checkResponseErr(resp)

View file

@ -8,6 +8,7 @@ import (
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/registry"
"github.com/docker/docker/errdefs" "github.com/docker/docker/errdefs"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@ -67,12 +68,12 @@ func (cli *Client) PluginInstall(ctx context.Context, name string, options types
} }
func (cli *Client) tryPluginPrivileges(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) { func (cli *Client) tryPluginPrivileges(ctx context.Context, query url.Values, registryAuth string) (serverResponse, error) {
headers := map[string][]string{"X-Registry-Auth": {registryAuth}} headers := map[string][]string{registry.AuthHeader: {registryAuth}}
return cli.get(ctx, "/plugins/privileges", query, headers) return cli.get(ctx, "/plugins/privileges", query, headers)
} }
func (cli *Client) tryPluginPull(ctx context.Context, query url.Values, privileges types.PluginPrivileges, registryAuth string) (serverResponse, error) { func (cli *Client) tryPluginPull(ctx context.Context, query url.Values, privileges types.PluginPrivileges, registryAuth string) (serverResponse, error) {
headers := map[string][]string{"X-Registry-Auth": {registryAuth}} headers := map[string][]string{registry.AuthHeader: {registryAuth}}
return cli.post(ctx, "/plugins/pull", query, privileges, headers) return cli.post(ctx, "/plugins/pull", query, privileges, headers)
} }
@ -106,7 +107,7 @@ func (cli *Client) checkPluginPermissions(ctx context.Context, query url.Values,
return nil, err return nil, err
} }
if !accept { if !accept {
return nil, pluginPermissionDenied{options.RemoteRef} return nil, errors.Errorf("permission denied while installing plugin %s", options.RemoteRef)
} }
} }
return privileges, nil return privileges, nil

View file

@ -3,11 +3,13 @@ package client // import "github.com/docker/docker/client"
import ( import (
"context" "context"
"io" "io"
"github.com/docker/docker/api/types/registry"
) )
// PluginPush pushes a plugin to a registry // PluginPush pushes a plugin to a registry
func (cli *Client) PluginPush(ctx context.Context, name string, registryAuth string) (io.ReadCloser, error) { func (cli *Client) PluginPush(ctx context.Context, name string, registryAuth string) (io.ReadCloser, error) {
headers := map[string][]string{"X-Registry-Auth": {registryAuth}} headers := map[string][]string{registry.AuthHeader: {registryAuth}}
resp, err := cli.post(ctx, "/plugins/"+name+"/push", nil, nil, headers) resp, err := cli.post(ctx, "/plugins/"+name+"/push", nil, nil, headers)
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -7,6 +7,7 @@ import (
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/registry"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@ -34,6 +35,6 @@ func (cli *Client) PluginUpgrade(ctx context.Context, name string, options types
} }
func (cli *Client) tryPluginUpgrade(ctx context.Context, query url.Values, privileges types.PluginPrivileges, name, registryAuth string) (serverResponse, error) { func (cli *Client) tryPluginUpgrade(ctx context.Context, query url.Values, privileges types.PluginPrivileges, name, registryAuth string) (serverResponse, error) {
headers := map[string][]string{"X-Registry-Auth": {registryAuth}} headers := map[string][]string{registry.AuthHeader: {registryAuth}}
return cli.post(ctx, "/plugins/"+name+"/upgrade", query, privileges, headers) return cli.post(ctx, "/plugins/"+name+"/upgrade", query, privileges, headers)
} }

View file

@ -8,6 +8,7 @@ import (
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/registry"
"github.com/docker/docker/api/types/swarm" "github.com/docker/docker/api/types/swarm"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -21,7 +22,7 @@ func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec,
} }
if options.EncodedRegistryAuth != "" { if options.EncodedRegistryAuth != "" {
headers["X-Registry-Auth"] = []string{options.EncodedRegistryAuth} headers[registry.AuthHeader] = []string{options.EncodedRegistryAuth}
} }
// Make sure containerSpec is not nil when no runtime is set or the runtime is set to container // Make sure containerSpec is not nil when no runtime is set or the runtime is set to container

View file

@ -6,6 +6,7 @@ import (
"net/url" "net/url"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/registry"
"github.com/docker/docker/api/types/swarm" "github.com/docker/docker/api/types/swarm"
) )
@ -23,7 +24,7 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version
} }
if options.EncodedRegistryAuth != "" { if options.EncodedRegistryAuth != "" {
headers["X-Registry-Auth"] = []string{options.EncodedRegistryAuth} headers[registry.AuthHeader] = []string{options.EncodedRegistryAuth}
} }
if options.RegistryAuthFrom != "" { if options.RegistryAuthFrom != "" {

View file

@ -10,13 +10,13 @@ import (
) )
// VolumeList returns the volumes configured in the docker host. // VolumeList returns the volumes configured in the docker host.
func (cli *Client) VolumeList(ctx context.Context, filter filters.Args) (volume.ListResponse, error) { func (cli *Client) VolumeList(ctx context.Context, options volume.ListOptions) (volume.ListResponse, error) {
var volumes volume.ListResponse var volumes volume.ListResponse
query := url.Values{} query := url.Values{}
if filter.Len() > 0 { if options.Filters.Len() > 0 {
//nolint:staticcheck // ignore SA1019 for old code //nolint:staticcheck // ignore SA1019 for old code
filterJSON, err := filters.ToParamWithVersion(cli.version, filter) filterJSON, err := filters.ToParamWithVersion(cli.version, options.Filters)
if err != nil { if err != nil {
return volumes, err return volumes, err
} }

View file

@ -64,13 +64,14 @@ func stick(f string) error {
// GetDataHome returns XDG_DATA_HOME. // GetDataHome returns XDG_DATA_HOME.
// GetDataHome returns $HOME/.local/share and nil error if XDG_DATA_HOME is not set. // GetDataHome returns $HOME/.local/share and nil error if XDG_DATA_HOME is not set.
// If HOME and XDG_DATA_HOME are not set, getpwent(3) is consulted to determine the users home directory.
// //
// See also https://standards.freedesktop.org/basedir-spec/latest/ar01s03.html // See also https://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
func GetDataHome() (string, error) { func GetDataHome() (string, error) {
if xdgDataHome := os.Getenv("XDG_DATA_HOME"); xdgDataHome != "" { if xdgDataHome := os.Getenv("XDG_DATA_HOME"); xdgDataHome != "" {
return xdgDataHome, nil return xdgDataHome, nil
} }
home := os.Getenv("HOME") home := Get()
if home == "" { if home == "" {
return "", errors.New("could not get either XDG_DATA_HOME or HOME") return "", errors.New("could not get either XDG_DATA_HOME or HOME")
} }
@ -79,13 +80,14 @@ func GetDataHome() (string, error) {
// GetConfigHome returns XDG_CONFIG_HOME. // GetConfigHome returns XDG_CONFIG_HOME.
// GetConfigHome returns $HOME/.config and nil error if XDG_CONFIG_HOME is not set. // GetConfigHome returns $HOME/.config and nil error if XDG_CONFIG_HOME is not set.
// If HOME and XDG_CONFIG_HOME are not set, getpwent(3) is consulted to determine the users home directory.
// //
// See also https://standards.freedesktop.org/basedir-spec/latest/ar01s03.html // See also https://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
func GetConfigHome() (string, error) { func GetConfigHome() (string, error) {
if xdgConfigHome := os.Getenv("XDG_CONFIG_HOME"); xdgConfigHome != "" { if xdgConfigHome := os.Getenv("XDG_CONFIG_HOME"); xdgConfigHome != "" {
return xdgConfigHome, nil return xdgConfigHome, nil
} }
home := os.Getenv("HOME") home := Get()
if home == "" { if home == "" {
return "", errors.New("could not get either XDG_CONFIG_HOME or HOME") return "", errors.New("could not get either XDG_CONFIG_HOME or HOME")
} }
@ -93,8 +95,9 @@ func GetConfigHome() (string, error) {
} }
// GetLibHome returns $HOME/.local/lib // GetLibHome returns $HOME/.local/lib
// If HOME is not set, getpwent(3) is consulted to determine the users home directory.
func GetLibHome() (string, error) { func GetLibHome() (string, error) {
home := os.Getenv("HOME") home := Get()
if home == "" { if home == "" {
return "", errors.New("could not get HOME") return "", errors.New("could not get HOME")
} }

View file

@ -3,15 +3,11 @@ package ioutils // import "github.com/docker/docker/pkg/ioutils"
import ( import (
"context" "context"
"io" "io"
"runtime/debug"
"sync/atomic"
// make sure crypto.SHA256, crypto.sha512 and crypto.SHA384 are registered // make sure crypto.SHA256, crypto.sha512 and crypto.SHA384 are registered
// TODO remove once https://github.com/opencontainers/go-digest/pull/64 is merged. // TODO remove once https://github.com/opencontainers/go-digest/pull/64 is merged.
_ "crypto/sha256" _ "crypto/sha256"
_ "crypto/sha512" _ "crypto/sha512"
"github.com/sirupsen/logrus"
) )
// ReadCloserWrapper wraps an io.Reader, and implements an io.ReadCloser // ReadCloserWrapper wraps an io.Reader, and implements an io.ReadCloser
@ -20,15 +16,10 @@ import (
type ReadCloserWrapper struct { type ReadCloserWrapper struct {
io.Reader io.Reader
closer func() error closer func() error
closed atomic.Bool
} }
// Close calls back the passed closer function // Close calls back the passed closer function
func (r *ReadCloserWrapper) Close() error { func (r *ReadCloserWrapper) Close() error {
if !r.closed.CompareAndSwap(false, true) {
subsequentCloseWarn("ReadCloserWrapper")
return nil
}
return r.closer() return r.closer()
} }
@ -96,7 +87,6 @@ type cancelReadCloser struct {
cancel func() cancel func()
pR *io.PipeReader // Stream to read from pR *io.PipeReader // Stream to read from
pW *io.PipeWriter pW *io.PipeWriter
closed atomic.Bool
} }
// NewCancelReadCloser creates a wrapper that closes the ReadCloser when the // NewCancelReadCloser creates a wrapper that closes the ReadCloser when the
@ -156,17 +146,6 @@ func (p *cancelReadCloser) closeWithError(err error) {
// Close closes the wrapper its underlying reader. It will cause // Close closes the wrapper its underlying reader. It will cause
// future calls to Read to return io.EOF. // future calls to Read to return io.EOF.
func (p *cancelReadCloser) Close() error { func (p *cancelReadCloser) Close() error {
if !p.closed.CompareAndSwap(false, true) {
subsequentCloseWarn("cancelReadCloser")
return nil
}
p.closeWithError(io.EOF) p.closeWithError(io.EOF)
return nil return nil
} }
func subsequentCloseWarn(name string) {
logrus.Error("subsequent attempt to close " + name)
if logrus.GetLevel() >= logrus.DebugLevel {
logrus.Errorf("stack trace: %s", string(debug.Stack()))
}
}

View file

@ -1,11 +0,0 @@
//go:build !windows
// +build !windows
package ioutils // import "github.com/docker/docker/pkg/ioutils"
import "os"
// TempDir on Unix systems is equivalent to os.MkdirTemp.
func TempDir(dir, prefix string) (string, error) {
return os.MkdirTemp(dir, prefix)
}

View file

@ -1,16 +0,0 @@
package ioutils // import "github.com/docker/docker/pkg/ioutils"
import (
"os"
"github.com/docker/docker/pkg/longpath"
)
// TempDir is the equivalent of os.MkdirTemp, except that the result is in Windows longpath format.
func TempDir(dir, prefix string) (string, error) {
tempDir, err := os.MkdirTemp(dir, prefix)
if err != nil {
return "", err
}
return longpath.AddPrefix(tempDir), nil
}

View file

@ -0,0 +1,10 @@
package ioutils
import "github.com/docker/docker/pkg/longpath"
// TempDir is the equivalent of [os.MkdirTemp], except that on Windows
// the result is in Windows longpath format. On Unix systems it is
// equivalent to [os.MkdirTemp].
//
// Deprecated: use [longpath.MkdirTemp].
var TempDir = longpath.MkdirTemp

View file

@ -1,9 +1,6 @@
package ioutils // import "github.com/docker/docker/pkg/ioutils" package ioutils // import "github.com/docker/docker/pkg/ioutils"
import ( import "io"
"io"
"sync/atomic"
)
// NopWriter represents a type which write operation is nop. // NopWriter represents a type which write operation is nop.
type NopWriter struct{} type NopWriter struct{}
@ -32,14 +29,9 @@ func (f *NopFlusher) Flush() {}
type writeCloserWrapper struct { type writeCloserWrapper struct {
io.Writer io.Writer
closer func() error closer func() error
closed atomic.Bool
} }
func (r *writeCloserWrapper) Close() error { func (r *writeCloserWrapper) Close() error {
if !r.closed.CompareAndSwap(false, true) {
subsequentCloseWarn("WriteCloserWrapper")
return nil
}
return r.closer() return r.closer()
} }

View file

@ -1,17 +1,20 @@
// longpath introduces some constants and helper functions for handling long paths // Package longpath introduces some constants and helper functions for handling
// in Windows, which are expected to be prepended with `\\?\` and followed by either // long paths in Windows.
// a drive letter, a UNC server\share, or a volume identifier. //
// Long paths are expected to be prepended with "\\?\" and followed by either a
// drive letter, a UNC server\share, or a volume identifier.
package longpath // import "github.com/docker/docker/pkg/longpath" package longpath // import "github.com/docker/docker/pkg/longpath"
import ( import (
"os"
"runtime"
"strings" "strings"
) )
// Prefix is the longpath prefix for Windows file paths. // Prefix is the longpath prefix for Windows file paths.
const Prefix = `\\?\` const Prefix = `\\?\`
// AddPrefix will add the Windows long path prefix to the path provided if // AddPrefix adds the Windows long path prefix to the path provided if
// it does not already have it. // it does not already have it.
func AddPrefix(path string) string { func AddPrefix(path string) string {
if !strings.HasPrefix(path, Prefix) { if !strings.HasPrefix(path, Prefix) {
@ -24,3 +27,17 @@ func AddPrefix(path string) string {
} }
return path return path
} }
// MkdirTemp is the equivalent of [os.MkdirTemp], except that on Windows
// the result is in Windows longpath format. On Unix systems it is
// equivalent to [os.MkdirTemp].
func MkdirTemp(dir, prefix string) (string, error) {
tempDir, err := os.MkdirTemp(dir, prefix)
if err != nil {
return "", err
}
if runtime.GOOS != "windows" {
return tempDir, nil
}
return AddPrefix(tempDir), nil
}

View file

@ -59,13 +59,4 @@ const (
// AnnotationBaseImageName is the annotation key for the image reference of the image's base image. // AnnotationBaseImageName is the annotation key for the image reference of the image's base image.
AnnotationBaseImageName = "org.opencontainers.image.base.name" AnnotationBaseImageName = "org.opencontainers.image.base.name"
// AnnotationArtifactCreated is the annotation key for the date and time on which the artifact was built, conforming to RFC 3339.
AnnotationArtifactCreated = "org.opencontainers.artifact.created"
// AnnotationArtifactDescription is the annotation key for the human readable description for the artifact.
AnnotationArtifactDescription = "org.opencontainers.artifact.description"
// AnnotationReferrersFiltersApplied is the annotation key for the comma separated list of filters applied by the registry in the referrers listing.
AnnotationReferrersFiltersApplied = "org.opencontainers.referrers.filtersApplied"
) )

View file

@ -1,34 +0,0 @@
// Copyright 2022 The Linux Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1
// Artifact describes an artifact manifest.
// This structure provides `application/vnd.oci.artifact.manifest.v1+json` mediatype when marshalled to JSON.
type Artifact struct {
// MediaType is the media type of the object this schema refers to.
MediaType string `json:"mediaType"`
// ArtifactType is the IANA media type of the artifact this schema refers to.
ArtifactType string `json:"artifactType"`
// Blobs is a collection of blobs referenced by this manifest.
Blobs []Descriptor `json:"blobs,omitempty"`
// Subject (reference) is an optional link from the artifact to another manifest forming an association between the artifact and the other manifest.
Subject *Descriptor `json:"subject,omitempty"`
// Annotations contains arbitrary metadata for the artifact manifest.
Annotations map[string]string `json:"annotations,omitempty"`
}

View file

@ -49,13 +49,15 @@ type ImageConfig struct {
// StopSignal contains the system call signal that will be sent to the container to exit. // StopSignal contains the system call signal that will be sent to the container to exit.
StopSignal string `json:"StopSignal,omitempty"` StopSignal string `json:"StopSignal,omitempty"`
// ArgsEscaped `[Deprecated]` - This field is present only for legacy // ArgsEscaped
// compatibility with Docker and should not be used by new image builders. //
// It is used by Docker for Windows images to indicate that the `Entrypoint` // Deprecated: This field is present only for legacy compatibility with
// or `Cmd` or both, contains only a single element array, that is a // Docker and should not be used by new image builders. It is used by Docker
// pre-escaped, and combined into a single string `CommandLine`. If `true` // for Windows images to indicate that the `Entrypoint` or `Cmd` or both,
// the value in `Entrypoint` or `Cmd` should be used as-is to avoid double // contains only a single element array, that is a pre-escaped, and combined
// escaping. // into a single string `CommandLine`. If `true` the value in `Entrypoint` or
// `Cmd` should be used as-is to avoid double escaping.
// https://github.com/opencontainers/image-spec/pull/892
ArgsEscaped bool `json:"ArgsEscaped,omitempty"` ArgsEscaped bool `json:"ArgsEscaped,omitempty"`
} }
@ -95,22 +97,8 @@ type Image struct {
// Author defines the name and/or email address of the person or entity which created and is responsible for maintaining the image. // Author defines the name and/or email address of the person or entity which created and is responsible for maintaining the image.
Author string `json:"author,omitempty"` Author string `json:"author,omitempty"`
// Architecture is the CPU architecture which the binaries in this image are built to run on. // Platform describes the platform which the image in the manifest runs on.
Architecture string `json:"architecture"` Platform
// Variant is the variant of the specified CPU architecture which image binaries are intended to run on.
Variant string `json:"variant,omitempty"`
// OS is the name of the operating system which the image is built to run on.
OS string `json:"os"`
// OSVersion is an optional field specifying the operating system
// version, for example on Windows `10.0.14393.1066`.
OSVersion string `json:"os.version,omitempty"`
// OSFeatures is an optional field specifying an array of strings,
// each listing a required OS feature (for example on Windows `win32k`).
OSFeatures []string `json:"os.features,omitempty"`
// Config defines the execution parameters which should be used as a base when running a container using the image. // Config defines the execution parameters which should be used as a base when running a container using the image.
Config ImageConfig `json:"config,omitempty"` Config ImageConfig `json:"config,omitempty"`

View file

@ -21,7 +21,7 @@ import digest "github.com/opencontainers/go-digest"
// when marshalled to JSON. // when marshalled to JSON.
type Descriptor struct { type Descriptor struct {
// MediaType is the media type of the object this schema refers to. // MediaType is the media type of the object this schema refers to.
MediaType string `json:"mediaType,omitempty"` MediaType string `json:"mediaType"`
// Digest is the digest of the targeted content. // Digest is the digest of the targeted content.
Digest digest.Digest `json:"digest"` Digest digest.Digest `json:"digest"`
@ -52,7 +52,7 @@ type Descriptor struct {
// Platform describes the platform which the image in the manifest runs on. // Platform describes the platform which the image in the manifest runs on.
type Platform struct { type Platform struct {
// Architecture field specifies the CPU architecture, for example // Architecture field specifies the CPU architecture, for example
// `amd64` or `ppc64`. // `amd64` or `ppc64le`.
Architecture string `json:"architecture"` Architecture string `json:"architecture"`
// OS specifies the operating system, for example `linux` or `windows`. // OS specifies the operating system, for example `linux` or `windows`.
@ -70,3 +70,11 @@ type Platform struct {
// example `v7` to specify ARMv7 when architecture is `arm`. // example `v7` to specify ARMv7 when architecture is `arm`.
Variant string `json:"variant,omitempty"` Variant string `json:"variant,omitempty"`
} }
// DescriptorEmptyJSON is the descriptor of a blob with content of `{}`.
var DescriptorEmptyJSON = Descriptor{
MediaType: MediaTypeEmptyJSON,
Digest: `sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a`,
Size: 2,
Data: []byte(`{}`),
}

View file

@ -24,9 +24,15 @@ type Index struct {
// MediaType specifies the type of this document data structure e.g. `application/vnd.oci.image.index.v1+json` // MediaType specifies the type of this document data structure e.g. `application/vnd.oci.image.index.v1+json`
MediaType string `json:"mediaType,omitempty"` MediaType string `json:"mediaType,omitempty"`
// ArtifactType specifies the IANA media type of artifact when the manifest is used for an artifact.
ArtifactType string `json:"artifactType,omitempty"`
// Manifests references platform specific manifests. // Manifests references platform specific manifests.
Manifests []Descriptor `json:"manifests"` Manifests []Descriptor `json:"manifests"`
// Subject is an optional link from the image manifest to another manifest forming an association between the image manifest and the other manifest.
Subject *Descriptor `json:"subject,omitempty"`
// Annotations contains arbitrary metadata for the image index. // Annotations contains arbitrary metadata for the image index.
Annotations map[string]string `json:"annotations,omitempty"` Annotations map[string]string `json:"annotations,omitempty"`
} }

View file

@ -15,10 +15,14 @@
package v1 package v1
const ( const (
// ImageLayoutFile is the file name of oci image layout file // ImageLayoutFile is the file name containing ImageLayout in an OCI Image Layout
ImageLayoutFile = "oci-layout" ImageLayoutFile = "oci-layout"
// ImageLayoutVersion is the version of ImageLayout // ImageLayoutVersion is the version of ImageLayout
ImageLayoutVersion = "1.0.0" ImageLayoutVersion = "1.0.0"
// ImageIndexFile is the file name of the entry point for references and descriptors in an OCI Image Layout
ImageIndexFile = "index.json"
// ImageBlobsDir is the directory name containing content addressable blobs in an OCI Image Layout
ImageBlobsDir = "blobs"
) )
// ImageLayout is the structure in the "oci-layout" file, found in the root // ImageLayout is the structure in the "oci-layout" file, found in the root

View file

@ -23,6 +23,9 @@ type Manifest struct {
// MediaType specifies the type of this document data structure e.g. `application/vnd.oci.image.manifest.v1+json` // MediaType specifies the type of this document data structure e.g. `application/vnd.oci.image.manifest.v1+json`
MediaType string `json:"mediaType,omitempty"` MediaType string `json:"mediaType,omitempty"`
// ArtifactType specifies the IANA media type of artifact when the manifest is used for an artifact.
ArtifactType string `json:"artifactType,omitempty"`
// Config references a configuration object for a container, by digest. // Config references a configuration object for a container, by digest.
// The referenced configuration object is a JSON blob that the runtime uses to set up the container. // The referenced configuration object is a JSON blob that the runtime uses to set up the container.
Config Descriptor `json:"config"` Config Descriptor `json:"config"`

View file

@ -21,12 +21,20 @@ const (
// MediaTypeLayoutHeader specifies the media type for the oci-layout. // MediaTypeLayoutHeader specifies the media type for the oci-layout.
MediaTypeLayoutHeader = "application/vnd.oci.layout.header.v1+json" MediaTypeLayoutHeader = "application/vnd.oci.layout.header.v1+json"
// MediaTypeImageManifest specifies the media type for an image manifest.
MediaTypeImageManifest = "application/vnd.oci.image.manifest.v1+json"
// MediaTypeImageIndex specifies the media type for an image index. // MediaTypeImageIndex specifies the media type for an image index.
MediaTypeImageIndex = "application/vnd.oci.image.index.v1+json" MediaTypeImageIndex = "application/vnd.oci.image.index.v1+json"
// MediaTypeImageManifest specifies the media type for an image manifest.
MediaTypeImageManifest = "application/vnd.oci.image.manifest.v1+json"
// MediaTypeImageConfig specifies the media type for the image configuration.
MediaTypeImageConfig = "application/vnd.oci.image.config.v1+json"
// MediaTypeEmptyJSON specifies the media type for an unused blob containing the value "{}".
MediaTypeEmptyJSON = "application/vnd.oci.empty.v1+json"
)
const (
// MediaTypeImageLayer is the media type used for layers referenced by the manifest. // MediaTypeImageLayer is the media type used for layers referenced by the manifest.
MediaTypeImageLayer = "application/vnd.oci.image.layer.v1.tar" MediaTypeImageLayer = "application/vnd.oci.image.layer.v1.tar"
@ -37,24 +45,41 @@ const (
// MediaTypeImageLayerZstd is the media type used for zstd compressed // MediaTypeImageLayerZstd is the media type used for zstd compressed
// layers referenced by the manifest. // layers referenced by the manifest.
MediaTypeImageLayerZstd = "application/vnd.oci.image.layer.v1.tar+zstd" MediaTypeImageLayerZstd = "application/vnd.oci.image.layer.v1.tar+zstd"
)
// Non-distributable layer media-types.
//
// Deprecated: Non-distributable layers are deprecated, and not recommended
// for future use. Implementations SHOULD NOT produce new non-distributable
// layers.
// https://github.com/opencontainers/image-spec/pull/965
const (
// MediaTypeImageLayerNonDistributable is the media type for layers referenced by // MediaTypeImageLayerNonDistributable is the media type for layers referenced by
// the manifest but with distribution restrictions. // the manifest but with distribution restrictions.
//
// Deprecated: Non-distributable layers are deprecated, and not recommended
// for future use. Implementations SHOULD NOT produce new non-distributable
// layers.
// https://github.com/opencontainers/image-spec/pull/965
MediaTypeImageLayerNonDistributable = "application/vnd.oci.image.layer.nondistributable.v1.tar" MediaTypeImageLayerNonDistributable = "application/vnd.oci.image.layer.nondistributable.v1.tar"
// MediaTypeImageLayerNonDistributableGzip is the media type for // MediaTypeImageLayerNonDistributableGzip is the media type for
// gzipped layers referenced by the manifest but with distribution // gzipped layers referenced by the manifest but with distribution
// restrictions. // restrictions.
//
// Deprecated: Non-distributable layers are deprecated, and not recommended
// for future use. Implementations SHOULD NOT produce new non-distributable
// layers.
// https://github.com/opencontainers/image-spec/pull/965
MediaTypeImageLayerNonDistributableGzip = "application/vnd.oci.image.layer.nondistributable.v1.tar+gzip" MediaTypeImageLayerNonDistributableGzip = "application/vnd.oci.image.layer.nondistributable.v1.tar+gzip"
// MediaTypeImageLayerNonDistributableZstd is the media type for zstd // MediaTypeImageLayerNonDistributableZstd is the media type for zstd
// compressed layers referenced by the manifest but with distribution // compressed layers referenced by the manifest but with distribution
// restrictions. // restrictions.
//
// Deprecated: Non-distributable layers are deprecated, and not recommended
// for future use. Implementations SHOULD NOT produce new non-distributable
// layers.
// https://github.com/opencontainers/image-spec/pull/965
MediaTypeImageLayerNonDistributableZstd = "application/vnd.oci.image.layer.nondistributable.v1.tar+zstd" MediaTypeImageLayerNonDistributableZstd = "application/vnd.oci.image.layer.nondistributable.v1.tar+zstd"
// MediaTypeImageConfig specifies the media type for the image configuration.
MediaTypeImageConfig = "application/vnd.oci.image.config.v1+json"
// MediaTypeArtifactManifest specifies the media type for a content descriptor.
MediaTypeArtifactManifest = "application/vnd.oci.artifact.manifest.v1+json"
) )

View file

@ -25,7 +25,7 @@ const (
VersionPatch = 0 VersionPatch = 0
// VersionDev indicates development branch. Releases will be empty string. // VersionDev indicates development branch. Releases will be empty string.
VersionDev = "-dev" VersionDev = ""
) )
// Version is the specification version that the package types support. // Version is the specification version that the package types support.

8
vendor/modules.txt vendored
View file

@ -14,7 +14,7 @@ github.com/cloudfoundry/jibber_jabber
# github.com/davecgh/go-spew v1.1.1 # github.com/davecgh/go-spew v1.1.1
## explicit ## explicit
github.com/davecgh/go-spew/spew github.com/davecgh/go-spew/spew
# github.com/docker/cli v23.0.10+incompatible # github.com/docker/cli v24.0.7+incompatible
## explicit ## explicit
github.com/docker/cli/cli/config github.com/docker/cli/cli/config
github.com/docker/cli/cli/config/configfile github.com/docker/cli/cli/config/configfile
@ -30,7 +30,7 @@ github.com/docker/cli/cli/context/store
## explicit ## explicit
github.com/docker/distribution/digestset github.com/docker/distribution/digestset
github.com/docker/distribution/reference github.com/docker/distribution/reference
# github.com/docker/docker v23.0.10+incompatible # github.com/docker/docker v24.0.7+incompatible
## explicit ## explicit
github.com/docker/docker/api github.com/docker/docker/api
github.com/docker/docker/api/types github.com/docker/docker/api/types
@ -184,8 +184,8 @@ github.com/mgutz/str
# github.com/opencontainers/go-digest v1.0.0 # github.com/opencontainers/go-digest v1.0.0
## explicit; go 1.13 ## explicit; go 1.13
github.com/opencontainers/go-digest github.com/opencontainers/go-digest
# github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b # github.com/opencontainers/image-spec v1.1.0
## explicit; go 1.17 ## explicit; go 1.18
github.com/opencontainers/image-spec/specs-go github.com/opencontainers/image-spec/specs-go
github.com/opencontainers/image-spec/specs-go/v1 github.com/opencontainers/image-spec/specs-go/v1
# github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 # github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5