Compare commits

..

11 Commits

Author SHA1 Message Date
4debf411d1 Merge pull request #4857 from thaJeztah/25.0_backport_codecov-action-4
Some checks failed
build / prepare (push) Has been cancelled
build / build (push) Has been cancelled
build / bin-image (push) Has been cancelled
build / prepare-plugins (push) Has been cancelled
build / plugins (push) Has been cancelled
codeql / codeql (push) Has been cancelled
e2e / e2e (19.03-dind, non-experimental) (push) Has been cancelled
e2e / e2e (alpine, stable-dind, connhelper-ssh) (push) Has been cancelled
e2e / e2e (alpine, stable-dind, experimental) (push) Has been cancelled
e2e / e2e (alpine, stable-dind, non-experimental) (push) Has been cancelled
e2e / e2e (debian, stable-dind, connhelper-ssh) (push) Has been cancelled
e2e / e2e (debian, stable-dind, experimental) (push) Has been cancelled
e2e / e2e (debian, stable-dind, non-experimental) (push) Has been cancelled
test / ctn (push) Has been cancelled
test / host (macos-12) (push) Has been cancelled
validate / validate (lint) (push) Has been cancelled
validate / validate (shellcheck) (push) Has been cancelled
validate / validate (update-authors) (push) Has been cancelled
validate / validate (validate-vendor) (push) Has been cancelled
validate / validate-md (push) Has been cancelled
validate / validate-make (manpages) (push) Has been cancelled
validate / validate-make (yamldocs) (push) Has been cancelled
[25.0 backport] build(deps): Bump codecov/codecov-action from 3 to 4
2024-02-06 21:42:40 +01:00
5e6ce1bde1 Merge pull request #4856 from thaJeztah/25.0_backport_plugin-socket-tests
[25.0 backport] Add tests for CLI/plugin communication
2024-02-06 21:42:20 +01:00
5428301e3f build(deps): Bump codecov/codecov-action from 3 to 4
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3 to 4.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit b123ce6526)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-02-06 21:35:08 +01:00
1cbc218c05 tests: add plugin-socket-compatibility tests
Adds a new plugin to the e2e plugins that simulates an older
plugin binary and a test suite to ensure older plugin binaries
keep behaving the same with newer CLI versions.

Signed-off-by: Laura Brehm <laurabrehm@hey.com>
(cherry picked from commit cfa9fef77d)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-02-06 21:31:55 +01:00
2f6b5ada71 scripts: don't hardcode architecture in e2e script
Signed-off-by: Laura Brehm <laurabrehm@hey.com>
(cherry picked from commit 1c4d6d85dd)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-02-06 21:31:55 +01:00
d8e07c9c47 tests: add tests for cli-plugins/socket
Signed-off-by: Laura Brehm <laurabrehm@hey.com>
(cherry picked from commit 469bfc05ed)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-02-06 21:31:52 +01:00
5f1b610fc3 Merge pull request #4841 from thaJeztah/25.0_vendor_docker_25.0.2
[25.0] vendor: github.com/docker/docker v25.0.2
2024-02-01 16:32:18 +01:00
c105cd3ac2 Merge pull request #4837 from dvdksn/25.0_docs_backport_linode_volume_plugin
[25.0 Backport] docs: Add Linode docker volume plugin #4396
2024-02-01 04:15:42 +01:00
62b2963b80 vendor: github.com/docker/docker v25.0.2
no changes in vendored code

full diff: https://github.com/docker/docker/compare/v25.0.1...v25.0.2

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-02-01 04:12:31 +01:00
71f2b0d109 vendor: github.com/docker/docker v25.0.1
relevant changes:

- Fix isGitURL regular expression
- pkg/system: return even richer xattr errors

full diff: https://github.com/moby/moby/compare/v25.0.0...v25.0.1

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 4b1ed1f442)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-02-01 04:11:47 +01:00
617bc98c8d Add Linode docker volume plugin
Signed-off-by: Zhiwei Liang <zliang@akamai.com>
(cherry picked from commit 1f9573bb05)
Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
2024-01-31 13:06:53 +01:00
13 changed files with 526 additions and 16 deletions

