diff --git a/go.mod b/go.mod
index 24d06871bf9f..d2461c3145e6 100644
--- a/go.mod
+++ b/go.mod
@@ -16,9 +16,9 @@ require (
github.com/containerd/typeurl/v2 v2.2.0
github.com/creack/pty v1.1.21
github.com/distribution/reference v0.6.0
- github.com/docker/cli v27.2.1+incompatible
+ github.com/docker/cli v27.2.2-0.20240913085431-48a2cdff970d+incompatible // 27.x branch / v27.3.0-dev
github.com/docker/cli-docs-tool v0.8.0
- github.com/docker/docker v27.2.1+incompatible
+ github.com/docker/docker v27.2.2-0.20240912213415-bf60e5cced83+incompatible // 27.x branch / v27.3.0-dev
github.com/docker/go-units v0.5.0
github.com/gofrs/flock v0.12.1
github.com/gogo/protobuf v1.3.2
diff --git a/go.sum b/go.sum
index ba0c1181ea1d..8d03d7093685 100644
--- a/go.sum
+++ b/go.sum
@@ -124,15 +124,15 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
-github.com/docker/cli v27.2.1+incompatible h1:U5BPtiD0viUzjGAjV1p0MGB8eVA3L3cbIrnyWmSJI70=
-github.com/docker/cli v27.2.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
+github.com/docker/cli v27.2.2-0.20240913085431-48a2cdff970d+incompatible h1:jbTJwvM0LKQUti9X1KfPCnRasE5894IGaqs5Y90YeXM=
+github.com/docker/cli v27.2.2-0.20240913085431-48a2cdff970d+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli-docs-tool v0.8.0 h1:YcDWl7rQJC3lJ7WVZRwSs3bc9nka97QLWfyJQli8yJU=
github.com/docker/cli-docs-tool v0.8.0/go.mod h1:8TQQ3E7mOXoYUs811LiPdUnAhXrcVsBIrW21a5pUbdk=
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 v27.2.1+incompatible h1:fQdiLfW7VLscyoeYEBz7/J8soYFDZV1u6VW6gJEjNMI=
-github.com/docker/docker v27.2.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/docker v27.2.2-0.20240912213415-bf60e5cced83+incompatible h1:OFHR9jugd3jgcQSzqynMgPecxBnmfnq3u8/Fh14Vh2U=
+github.com/docker/docker v27.2.2-0.20240912213415-bf60e5cced83+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo=
github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M=
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=
diff --git a/vendor/github.com/docker/cli/cli/command/telemetry_docker.go b/vendor/github.com/docker/cli/cli/command/telemetry_docker.go
index 94ab3a3929dd..8c50dc3ef68e 100644
--- a/vendor/github.com/docker/cli/cli/command/telemetry_docker.go
+++ b/vendor/github.com/docker/cli/cli/command/telemetry_docker.go
@@ -5,9 +5,14 @@ package command
import (
"context"
+ "fmt"
+ "io/fs"
"net/url"
"os"
"path"
+ "path/filepath"
+ "strings"
+ "unicode"
"github.com/pkg/errors"
"go.opentelemetry.io/otel"
@@ -77,14 +82,7 @@ func dockerExporterOTLPEndpoint(cli Cli) (endpoint string, secure bool) {
switch u.Scheme {
case "unix":
- // Unix sockets are a bit weird. OTEL seems to imply they
- // can be used as an environment variable and are handled properly,
- // but they don't seem to be as the behavior of the environment variable
- // is to strip the scheme from the endpoint, but the underlying implementation
- // needs the scheme to use the correct resolver.
- //
- // We'll just handle this in a special way and add the unix:// back to the endpoint.
- endpoint = "unix://" + path.Join(u.Host, u.Path)
+ endpoint = unixSocketEndpoint(u)
case "https":
secure = true
fallthrough
@@ -135,3 +133,109 @@ func dockerMetricExporter(ctx context.Context, cli Cli) []sdkmetric.Option {
}
return []sdkmetric.Option{sdkmetric.WithReader(newCLIReader(exp))}
}
+
+// unixSocketEndpoint converts the unix scheme from URL to
+// an OTEL endpoint that can be used with the OTLP exporter.
+//
+// The OTLP exporter handles unix sockets in a strange way.
+// It seems to imply they can be used as an environment variable
+// and are handled properly, but they don't seem to be as the behavior
+// of the environment variable is to strip the scheme from the endpoint
+// while the underlying implementation needs the scheme to use the
+// correct resolver.
+func unixSocketEndpoint(u *url.URL) string {
+ // GRPC does not allow host to be used.
+ socketPath := u.Path
+
+ // If we are on windows and we have an absolute path
+ // that references a letter drive, check to see if the
+ // WSL equivalent path exists and we should use that instead.
+ if isWsl() {
+ if p := wslSocketPath(socketPath, os.DirFS("/")); p != "" {
+ socketPath = p
+ }
+ }
+ // Enforce that we are using forward slashes.
+ return "unix://" + filepath.ToSlash(socketPath)
+}
+
+// wslSocketPath will convert the referenced URL to a WSL-compatible
+// path and check if that path exists. If the path exists, it will
+// be returned.
+func wslSocketPath(s string, f fs.FS) string {
+ if p := toWslPath(s); p != "" {
+ if _, err := stat(p, f); err == nil {
+ return "/" + p
+ }
+ }
+ return ""
+}
+
+// toWslPath converts the referenced URL to a WSL-compatible
+// path if this looks like a Windows absolute path.
+//
+// If no drive is in the URL, defaults to the C drive.
+func toWslPath(s string) string {
+ drive, p, ok := parseUNCPath(s)
+ if !ok {
+ return ""
+ }
+ return fmt.Sprintf("mnt/%s%s", drive, p)
+}
+
+func parseUNCPath(s string) (drive, p string, ok bool) {
+ // UNC paths use backslashes but we're using forward slashes
+ // so also enforce that here.
+ //
+ // In reality, this should have been enforced much earlier
+ // than here since backslashes aren't allowed in URLs, but
+ // we're going to code defensively here.
+ s = filepath.ToSlash(s)
+
+ const uncPrefix = "//./"
+ if !strings.HasPrefix(s, uncPrefix) {
+ // Not a UNC path.
+ return "", "", false
+ }
+ s = s[len(uncPrefix):]
+
+ parts := strings.SplitN(s, "/", 2)
+ if len(parts) != 2 {
+ // Not enough components.
+ return "", "", false
+ }
+
+ drive, ok = splitWindowsDrive(parts[0])
+ if !ok {
+ // Not a windows drive.
+ return "", "", false
+ }
+ return drive, "/" + parts[1], true
+}
+
+// splitWindowsDrive checks if the string references a windows
+// drive (such as c:) and returns the drive letter if it is.
+func splitWindowsDrive(s string) (string, bool) {
+ if b := []rune(s); len(b) == 2 && unicode.IsLetter(b[0]) && b[1] == ':' {
+ return string(b[0]), true
+ }
+ return "", false
+}
+
+func stat(p string, f fs.FS) (fs.FileInfo, error) {
+ if f, ok := f.(fs.StatFS); ok {
+ return f.Stat(p)
+ }
+
+ file, err := f.Open(p)
+ if err != nil {
+ return nil, err
+ }
+
+ defer file.Close()
+ return file.Stat()
+}
+
+func isWsl() bool {
+ return os.Getenv("WSL_DISTRO_NAME") != ""
+}
diff --git a/vendor/github.com/docker/docker/api/swagger.yaml b/vendor/github.com/docker/docker/api/swagger.yaml
index 69ad8a37df6f..7164e1eba53d 100644
--- a/vendor/github.com/docker/docker/api/swagger.yaml
+++ b/vendor/github.com/docker/docker/api/swagger.yaml
@@ -393,7 +393,7 @@ definitions:
Make the mount non-recursively read-only, but still leave the mount recursive
(unless NonRecursive is set to `true` in conjunction).
- Addded in v1.44, before that version all read-only mounts were
+ Added in v1.44, before that version all read-only mounts were
non-recursive by default. To match the previous behaviour this
will default to `true` for clients on versions prior to v1.44.
type: "boolean"
@@ -1384,7 +1384,7 @@ definitions:
> **Deprecated**: this field is not part of the image specification and is
- > always empty. It must not be used, and will be removed in API v1.47.
+ > always empty. It must not be used, and will be removed in API v1.48.
type: "string"
example: ""
Domainname:
@@ -1394,7 +1394,7 @@ definitions:
> **Deprecated**: this field is not part of the image specification and is
- > always empty. It must not be used, and will be removed in API v1.47.
+ > always empty. It must not be used, and will be removed in API v1.48.
type: "string"
example: ""
User:
@@ -1408,7 +1408,7 @@ definitions:
> **Deprecated**: this field is not part of the image specification and is
- > always false. It must not be used, and will be removed in API v1.47.
+ > always false. It must not be used, and will be removed in API v1.48.
type: "boolean"
default: false
example: false
@@ -1419,7 +1419,7 @@ definitions:
> **Deprecated**: this field is not part of the image specification and is
- > always false. It must not be used, and will be removed in API v1.47.
+ > always false. It must not be used, and will be removed in API v1.48.
type: "boolean"
default: false
example: false
@@ -1430,7 +1430,7 @@ definitions:
> **Deprecated**: this field is not part of the image specification and is
- > always false. It must not be used, and will be removed in API v1.47.
+ > always false. It must not be used, and will be removed in API v1.48.
type: "boolean"
default: false
example: false
@@ -1457,7 +1457,7 @@ definitions:
> **Deprecated**: this field is not part of the image specification and is
- > always false. It must not be used, and will be removed in API v1.47.
+ > always false. It must not be used, and will be removed in API v1.48.
type: "boolean"
default: false
example: false
@@ -1468,7 +1468,7 @@ definitions:
> **Deprecated**: this field is not part of the image specification and is
- > always false. It must not be used, and will be removed in API v1.47.
+ > always false. It must not be used, and will be removed in API v1.48.
type: "boolean"
default: false
example: false
@@ -1479,7 +1479,7 @@ definitions:
> **Deprecated**: this field is not part of the image specification and is
- > always false. It must not be used, and will be removed in API v1.47.
+ > always false. It must not be used, and will be removed in API v1.48.
type: "boolean"
default: false
example: false
@@ -1516,7 +1516,7 @@ definitions:
> **Deprecated**: this field is not part of the image specification and is
- > always empty. It must not be used, and will be removed in API v1.47.
+ > always empty. It must not be used, and will be removed in API v1.48.
type: "string"
default: ""
example: ""
@@ -1555,7 +1555,7 @@ definitions:
> **Deprecated**: this field is not part of the image specification and is
- > always omitted. It must not be used, and will be removed in API v1.47.
+ > always omitted. It must not be used, and will be removed in API v1.48.
type: "boolean"
default: false
example: false
@@ -1567,7 +1567,7 @@ definitions:
> **Deprecated**: this field is not part of the image specification and is
- > always omitted. It must not be used, and will be removed in API v1.47.
+ > always omitted. It must not be used, and will be removed in API v1.48.
type: "string"
default: ""
example: ""
@@ -1601,7 +1601,7 @@ definitions:
> **Deprecated**: this field is not part of the image specification and is
- > always omitted. It must not be used, and will be removed in API v1.47.
+ > always omitted. It must not be used, and will be removed in API v1.48.
type: "integer"
default: 10
x-nullable: true
@@ -2216,7 +2216,7 @@ definitions:
Created:
description: |
Date and time at which the image was created as a Unix timestamp
- (number of seconds sinds EPOCH).
+ (number of seconds since EPOCH).
type: "integer"
x-nullable: false
example: "1644009612"
@@ -2513,7 +2513,7 @@ definitions:
example: false
Attachable:
description: |
- Wheter a global / swarm scope network is manually attachable by regular
+ Whether a global / swarm scope network is manually attachable by regular
containers from workers in swarm mode.
type: "boolean"
default: false
@@ -3736,7 +3736,7 @@ definitions:
example: "json-file"
Options:
description: |
- Driver-specific options for the selectd log driver, specified
+ Driver-specific options for the selected log driver, specified
as key/value pairs.
type: "object"
additionalProperties:
@@ -7712,7 +7712,7 @@ paths:
* Memory usage % = `(used_memory / available_memory) * 100.0`
* cpu_delta = `cpu_stats.cpu_usage.total_usage - precpu_stats.cpu_usage.total_usage`
* system_cpu_delta = `cpu_stats.system_cpu_usage - precpu_stats.system_cpu_usage`
- * number_cpus = `lenght(cpu_stats.cpu_usage.percpu_usage)` or `cpu_stats.online_cpus`
+ * number_cpus = `length(cpu_stats.cpu_usage.percpu_usage)` or `cpu_stats.online_cpus`
* CPU usage % = `(cpu_delta / system_cpu_delta) * number_cpus * 100.0`
operationId: "ContainerStats"
produces: ["application/json"]
@@ -9226,12 +9226,23 @@ paths:
parameters:
- name: "name"
in: "path"
- description: "Image name or ID."
+ description: |
+ Name of the image to push. For example, `registry.example.com/myimage`.
+ The image must be present in the local image store with the same name.
+
+ The name should be provided without tag; if a tag is provided, it
+ is ignored. For example, `registry.example.com/myimage:latest` is
+ considered equivalent to `registry.example.com/myimage`.
+
+ Use the `tag` parameter to specify the tag to push.
type: "string"
required: true
- name: "tag"
in: "query"
- description: "The tag to associate with the image on the registry."
+ description: |
+ Tag of the image to push. For example, `latest`. If no tag is provided,
+ all tags of the given image that are present in the local image store
+ are pushed.
type: "string"
- name: "X-Registry-Auth"
in: "header"
diff --git a/vendor/github.com/docker/docker/api/types/filters/parse.go b/vendor/github.com/docker/docker/api/types/filters/parse.go
index 0c39ab5f18b5..0914b2a4410c 100644
--- a/vendor/github.com/docker/docker/api/types/filters/parse.go
+++ b/vendor/github.com/docker/docker/api/types/filters/parse.go
@@ -196,7 +196,7 @@ func (args Args) Match(field, source string) bool {
}
// 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.
+// and is interpretable 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]
diff --git a/vendor/github.com/docker/docker/api/types/image/summary.go b/vendor/github.com/docker/docker/api/types/image/summary.go
index c7168fe62eab..e87e216a28b3 100644
--- a/vendor/github.com/docker/docker/api/types/image/summary.go
+++ b/vendor/github.com/docker/docker/api/types/image/summary.go
@@ -12,7 +12,7 @@ type Summary struct {
Containers int64 `json:"Containers"`
// Date and time at which the image was created as a Unix timestamp
- // (number of seconds sinds EPOCH).
+ // (number of seconds since EPOCH).
//
// Required: true
Created int64 `json:"Created"`
diff --git a/vendor/github.com/docker/docker/api/types/swarm/swarm.go b/vendor/github.com/docker/docker/api/types/swarm/swarm.go
index 3eae4b9b297d..1b4be6fffbab 100644
--- a/vendor/github.com/docker/docker/api/types/swarm/swarm.go
+++ b/vendor/github.com/docker/docker/api/types/swarm/swarm.go
@@ -122,7 +122,7 @@ type CAConfig struct {
SigningCAKey string `json:",omitempty"`
// If this value changes, and there is no specified signing cert and key,
- // then the swarm is forced to generate a new root certificate ane key.
+ // then the swarm is forced to generate a new root certificate and key.
ForceRotate uint64 `json:",omitempty"`
}
diff --git a/vendor/github.com/docker/docker/api/types/volume/cluster_volume.go b/vendor/github.com/docker/docker/api/types/volume/cluster_volume.go
index bbd9ff0b8f97..618a4816209a 100644
--- a/vendor/github.com/docker/docker/api/types/volume/cluster_volume.go
+++ b/vendor/github.com/docker/docker/api/types/volume/cluster_volume.go
@@ -414,7 +414,7 @@ type Info struct {
// the Volume has not been successfully created yet.
VolumeID string `json:",omitempty"`
- // AccessibleTopolgoy is the topology this volume is actually accessible
+ // AccessibleTopology is the topology this volume is actually accessible
// from.
AccessibleTopology []Topology `json:",omitempty"`
}
diff --git a/vendor/github.com/docker/docker/pkg/jsonmessage/jsonmessage.go b/vendor/github.com/docker/docker/pkg/jsonmessage/jsonmessage.go
index 035160c834e4..8d2c8857fb03 100644
--- a/vendor/github.com/docker/docker/pkg/jsonmessage/jsonmessage.go
+++ b/vendor/github.com/docker/docker/pkg/jsonmessage/jsonmessage.go
@@ -290,7 +290,7 @@ func DisplayJSONMessagesStream(in io.Reader, out io.Writer, terminalFd uintptr,
}
// Stream is an io.Writer for output with utilities to get the output's file
-// descriptor and to detect wether it's a terminal.
+// descriptor and to detect whether it's a terminal.
//
// it is subset of the streams.Out type in
// https://pkg.go.dev/github.com/docker/cli@v20.10.17+incompatible/cli/streams#Out
diff --git a/vendor/github.com/docker/docker/pkg/pools/pools.go b/vendor/github.com/docker/docker/pkg/pools/pools.go
index 3792c67a9e45..3ea3012b188b 100644
--- a/vendor/github.com/docker/docker/pkg/pools/pools.go
+++ b/vendor/github.com/docker/docker/pkg/pools/pools.go
@@ -124,7 +124,7 @@ func (bufPool *BufioWriterPool) Put(b *bufio.Writer) {
}
// NewWriteCloserWrapper returns a wrapper which puts the bufio.Writer back
-// into the pool and closes the writer if it's an io.Writecloser.
+// into the pool and closes the writer if it's an io.WriteCloser.
func (bufPool *BufioWriterPool) NewWriteCloserWrapper(buf *bufio.Writer, w io.Writer) io.WriteCloser {
return ioutils.NewWriteCloserWrapper(w, func() error {
buf.Flush()
diff --git a/vendor/github.com/docker/docker/pkg/system/xattrs_linux.go b/vendor/github.com/docker/docker/pkg/system/xattrs_linux.go
index facfbb3126f1..b877ecc5a942 100644
--- a/vendor/github.com/docker/docker/pkg/system/xattrs_linux.go
+++ b/vendor/github.com/docker/docker/pkg/system/xattrs_linux.go
@@ -6,7 +6,7 @@ import (
// Lgetxattr retrieves the value of the extended attribute identified by attr
// 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.
+// It returns a nil slice and nil error if the xattr is not set.
func Lgetxattr(path string, attr string) ([]byte, error) {
sysErr := func(err error) ([]byte, error) {
return nil, &XattrError{Op: "lgetxattr", Attr: attr, Path: path, Err: err}
diff --git a/vendor/github.com/docker/docker/registry/config.go b/vendor/github.com/docker/docker/registry/config.go
index 84b0a63ad25b..e1b0a0ca14c6 100644
--- a/vendor/github.com/docker/docker/registry/config.go
+++ b/vendor/github.com/docker/docker/registry/config.go
@@ -359,7 +359,7 @@ func hasScheme(reposName string) bool {
}
func validateHostPort(s string) error {
- // Split host and port, and in case s can not be splitted, assume host only
+ // Split host and port, and in case s can not be split, assume host only
host, port, err := net.SplitHostPort(s)
if err != nil {
host = s
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 5a6508133f41..99dd366bc91d 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -218,7 +218,7 @@ github.com/davecgh/go-spew/spew
# github.com/distribution/reference v0.6.0
## explicit; go 1.20
github.com/distribution/reference
-# github.com/docker/cli v27.2.1+incompatible
+# github.com/docker/cli v27.2.2-0.20240913085431-48a2cdff970d+incompatible
## explicit
github.com/docker/cli/cli
github.com/docker/cli/cli-plugins/hooks
@@ -270,7 +270,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 v27.2.1+incompatible
+# github.com/docker/docker v27.2.2-0.20240912213415-bf60e5cced83+incompatible
## explicit
github.com/docker/docker/api
github.com/docker/docker/api/types