View File

@ -59,6 +59,6 @@ jobs:
TESTFLAGS: -coverprofile=/tmp/coverage/coverage.txt
-
name: Send to Codecov
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v4
with:
file: ./build/coverage/coverage.txt

View File

@ -31,7 +31,7 @@ jobs:
targets: test-coverage
-
name: Send to Codecov
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v4
with:
file: ./build/coverage/coverage.txt
@ -73,7 +73,7 @@ jobs:
shell: bash
-
name: Send to Codecov
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v4
with:
file: /tmp/coverage.txt
working-directory: ${{ env.GOPATH }}/src/github.com/docker/cli

View File

@ -0,0 +1,133 @@
package socket
import (
"io/fs"
"net"
"os"
"runtime"
"strings"
"testing"
"time"
"gotest.tools/v3/assert"
"gotest.tools/v3/poll"
)
func TestSetupConn(t *testing.T) {
t.Run("updates conn when connected", func(t *testing.T) {
var conn *net.UnixConn
listener, err := SetupConn(&conn)
assert.NilError(t, err)
assert.Check(t, listener != nil, "returned nil listener but no error")
addr, err := net.ResolveUnixAddr("unix", listener.Addr().String())
assert.NilError(t, err, "failed to resolve listener address")
_, err = net.DialUnix("unix", nil, addr)
assert.NilError(t, err, "failed to dial returned listener")
pollConnNotNil(t, &conn)
})
t.Run("allows reconnects", func(t *testing.T) {
var conn *net.UnixConn
listener, err := SetupConn(&conn)
assert.NilError(t, err)
assert.Check(t, listener != nil, "returned nil listener but no error")
addr, err := net.ResolveUnixAddr("unix", listener.Addr().String())
assert.NilError(t, err, "failed to resolve listener address")
otherConn, err := net.DialUnix("unix", nil, addr)
assert.NilError(t, err, "failed to dial returned listener")
otherConn.Close()
_, err = net.DialUnix("unix", nil, addr)
assert.NilError(t, err, "failed to redial listener")
})
t.Run("does not leak sockets to local directory", func(t *testing.T) {
var conn *net.UnixConn
listener, err := SetupConn(&conn)
assert.NilError(t, err)
assert.Check(t, listener != nil, "returned nil listener but no error")
checkDirNoPluginSocket(t)
addr, err := net.ResolveUnixAddr("unix", listener.Addr().String())
assert.NilError(t, err, "failed to resolve listener address")
_, err = net.DialUnix("unix", nil, addr)
assert.NilError(t, err, "failed to dial returned listener")
checkDirNoPluginSocket(t)
})
}
func checkDirNoPluginSocket(t *testing.T) {
t.Helper()
files, err := os.ReadDir(".")
assert.NilError(t, err, "failed to list files in dir to check for leaked sockets")
for _, f := range files {
info, err := f.Info()
assert.NilError(t, err, "failed to check file info")
// check for a socket with `docker_cli_` in the name (from `SetupConn()`)
if strings.Contains(f.Name(), "docker_cli_") && info.Mode().Type() == fs.ModeSocket {
t.Fatal("found socket in a local directory")
}
}
}
func TestConnectAndWait(t *testing.T) {
t.Run("calls cancel func on EOF", func(t *testing.T) {
var conn *net.UnixConn
listener, err := SetupConn(&conn)
assert.NilError(t, err, "failed to setup listener")
done := make(chan struct{})
t.Setenv(EnvKey, listener.Addr().String())
cancelFunc := func() {
done <- struct{}{}
}
ConnectAndWait(cancelFunc)
pollConnNotNil(t, &conn)
conn.Close()
select {
case <-done:
case <-time.After(10 * time.Millisecond):
t.Fatal("cancel function not closed after 10ms")
}
})
// TODO: this test cannot be executed with `t.Parallel()`, due to
// relying on goroutine numbers to ensure correct behaviour
t.Run("connect goroutine exits after EOF", func(t *testing.T) {
var conn *net.UnixConn
listener, err := SetupConn(&conn)
assert.NilError(t, err, "failed to setup listener")
t.Setenv(EnvKey, listener.Addr().String())
numGoroutines := runtime.NumGoroutine()
ConnectAndWait(func() {})
assert.Equal(t, runtime.NumGoroutine(), numGoroutines+1)
pollConnNotNil(t, &conn)
conn.Close()
poll.WaitOn(t, func(t poll.LogT) poll.Result {
if runtime.NumGoroutine() > numGoroutines+1 {
return poll.Continue("waiting for connect goroutine to exit")
}
return poll.Success()
}, poll.WithDelay(1*time.Millisecond), poll.WithTimeout(10*time.Millisecond))
})
}
func pollConnNotNil(t *testing.T, conn **net.UnixConn) {
t.Helper()
poll.WaitOn(t, func(t poll.LogT) poll.Result {
if *conn == nil {
return poll.Continue("waiting for conn to not be nil")
}
return poll.Success()
}, poll.WithDelay(1*time.Millisecond), poll.WithTimeout(10*time.Millisecond))
}

View File

@ -60,6 +60,7 @@ The sections below provide an overview of available third-party plugins.
| [Infinit volume plugin](https://infinit.sh/documentation/docker/volume-plugin) | A volume plugin that makes it easy to mount and manage Infinit volumes using Docker. |
| [IPFS Volume Plugin](https://github.com/vdemeester/docker-volume-ipfs) | An open source volume plugin that allows using an [ipfs](https://ipfs.io/) filesystem as a volume. |
| [Keywhiz plugin](https://github.com/calavera/docker-volume-keywhiz) | A plugin that provides credentials and secret management using Keywhiz as a central repository. |
| [Linode Volume Plugin](https://github.com/linode/docker-volume-linode) | A plugin that adds the ability to manage Linode Block Storage as Docker Volumes from within a Linode. |
| [Local Persist Plugin](https://github.com/CWSpear/local-persist) | A volume plugin that extends the default `local` driver's functionality by allowing you specify a mountpoint anywhere on the host, which enables the files to *always persist*, even if the volume is removed via `docker volume rm`. |
| [NetApp Plugin](https://github.com/NetApp/netappdvp) (nDVP) | A volume plugin that provides direct integration with the Docker ecosystem for the NetApp storage portfolio. The nDVP package supports the provisioning and management of storage resources from the storage platform to Docker hosts, with a robust framework for adding additional platforms in the future. |
| [Netshare plugin](https://github.com/ContainX/docker-volume-netshare) | A volume plugin that provides volume management for NFS 3/4, AWS EFS and CIFS file systems. |

View File

@ -0,0 +1,123 @@
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
"time"
"github.com/docker/cli/cli-plugins/manager"
"github.com/docker/cli/cli-plugins/plugin"
"github.com/docker/cli/cli/command"
"github.com/spf13/cobra"
)
func main() {
plugin.Run(RootCmd, manager.Metadata{
SchemaVersion: "0.1.0",
Vendor: "Docker Inc.",
Version: "test",
})
}
func RootCmd(dockerCli command.Cli) *cobra.Command {
cmd := cobra.Command{
Use: "presocket",
Short: "testing plugin that does not connect to the socket",
// override PersistentPreRunE so that the plugin default
// PersistentPreRunE doesn't run, simulating a plugin built
// with a pre-socket-communication version of the CLI
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return nil
},
}
cmd.AddCommand(&cobra.Command{
Use: "test-no-socket",
Short: "test command that runs until it receives a SIGINT",
RunE: func(cmd *cobra.Command, args []string) error {
go func() {
<-cmd.Context().Done()
fmt.Fprintln(dockerCli.Out(), "context cancelled")
os.Exit(2)
}()
signalCh := make(chan os.Signal, 10)
signal.Notify(signalCh, syscall.SIGINT, syscall.SIGTERM)
go func() {
for range signalCh {
fmt.Fprintln(dockerCli.Out(), "received SIGINT")
}
}()
<-time.After(3 * time.Second)
fmt.Fprintln(dockerCli.Err(), "exit after 3 seconds")
return nil
},
})
cmd.AddCommand(&cobra.Command{
Use: "test-socket",
Short: "test command that runs until it receives a SIGINT",
PreRunE: func(cmd *cobra.Command, args []string) error {
return plugin.PersistentPreRunE(cmd, args)
},
RunE: func(cmd *cobra.Command, args []string) error {
go func() {
<-cmd.Context().Done()
fmt.Fprintln(dockerCli.Out(), "context cancelled")
os.Exit(2)
}()
signalCh := make(chan os.Signal, 10)
signal.Notify(signalCh, syscall.SIGINT, syscall.SIGTERM)
go func() {
for range signalCh {
fmt.Fprintln(dockerCli.Out(), "received SIGINT")
}
}()
<-time.After(3 * time.Second)
fmt.Fprintln(dockerCli.Err(), "exit after 3 seconds")
return nil
},
})
cmd.AddCommand(&cobra.Command{
Use: "test-socket-ignore-context",
Short: "test command that runs until it receives a SIGINT",
PreRunE: func(cmd *cobra.Command, args []string) error {
return plugin.PersistentPreRunE(cmd, args)
},
RunE: func(cmd *cobra.Command, args []string) error {
signalCh := make(chan os.Signal, 10)
signal.Notify(signalCh, syscall.SIGINT, syscall.SIGTERM)
go func() {
for range signalCh {
fmt.Fprintln(dockerCli.Out(), "received SIGINT")
}
}()
<-time.After(3 * time.Second)
fmt.Fprintln(dockerCli.Err(), "exit after 3 seconds")
return nil
},
})
cmd.AddCommand(&cobra.Command{
Use: "tty",
Short: "test command that attempts to read from the TTY",
RunE: func(cmd *cobra.Command, args []string) error {
done := make(chan struct{})
go func() {
b := make([]byte, 1)
_, _ = dockerCli.In().Read(b)
done <- struct{}{}
}()
select {
case <-done:
case <-time.After(2 * time.Second):
fmt.Fprint(dockerCli.Err(), "timeout after 2 seconds")
}
return nil
},
})
return &cmd
}

View File

@ -0,0 +1,235 @@
package cliplugins
import (
"bytes"
"io"
"os/exec"
"strings"
"syscall"
"testing"
"time"
"github.com/creack/pty"
"gotest.tools/v3/assert"
)
// TestPluginSocketBackwardsCompatible executes a plugin binary
// that does not connect to the CLI plugin socket, simulating
// a plugin compiled against an older version of the CLI, and
// ensures that backwards compatibility is maintained.
func TestPluginSocketBackwardsCompatible(t *testing.T) {
run, _, cleanup := prepare(t)
defer cleanup()
t.Run("attached", func(t *testing.T) {
t.Run("the plugin gets signalled if attached to a TTY", func(t *testing.T) {
cmd := run("presocket", "test-no-socket")
command := exec.Command(cmd.Command[0], cmd.Command[1:]...)
ptmx, err := pty.Start(command)
assert.NilError(t, err, "failed to launch command with fake TTY")
// send a SIGINT to the process group after 1 second, since
// we're simulating an "attached TTY" scenario and a TTY would
// send a signal to the process group
go func() {
<-time.After(time.Second)
err := syscall.Kill(-command.Process.Pid, syscall.SIGINT)
assert.NilError(t, err, "failed to signal process group")
}()
bytes, err := io.ReadAll(ptmx)
if err != nil && !strings.Contains(err.Error(), "input/output error") {
t.Fatal("failed to get command output")
}
// the plugin is attached to the TTY, so the parent process
// ignores the received signal, and the plugin receives a SIGINT
// as well
assert.Equal(t, string(bytes), "received SIGINT\r\nexit after 3 seconds\r\n")
})
// ensure that we don't break plugins that attempt to read from the TTY
// (see: https://github.com/moby/moby/issues/47073)
// (remove me if/when we decide to break compatibility here)
t.Run("the plugin can read from the TTY", func(t *testing.T) {
cmd := run("presocket", "tty")
command := exec.Command(cmd.Command[0], cmd.Command[1:]...)
ptmx, err := pty.Start(command)
assert.NilError(t, err, "failed to launch command with fake TTY")
_, _ = ptmx.Write([]byte("hello!"))
done := make(chan error)
go func() {
<-time.After(time.Second)
_, err := io.ReadAll(ptmx)
done <- err
}()
select {
case cmdErr := <-done:
if cmdErr != nil && !strings.Contains(cmdErr.Error(), "input/output error") {
t.Fatal("failed to get command output")
}
case <-time.After(5 * time.Second):
t.Fatal("timed out! plugin process probably stuck")
}
})
})
t.Run("detached", func(t *testing.T) {
t.Run("the plugin does not get signalled", func(t *testing.T) {
cmd := run("presocket", "test-no-socket")
command := exec.Command(cmd.Command[0], cmd.Command[1:]...)
t.Log(strings.Join(command.Args, " "))
command.SysProcAttr = &syscall.SysProcAttr{
Setpgid: true,
}
go func() {
<-time.After(time.Second)
// we're signalling the parent process directly and not
// the process group, since we're testing the case where
// the process is detached and not simulating a CTRL-C
// from a TTY
err := syscall.Kill(command.Process.Pid, syscall.SIGINT)
assert.NilError(t, err, "failed to signal process group")
}()
bytes, err := command.CombinedOutput()
t.Log("command output: " + string(bytes))
assert.NilError(t, err, "failed to run command")
// the plugin process does not receive a SIGINT
// so it exits after 3 seconds and prints this message
assert.Equal(t, string(bytes), "exit after 3 seconds\n")
})
t.Run("the main CLI exits after 3 signals", func(t *testing.T) {
cmd := run("presocket", "test-no-socket")
command := exec.Command(cmd.Command[0], cmd.Command[1:]...)
t.Log(strings.Join(command.Args, " "))
command.SysProcAttr = &syscall.SysProcAttr{
Setpgid: true,
}
go func() {
<-time.After(time.Second)
// we're signalling the parent process directly and not
// the process group, since we're testing the case where
// the process is detached and not simulating a CTRL-C
// from a TTY
err := syscall.Kill(command.Process.Pid, syscall.SIGINT)
assert.NilError(t, err, "failed to signal process group")
// TODO: look into CLI signal handling, it's currently necessary
// to add a short delay between each signal in order for the CLI
// process to consistently pick them all up.
time.Sleep(50 * time.Millisecond)
err = syscall.Kill(command.Process.Pid, syscall.SIGINT)
assert.NilError(t, err, "failed to signal process group")
time.Sleep(50 * time.Millisecond)
err = syscall.Kill(command.Process.Pid, syscall.SIGINT)
assert.NilError(t, err, "failed to signal process group")
}()
bytes, err := command.CombinedOutput()
assert.ErrorContains(t, err, "exit status 1")
// the plugin process does not receive a SIGINT and does
// the CLI cannot cancel it over the socket, so it kills
// the plugin process and forcefully exits
assert.Equal(t, string(bytes), "got 3 SIGTERM/SIGINTs, forcefully exiting\n")
})
})
}
func TestPluginSocketCommunication(t *testing.T) {
run, _, cleanup := prepare(t)
defer cleanup()
t.Run("attached", func(t *testing.T) {
t.Run("the socket is not closed + the plugin receives a signal due to pgid", func(t *testing.T) {
cmd := run("presocket", "test-socket")
command := exec.Command(cmd.Command[0], cmd.Command[1:]...)
ptmx, err := pty.Start(command)
assert.NilError(t, err, "failed to launch command with fake TTY")
// send a SIGINT to the process group after 1 second, since
// we're simulating an "attached TTY" scenario and a TTY would
// send a signal to the process group
go func() {
<-time.After(time.Second)
err := syscall.Kill(-command.Process.Pid, syscall.SIGINT)
assert.NilError(t, err, "failed to signal process group")
}()
bytes, err := io.ReadAll(ptmx)
if err != nil && !strings.Contains(err.Error(), "input/output error") {
t.Fatal("failed to get command output")
}
// the plugin is attached to the TTY, so the parent process
// ignores the received signal, and the plugin receives a SIGINT
// as well
assert.Equal(t, string(bytes), "received SIGINT\r\nexit after 3 seconds\r\n")
})
})
t.Run("detached", func(t *testing.T) {
t.Run("the plugin does not get signalled", func(t *testing.T) {
cmd := run("presocket", "test-socket")
command := exec.Command(cmd.Command[0], cmd.Command[1:]...)
outB := bytes.Buffer{}
command.Stdout = &outB
command.Stderr = &outB
command.SysProcAttr = &syscall.SysProcAttr{
Setpgid: true,
}
// send a SIGINT to the process group after 1 second
go func() {
<-time.After(time.Second)
err := syscall.Kill(command.Process.Pid, syscall.SIGINT)
assert.NilError(t, err, "failed to signal CLI process")
}()
err := command.Run()
t.Log(outB.String())
assert.ErrorContains(t, err, "exit status 2")
// the plugin does not get signalled, but it does get it's
// context cancelled by the CLI through the socket
assert.Equal(t, outB.String(), "context cancelled\n")
})
t.Run("the main CLI exits after 3 signals", func(t *testing.T) {
cmd := run("presocket", "test-socket-ignore-context")
command := exec.Command(cmd.Command[0], cmd.Command[1:]...)
command.SysProcAttr = &syscall.SysProcAttr{
Setpgid: true,
}
go func() {
<-time.After(time.Second)
// we're signalling the parent process directly and not
// the process group, since we're testing the case where
// the process is detached and not simulating a CTRL-C
// from a TTY
err := syscall.Kill(command.Process.Pid, syscall.SIGINT)
assert.NilError(t, err, "failed to signal CLI process")
// TODO: same as above TODO, CLI signal handling is not consistent
// with multiple signals without intervals
time.Sleep(50 * time.Millisecond)
err = syscall.Kill(command.Process.Pid, syscall.SIGINT)
assert.NilError(t, err, "failed to signal CLI process")
time.Sleep(50 * time.Millisecond)
err = syscall.Kill(command.Process.Pid, syscall.SIGINT)
assert.NilError(t, err, "failed to signal CLI process§")
}()
bytes, err := command.CombinedOutput()
assert.ErrorContains(t, err, "exit status 1")
// the plugin process does not receive a SIGINT and does
// not exit after having it's context cancelled, so the CLI
// kills the plugin process and forcefully exits
assert.Equal(t, string(bytes), "got 3 SIGTERM/SIGINTs, forcefully exiting\n")
})
})
}

View File

@ -2,6 +2,8 @@
# Run integration tests against the latest docker-ce dind
set -eu -o pipefail
source ./scripts/build/.variables
container_ip() {
local cid=$1
local network=$2
@ -69,7 +71,7 @@ runtests() {
GOPATH="$GOPATH" \
PATH="$PWD/build/:/usr/bin:/usr/local/bin:/usr/local/go/bin" \
HOME="$HOME" \
DOCKER_CLI_E2E_PLUGINS_EXTRA_DIRS="$PWD/build/plugins-linux-amd64" \
DOCKER_CLI_E2E_PLUGINS_EXTRA_DIRS="$PWD/build/plugins-linux-${GOARCH}" \
GO111MODULE=auto \
"$(command -v gotestsum)" -- ${TESTDIRS:-./e2e/...} ${TESTFLAGS-}
}

View File

@ -12,7 +12,7 @@ require (
github.com/creack/pty v1.1.21
github.com/distribution/reference v0.5.0
github.com/docker/distribution v2.8.3+incompatible
github.com/docker/docker v25.0.0+incompatible
github.com/docker/docker v25.0.2+incompatible
github.com/docker/docker-credential-helpers v0.8.1
github.com/docker/go-connections v0.5.0
github.com/docker/go-units v0.5.0

View File

@ -54,8 +54,8 @@ github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v25.0.0+incompatible h1:g9b6wZTblhMgzOT2tspESstfw6ySZ9kdm94BLDKaZac=
github.com/docker/docker v25.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v25.0.2+incompatible h1:/OaKeauroa10K4Nqavw4zlhcDq/WBcPMc5DbjOGgozY=
github.com/docker/docker v25.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.8.1 h1:j/eKUktUltBtMzKqmfLB0PAgqYyMHOp5vfsD1807oKo=
github.com/docker/docker-credential-helpers v0.8.1/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M=
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=

View File

@ -12,7 +12,7 @@ import (
// urlPathWithFragmentSuffix matches fragments to use as Git reference and build
// context from the Git repository. See IsGitURL for details.
var urlPathWithFragmentSuffix = regexp.MustCompile(".git(?:#.+)?$")
var urlPathWithFragmentSuffix = regexp.MustCompile(`\.git(?:#.+)?$`)
// IsURL returns true if the provided str is an HTTP(S) URL by checking if it
// has a http:// or https:// scheme. No validation is performed to verify if the

18
vendor/github.com/docker/docker/pkg/system/xattrs.go generated vendored Normal file
View File

@ -0,0 +1,18 @@
package system // import "github.com/docker/docker/pkg/system"
type XattrError struct {
Op string
Attr string
Path string
Err error
}
func (e *XattrError) Error() string { return e.Op + " " + e.Attr + " " + e.Path + ": " + e.Err.Error() }
func (e *XattrError) Unwrap() error { return e.Err }
// Timeout reports whether this error represents a timeout.
func (e *XattrError) Timeout() bool {
t, ok := e.Err.(interface{ Timeout() bool })
return ok && t.Timeout()
}

View File

@ -1,8 +1,6 @@
package system // import "github.com/docker/docker/pkg/system"
import (
"io/fs"
"golang.org/x/sys/unix"
)
@ -10,8 +8,8 @@ import (
// and associated with the given path in the file system.
// It will returns a nil slice and nil error if the xattr is not set.
func Lgetxattr(path string, attr string) ([]byte, error) {
pathErr := func(err error) ([]byte, error) {
return nil, &fs.PathError{Op: "lgetxattr", Path: path, Err: err}
sysErr := func(err error) ([]byte, error) {
return nil, &XattrError{Op: "lgetxattr", Attr: attr, Path: path, Err: err}
}
// Start with a 128 length byte array
@ -22,7 +20,7 @@ func Lgetxattr(path string, attr string) ([]byte, error) {
// Buffer too small, use zero-sized buffer to get the actual size
sz, errno = unix.Lgetxattr(path, attr, []byte{})
if errno != nil {
return pathErr(errno)
return sysErr(errno)
}
dest = make([]byte, sz)
sz, errno = unix.Lgetxattr(path, attr, dest)
@ -32,7 +30,7 @@ func Lgetxattr(path string, attr string) ([]byte, error) {
case errno == unix.ENODATA:
return nil, nil
case errno != nil:
return pathErr(errno)
return sysErr(errno)
}
return dest[:sz], nil
@ -43,7 +41,7 @@ func Lgetxattr(path string, attr string) ([]byte, error) {
func Lsetxattr(path string, attr string, data []byte, flags int) error {
err := unix.Lsetxattr(path, attr, data, flags)
if err != nil {
return &fs.PathError{Op: "lsetxattr", Path: path, Err: err}
return &XattrError{Op: "lsetxattr", Attr: attr, Path: path, Err: err}
}
return nil
}

2
vendor/modules.txt vendored
View File

@ -53,7 +53,7 @@ github.com/docker/distribution/registry/client/transport
github.com/docker/distribution/registry/storage/cache
github.com/docker/distribution/registry/storage/cache/memory
github.com/docker/distribution/uuid
# github.com/docker/docker v25.0.0+incompatible
# github.com/docker/docker v25.0.2+incompatible
## explicit
github.com/docker/docker/api
github.com/docker/docker/api/types